Architecture
Separation of Concerns
Dividing a system into distinct sections, each addressing a single responsibility.
Overview
Separation of Concerns (SoC) divides a system into distinct sections, each addressing a separate concern, so changes to one do not cascade into others. A concern is any aspect of a program's function, rendering, persistence, validation, authentication, business logic. Code that mixes concerns becomes tightly coupled and hard to change.
Origin
Coined by Edsger Dijkstra in "On the Role of Scientific Thought" (1974). The principle is foundational to software engineering and appears in every major architectural pattern as the underlying motivation.
Examples
MVC as separation of concerns
# Violation: controller that does everything
class OrdersController < ApplicationController
def create
# Concern 1: HTTP input parsing (ok for controller)
attrs = params.require(:order).permit(:product_id, :quantity)
# Concern 2: Business logic (belongs in domain model or service)
product = Product.find(attrs[:product_id])
raise "Out of stock" if product.stock < attrs[:quantity].to_i
total = product.price * attrs[:quantity].to_i
# Concern 3: Persistence
@order = Order.create!(attrs.merge(total: total))
# Concern 4: Side effects (belongs in a service or job)
InventoryService.deduct(product, attrs[:quantity].to_i)
OrderMailer.confirmation(@order).deliver_later
render json: @order
end
end
# Each concern in its own layer
class OrdersController < ApplicationController
def create
result = PlaceOrder.new.call(params: order_params, user: current_user)
render json: result.order, status: :created
end
endUse Cases
- 01MVC/MVVM: separating data, business logic, and presentation so each can vary independently
- 02CSS modules: isolating component styles so they cannot leak or conflict
- 03Middleware pipelines: each middleware handles one cross-cutting concern (logging, auth, compression)
- 04Database access layer: queries isolated from business logic so the persistence mechanism can change
When Not to Use
- //Over-separating trivial code into many small files increases navigation cost for no benefit
- //Premature separation before the concerns are well-understood leads to the wrong boundaries
Technical Notes
- SoC is a guiding principle, not a prescriptive pattern. The number of layers and where boundaries fall depends on the system's complexity
- The test for good separation: if you need to change concern A, do you need to modify files that belong to concern B?
- Feature-based organisation (group by domain concept) can have better SoC than layer-based organisation (group by technical role) in large applications
More in Architecture
SOLID PrinciplesDesign PatternsClean & Hexagonal ArchitectureDependency InjectionEvent SourcingCQRSRepository PatternStrangler Fig PatternFeature FlagsMicroservicesLoad BalancingMessage Queues & Pub/SubDistributed SystemsCAP TheoremDatabase Sharding & ReplicationAPI Gateway PatternService MeshCircuit Breaker PatternSaga PatternBlue-Green DeploymentCanary ReleasesServerless Architecture