GRASP
Nine questions for deciding which object should own which responsibility.
What you will learn
- 01Assigning responsibilities
- 02Information Expert and Creator
- 03Controller
- 04Low coupling and high cohesion
- 05Four more tools
- 06Using GRASP
Assigning responsibilities
Designing objects comes down to one repeated decision: who is responsible for this? GRASP, short for General Responsibility Assignment Software Patterns, is a set of nine rules of thumb for answering it. They matter most when you start modeling a problem like our parking lot, where dozens of small duties must each find a home.
Swipe sideways to pan · drag a box to move it
Information Expert and Creator
Information Expert: give a responsibility to the object that already has the information needed. To compute how long a car has stayed, the Ticket knows when it entered, so the Ticket should answer minutesParked(now). Putting that logic elsewhere forces others to reach in and pull data out.
Creator: give the job of creating B to the object that contains B, records B, or closely uses B. The ParkingLot holds the tickets, so the lot creates them.
Swipe sideways to pan · drag a box to move it
Controller
Something must receive a request from outside, such as a button press or an API call, and decide what to do. A Controller is the first object past the interface layer that coordinates the work. It should delegate, not do the work itself.
class EntryGate {
constructor(private lot: ParkingLot) {}
handle(plate: string, now: number) { return this.lot.enter(plate, now); }
}
A controller that grows its own rules becomes a bloated class. Keep it thin.
Swipe sideways to pan · drag a box to move it
Low coupling and high cohesion
These are the two yardsticks for judging any assignment.
- Low coupling: an object should know few others, and only through simple connections. Fewer dependencies mean fewer ripples when something changes.
- High cohesion: everything in an object should serve one focused purpose.
When two options both work, pick the one with lower coupling and higher cohesion.
Four more tools
- Polymorphism: when behavior varies by type, give each type its own version instead of branching on the type.
- Pure Fabrication: if no domain object fits a duty without hurting cohesion, invent a class for it, such as a
TicketRepository. It does not exist in the real world, and that is fine. - Indirection: add a middle object to keep two parts from knowing each other directly.
- Protected Variations: find the point where change is likely and put a stable interface in front of it.
Using GRASP
Ask in order. Who has the data? Who contains or records these things? Who receives the request? Then check the result for coupling and cohesion. Each answer is a tradeoff. Moving a duty to the expert may couple two classes, and a fabrication adds a class to read. Choose the option you will be glad of when the next requirement arrives.