Design Principles
GRASP: where does the job live?
SOLID tells you that a pricing class should not also write SQL. It does not tell you whether Ticket, ParkingLot, or PricingStrategy should compute the fee. GRASP fills that gap: it is a set of principles for deciding where a responsibility belongs.
You do not need to memorize all nine GRASP names for an interview. Information Expert, Creator, Controller, low coupling, high cohesion, and Protected Variations cover almost every machine-coding follow-up. First place the job. Then name the pattern if it helps.
Ask in this order
- 1
Name the job: compute a fee, create a ticket, allocate a spot, park a car.
- 2
Who already has the data? Start with Information Expert.
- 3
Who contains or records the new object? That is Creator.
- 4
Who receives the system operation from the outside world? That is Controller.
- 5
What will vary over time? Hide it behind a stable interface — Protected Variations.
Who calculates parking fees?
That question is the classic GRASP interview prompt. Ticket knows the time bounds. PricingStrategy knows the pricing policy. A controller asks both of them at exit. ParkingSpot knows occupancy, not GST. Saying “I will use the Strategy pattern” without answering who owns duration and who owns policy is cargo cult. Strategy is how you vary a job that already has a home. GRASP is how you choose that home.
A Manager that asks every object for fields is a last resort, not a default. If you skip Expert and dump every verb onto ParkingService, you get a God object wearing a GRASP label. A controller is a thin use-case object, not a dumping ground for every rule.
Placement board
Five candidates, one honest home
Ticket
Has: entry time, exit time, vehicle type
Expert for duration. Not expert for GST policy.
ParkingSpot
Has: occupancy, size, charger
Expert for whether this car can sit here. Not expert for money.
ParkingLot
Has: floors, the list of tickets
Coordinates the lot. Should not own tax rules.
PricingStrategy
Has: the varying formula
Expert for the pricing policy. Ask Ticket for duration.
Controller
Has: the system operation “exit”
Asks Ticket and Strategy at checkout. Does not become the formula.
The handful of names you actually use
Information Expert
Give the job to the object that has the data. Ticket.hoursParked(clock) belongs on Ticket. The fee formula belongs on a strategy because the policy is the data that varies. See Information Expert.
Creator
The object that contains, records, or closely uses another object should create it. ParkingLot records tickets, so ParkingLot creates Ticket — not TicketUtil. A factory appears only when the concrete type itself varies. See Creator.
Controller
A use-case object receives park, exit, and pay. The gate button does not. Ticket does not become the whole application. Keep the controller thin: load collaborators, ask experts, save results, and return. See Controller.
Low coupling, high cohesion
A change in one place should not ripple through the design. A class should be about one thing. Extracting PricingStrategy raises cohesion in the lot and lowers coupling to the current fee formula. See cohesion and coupling.
Protected Variations
Find the unstable part — pricing, allocation, payment — and hide it behind a stable interface. Open-Closed is the SOLID name for living with that abstraction: clients depend on the strategy interface, not on one concrete formula. See Protected Variations.
Java: place the fee, then vary it
Duration lives on Ticket. Policy lives on PricingStrategy. ExitService is the controller that asks both. ParkingLot is not in this method. Spot is not in this method. That is GRASP expressed as code, not as a list of pattern names.
class Ticket {
private final Instant enteredAt;
private Instant exitedAt;
private final VehicleType vehicleType;
private final Money hourlyRate;
Duration parked(Clock clock) {
Instant end = exitedAt != null ? exitedAt : clock.instant();
return Duration.between(enteredAt, end);
}
VehicleType vehicleType() { return vehicleType; }
Money hourlyRate() { return hourlyRate; }
}
interface PricingStrategy {
Money fee(Ticket ticket, Clock clock);
}
class HourlyPricing implements PricingStrategy {
public Money fee(Ticket ticket, Clock clock) {
long seconds = ticket.parked(clock).getSeconds();
if (seconds < 0) throw new IllegalArgumentException("negative stay");
long hours = Math.max(1, seconds / 3600 + (seconds % 3600 == 0 ? 0 : 1));
return ticket.hourlyRate().times(hours);
}
}
class ExitService {
private final PricingStrategy pricing;
private final TicketRepository tickets;
Money handle(TicketId id, Clock clock) {
Ticket ticket = tickets.find(id).orElseThrow();
ticket.close(clock.instant());
Money due = pricing.fee(ticket, clock);
tickets.save(ticket);
return due;
}
}SOLID places nothing; GRASP places, SOLID keeps
SOLID keeps a placement cheap when the next vehicle type arrives. It does not choose Ticket versus Strategy. If you only recite SOLID, you can still put GST on ParkingSpot. If you only recite GRASP, you can still let the expert grow a second job. Use Expert to place duration on Ticket. Use Single Responsibility to keep SMS off Ticket. Use Protected Variations and Open-Closed to put the formula behind a strategy interface.
In an interview, defaulting to Strategy without asking who holds time and who holds policy is a common skip. “I will use Strategy for fees” never answered the placement question. Ask first. Then, if two policies are in play, Strategy is the stable interface for that variation — not a substitute for placing the job.
Who creates the ticket?
ParkingLot records the stay, so ParkingLot creates Ticket. That is Creator. TicketFactory is only justified if the ticket type itself varies — long-stay versus hourly, or validation tickets versus paid tickets. Most rounds have one Ticket class. new Ticket(...) next to the lot that stores it is enough.
The controller may call lot.enter(...), which creates and records the ticket. The controller should not also call new Ticket while the lot keeps a list — then two owners both feel like creators, and the reference lives in the wrong place. Pick the object that will hold the child after construction.
Dumping every verb on a Service
A ParkingService that creates, prices, allocates, and persists is not a controller. It is a God object wearing a GRASP name. A real controller receives one system operation and asks collaborators. If you cannot name the use case — park, exit, pay — you are not ready to name the controller. Start from the verbs. Those names become the class or method names. See use cases and assigning responsibilities.
A two-minute placement script
Write the verbs: park, exit, pay. For each verb, write the facts it needs. For each fact, write who already stores it. Draw arrows from the controller to the experts, not from a Manager to everyone. Circle what will vary. Hide those reasons to change behind stable interfaces. That is the whole GRASP round. Pattern names, if they appear, are labels on those abstractions.
If the interviewer asks “why not put fee on Ticket?”, answer with Expert: Ticket does not have GST. If they ask “why not put fee on ParkingLot?”, answer with cohesion: the lot should not reopen when tax rules change. If they ask “why Strategy?”, answer with Protected Variations: because a second policy is a likely follow-up. Those three answers are GRASP doing real work.
The rest of the map
The nine names, and which you can skip
Full GRASP also lists Polymorphism, Indirection, and Pure Fabrication. Polymorphism means let the subtype answer, which you already do with strategies. Indirection means put an abstraction between clients and the varying part, which is Protected Variations. Pure Fabrication is a class with no domain noun — PricingStrategy is one — invented so Expert and cohesion still hold. You do not need to recite those three in a round if you already placed the fee and hid the variation behind a stable interface. Recite them only if the interviewer asks where Strategy sits in GRASP: it is fabrication plus polymorphism plus protected variation, for a job Expert already found.
Place first, pattern second, in one breath
“Ticket has times, so Ticket.parked. Policy varies, so PricingStrategy. ExitService asks both. ParkingLot creates the ticket because it records stays.” That paragraph is Expert, Protected Variations, Controller, and Creator. You never needed to say GRASP as a word. The interviewer heard placement. That is this overview’s job: give you the paragraph, then the named pages if you want depth.
How to explain this in an interview
Give the placement paragraph, then stop. If the interviewer wants depth, they will ask who creates the ticket or how you would add airport rates. You already have Creator and Protected Variations ready. Dumping all nine GRASP names up front wastes the minutes you need for the object model. Placement is the product; the vocabulary is the tool.
Takeaway
GRASP answers where the job lives. Expert has the data. Creator records the new object. Controller receives the system operation. Protected Variations hides what will change behind a stable interface. SOLID then keeps that placement from rotting. Do not default to Strategy, and do not dump every verb on a Service.