Separation of Concerns
Split a program along its concerns, and let no concern know how another one does its job.
Encapsulate What Varies tells you to wall off the part of a class that changes from the part that doesn't. Separation of Concerns is the older, blunter ancestor of that idea: split any program, not just a single class, into pieces where each piece answers exactly one question, and none of them has to understand another's job to do its own.
Why it exists
Picture an OrderImportJob that reads a CSV off disk, parses each row into an Order,
checks that the totals add up, and writes the survivors to the database, all inside one
run() method. It works, right up until the file format changes, or validation needs a new
rule, or storage swaps from a database to a queue. Every one of those changes touches the
same method, because the method never separated "where the bytes come from" from "what a
valid row looks like" from "where a valid row goes." A bug in date parsing sends you into a
method that also happens to open sockets and write SQL, and you have to read all of it to
trust that your fix to one concern didn't disturb another.
Four questions, four owners
Split each question into its own object and each one gets a name that describes exactly what it does and nothing else.
None of the four new classes got smaller in total - the line count barely moved. What changed is that a bug in date parsing now points you at one file with one job, instead of a grep through a method that also happens to open sockets and write SQL.
Try it yourself: OrderImportJob above still decides when to run and in what order
to call its four collaborators. Is scheduling ("run this nightly at 2am") a fifth concern
that belongs somewhere else too, or is orchestration exactly what OrderImportJob itself
should own? Write down your reasoning before moving on.
The cost of overapplying it
Splitting can go past the point of return. Four single-line classes, each holding one field and delegating to it, can be strictly harder to trace than the one cohesive method they replaced, if the "concerns" being separated were never actually independent questions - just busywork slicing of code that always changes together for the same reason. The test for a real concern is: does this piece have its own reason to change, separate from the others? If splitting a method in two means both halves still change in lockstep every time, you split along the wrong seam.
How it relates to its neighbours
The Single Responsibility Principle, covered later under SOLID, is Separation of Concerns
applied to exactly one class at a time - "a class should have one reason to change" is this
same idea, scoped down. Coupling and Cohesion is the measurement
this split produces: each of the four new classes above is more cohesive on its own than
OrderImportJob was holding all four jobs, and OrderImportJob is now loosely coupled to
each of them, holding only a reference and calling one method.
Where you'll see it in the pattern catalog
Command separates the concern of "what should happen" from "when and how it gets invoked" -
a menu item doesn't need to know how undo works to trigger it. In this site's
additional patterns, Repository is
Separation of Concerns applied specifically to persistence: business logic stops needing to
know how data gets stored, the same move OrderRepository makes above.
Check yourself
An OrderImportJob reads a file, parses it, validates the rows, and saves them to the database, all in one run() method. Which principle explains what to do about it, and which later SOLID principle is the class-level version of the same idea?