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
end

Use 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