Give a case where following GRASP's Information Expert produces a bad design, and name the principle you would apply instead.
answer
- sale.save() is the trap
- Pure Fabrication = invented, non-domain class
- technical concern → override Expert
- cross-aggregate → domain service
- volatile rule → Protected Variations
basics
~20 sSaving an object to a database. A Sale knows all its own data, so Information Expert literally says sale.save(). That would force every domain class to know SQL and transactions. Instead use Pure Fabrication: a SaleRepository invented purely for design reasons.
solid answer
~50 sThe classic counter-example is persistence. Since a Sale holds all of its own data, Information Expert naively elects Sale to save itself. But `sale.save()` drags SQL, connection handling, transactions, and mapping into a domain class: cohesion collapses (the class now has two unrelated jobs), coupling explodes (every entity depends on the database layer), and the logic becomes untestable and unreusable. The overriding GRASP principle is **Pure Fabrication** — invent a class that does not represent a domain concept, such as `SaleRepository`, purely to gain cohesion, low coupling and reuse. Related overrides: **Creator** (who instantiates), **Controller** (who receives system events), **Protected Variations** (put an interface at a point of predicted change), and domain services for cross-aggregate policy. General rule: Information Expert is a *default* for domain logic; it is overridden whenever obeying it would import a technical concern into a domain class or force one class to own information it does not conceptually hold.
go deeper
Name the persistence example: an object knowing its own data does not mean it should know the database. Mention that a repository class handles saving.
Give the persistence case plus the cohesion/coupling/testability reasoning, and name Pure Fabrication as the GRASP principle that overrides it.
Enumerate several override categories (persistence, presentation, cross-aggregate, volatility, performance) and describe a precedence order among GRASP principles, keeping coupling/cohesion as the actual objective.
Frame heuristic conflict as normal, discuss how the chosen overrides shape the architecture (repository vs Active Record, domain services vs aggregates, projections for read paths), and how to make those trade-offs explicit and reversible.
## Restating the tension **Information Expert** says: assign a responsibility to the class holding the information required. Applied blindly, "holding the information" is satisfied by *any* class that owns the bytes — including for tasks whose real difficulty has nothing to do with those bytes. ## Case 1 — Persistence (the textbook one) A `Sale` object knows its id, its line items, its totals, its timestamp. So by literal Expert reasoning, `Sale` should save itself. Why that is wrong: - **Cohesion collapses.** The class now handles domain rules *and* SQL/ORM/connection/transaction concerns — two axes of change in one place, violating the Single Responsibility Principle. - **Coupling explodes.** Every entity gains a dependency on the persistence technology; swapping stores becomes a sweeping change. - **Duplication.** Connection acquisition, retry, batching, and mapping get re-implemented per entity. - **Testability.** Pure domain logic can no longer be unit-tested without a database. The override is **Pure Fabrication**: invent `SaleRepository` (or a generic persistence mapper). "Pure fabrication" literally means a class that exists for *design* reasons rather than because the domain has that noun. Repository, Unit of Work, Data Mapper, Serializer, and Factory are all fabrications in this sense. ## Case 2 — Presentation and protocol An `Invoice` knows its own contents, so "render me as HTML" or "serialize me to JSON with this API version" naively lands on `Invoice`. Same objection: format concerns change for different reasons than invoicing rules, and one domain object should not carry N representations. Overrides: a dedicated view model / presenter / serializer, or a Visitor when many operations over one structure are needed. ## Case 3 — Cross-entity policy A transfer touches two accounts; a shipping-cost rule needs an order, a carrier tariff, and a destination zone. No single class is *the* expert; electing one arbitrarily creates a hidden dependency from that class to everything else. Override: a **domain service** (also a Pure Fabrication) that coordinates, while each entity keeps the part it truly owns. ## Case 4 — Point of predicted variation If tax rules will be swapped per jurisdiction, putting `calculateTax()` directly on `Sale` bakes in a dependency on a volatile rule. **Protected Variations** says wrap the unstable part behind a stable interface (`TaxCalculator`) so change is contained. `Sale` still owns *what* to tax; the *how* is pluggable — this is Expert plus an indirection, not Expert abandoned. ## Case 5 — Information the expert only *appears* to hold A `Report` object might hold the raw rows because someone loaded them into it, but that does not make it the conceptual owner. Expert is about the domain's information model, not about whichever object currently caches the bytes. Deciding by accidental possession leads to god objects. ## Case 6 — Legitimate performance overrides A correct per-object computation may be catastrophically slow in aggregate (the classic N+1 problem: asking each of 10,000 line items for its product's price triggers 10,000 queries). A set-based computation in a repository or a materialized projection may be required. This is a real, defensible override — but it should be a *deliberate, measured* one, and ideally kept behind the expert's method signature so callers still "tell". ## How to answer the meta-question GRASP principles are heuristics that intentionally conflict; part of design skill is knowing the precedence: 1. Start with Information Expert for domain logic. 2. If it imports a technical concern → **Pure Fabrication**. 3. If no single class holds the information → domain service / partial experts. 4. If the responsibility is about receiving a system event → **Controller**. 5. If a volatile dependency is involved → **Protected Variations** / **Indirection**. 6. Sanity-check the result against coupling, cohesion, and testability — those are the objectives that all of the above are proxies for. Saying "Information Expert always wins" is as wrong as never applying it.
- Is the Active Record pattern therefore always wrong, since the entity saves itself?No — it is a conscious trade-off. Active Record accepts the Expert-literal coupling of domain object to table in exchange for a very small amount of code, which pays off in CRUD-shaped apps with a thin domain. It hurts when the domain is rich, when the object model diverges from the schema, or when you need database-free unit tests. Data Mapper/Repository is the alternative that keeps the domain pure at the cost of mapping machinery.
- How do you decide between adding a method to an entity and creating a domain service?Ask what information the rule needs. If it is all inside one aggregate, it belongs on that aggregate. If it needs several aggregates, external data, or a policy that varies independently, a domain service is more honest. A useful check: would putting it on the entity force that entity to hold a reference to something it otherwise has no business knowing? If yes, use a service.
A witness has all the facts about an accident, but you don't ask them to file the court record, run the trial, and archive the paperwork. Owning the information doesn't mean owning every process that touches it.
saying these in an interview costs you the question
- Claiming GRASP principles never conflict, so no precedence reasoning is needed
- Naming the override as "just use a service layer" without articulating cohesion/coupling reasons — this often slides into an anemic model
- Believing Pure Fabrication means any helper/util class is justified; the test is whether it buys cohesion, low coupling, or reuse
- Putting persistence on entities and defending it purely with "Information Expert says so"
- Overriding Expert for imagined performance reasons with no measurement