Suggest an editImprove this articleRefine the answer for “What are grasp patterns”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**GRASP patterns** are nine guidelines for assigning responsibilities to classes in object-oriented design. Core rule: give a task to the class that has the data to fulfill it (Information Expert). Not enforced by compilers, applied during system modeling. **Key point:** GRASP decides who owns what; SOLID and GoF handle class structure and reusable solutions.Shown above the full answer for quick recall.Answer (EN)Image**GRASP** (General Responsibility Assignment Software Patterns) is a set of nine guidelines for deciding which class should own which responsibility in object-oriented design. ## Theory ### TL;DR - Think of GRASP like kitchen roles: the chef (Information Expert) handles recipes because they know the ingredients, not the waiter. - Core idea: give a task to the class that has the data to do it. - Main difference from SOLID: GRASP decides *who does what*, SOLID decides *how classes are structured*. - Three principles carry 80% of the value in practice: Information Expert, Low Coupling, High Cohesion. - Not useful for procedural or functional code with no class hierarchy. ### Quick Example ```java // Bad: Controller knows too much about Order business rules class OrderController { void process(Order order) { if (order.getTotal() > 100) order.applyDiscount(0.1); // Wrong owner } } // Good: Information Expert - Order owns its discount logic class Order { private double total; void applyDiscountIfEligible() { if (total > 100) total *= 0.9; // Order has the data, so it owns the rule } } ``` The controller just coordinates. The discount rule lives where the data lives. ### What GRASP Actually Is GRASP is not a framework or library. No compiler enforces it. It is a design vocabulary: a set of named principles used on a whiteboard, in UML diagrams, or while sketching class structures before writing code. The benefit shows up later, in fewer ripple changes when requirements shift. Craig Larman introduced GRASP in "Applying UML and Patterns" to make responsibility assignment explicit. Before it, developers made these decisions intuitively, without a shared language to justify them. ### GRASP vs SOLID vs GoF Three things developers confuse most in interviews. GRASP answers: which class should own this responsibility? SOLID answers: how should individual classes be structured? GoF answers: what pattern solves this recurring structural problem? GRASP helps you choose or invent patterns. GoF assumes you already know when to apply them. | | GRASP | SOLID | GoF | |---|---|---|---| | Focus | Responsibility assignment | Class design rules | Reusable solutions | | Stage | Initial modeling | Ongoing design | Pattern selection | | Output | "This class owns that" | Better class structure | Concrete pattern | | Author | Craig Larman | Multiple (Martin, etc.) | Gang of Four | ### The Nine Principles **Information Expert.** Give a responsibility to the class that has the information needed to fulfill it. `Order` validates items because it holds the item list. Not `Controller`, not a utility class. **Creator.** Class B should create instances of class A if B contains, aggregates, records, or closely uses A. `PaymentGateway` creates `Charge` objects because it owns the payment context. **Controller.** Route external events (UI clicks, API calls) through a dedicated controller class. The controller delegates to domain objects. It does not execute domain logic itself. **Low Coupling.** Minimize dependencies between classes. When one class changes, the fewer others break, the better. Pass only what a method actually needs, not the whole object. **High Cohesion.** Each class does one thing, or a closely related set of things. A class that handles auth, logging, and discount calculation is a cohesion problem waiting to be a refactoring story. **Polymorphism.** Handle type-based variation with polymorphism instead of if/else chains. When behavior changes by type at runtime, interfaces and subclasses carry that variation cleanly. **Pure Fabrication.** Sometimes no domain class is the right place for a responsibility. Create an artificial class that does not represent a domain concept but exists to keep cohesion high and coupling low. `AuditLogger` is the textbook example. **Indirection.** Add an intermediary between two classes that should not know about each other directly. Message brokers, facades, and adapters are all indirection in practice. **Protected Variations.** Wrap anything that might change behind a stable interface. The caller stays unchanged even when the implementation behind it changes. ### When to Use GRASP - Starting a new domain model: apply all nine to assign class roles before writing code. - Refactoring a god class: High Cohesion and Low Coupling show you where to split. - Team design reviews: naming the principle makes the justification concrete, not personal. - Defining microservice boundaries: Information Expert tells you which service owns which data. Not useful for procedural scripts or functional pipelines with no class hierarchy. ### Common Mistakes **1. Controller as a business logic dump.** GRASP's Controller is a thin coordinator. When it starts accumulating domain rules, it violates Information Expert and kills cohesion. Most codebases I have seen start this way because the controller is the obvious entry point. The fix is to delegate early. ```java // Wrong: controller doing domain work class OrderController { void process(Order order) { // 80 lines of discount, tax, and shipping logic } } // Right: controller delegates class OrderController { void process(Order order) { orderService.applyEligibleDiscounts(order); shippingService.calculateCost(order); } } ``` **2. Passing full objects to reduce Low Coupling.** If a method only needs one field, passing the whole object creates unnecessary coupling. Add a field to `Order`, and every method that accepts it becomes a potential problem. ```java // Wrong: takes whole Order, uses only total void printReceipt(Order order) { System.out.println(order.getTotal()); } // Better: pass what you need void printReceipt(double total) { System.out.println(total); } ``` **3. Polymorphism for simple static cases.** Polymorphism makes sense when behavior varies at runtime. It does not make sense for two fixed cases. Creating `Discount10Percent` and `Discount20Percent` subclasses for a hardcoded if/else is premature abstraction. Use if/else for two or three cases; use polymorphism when the variation happens at runtime. **4. Scattered `new` calls instead of applying Creator.** When object creation is spread across classes, tracking dependencies and testing in isolation gets painful. Creator gives a clear rule: the class that contextually owns an object should create it. ### Real-World Usage - Spring Framework: `@Service` classes act as GRASP Controllers; `@Entity` classes are Information Experts. - React/Redux: reducers follow High Cohesion (pure state logic only); action creators follow Creator. - Java EE: `EntityManager` is the Creator for JPA entities. - Stripe API: `PaymentGateway` creates `Charge` objects, not the client code. - Microservices: Information Expert tells you which service owns which dataset. ### Follow-up Questions **Q:** Explain Information Expert with a bad and good example. **A:** Bad: a UI component calculates order total because it needs to display it. It now depends on every field in the calculation. Good: `Order.calculateTotal()` owns the logic because it owns the data. The UI just calls the method. **Q:** How does Low Coupling differ from Dependency Inversion? **A:** Low Coupling is the goal: minimize dependencies overall. Dependency Inversion is a technique: depend on abstractions, not concrete classes. DIP is one way to achieve Low Coupling, not the only one. **Q:** When would you use Pure Fabrication instead of adding a method to a domain class? **A:** When the responsibility does not belong to any domain concept. Logging, auditing, export formatting: none of these are domain behaviors. Forcing them into a domain class breaks cohesion. **Q:** Design an auction system using three GRASP principles (senior level). **A:** `Bid` as Information Expert (knows its own validity based on minimum price and bid limits). `Auctioneer` as Controller (receives bid events, delegates to `BidValidator`). Low Coupling through a `BidValidator` interface so `Auctioneer` does not depend on concrete validation logic. **Q:** High Cohesion vs Single Responsibility Principle: are they the same thing? **A:** Related but not identical. High Cohesion groups related behaviors in one class. SRP says a class should have only one reason to change. A class can be cohesive but still violate SRP: handling both auth and profile display is "user-related", but each changes for different reasons. **Q:** How do GRASP principles map to functional programming? **A:** Information Expert maps to pure functions that operate on the data they receive. Low Coupling maps to function composition with minimal shared state. The naming differs, the ideas overlap. ## Examples ### Information Expert: Order Validates Itself ```java // Bad: Client duplicates Order's internal logic class Client { void validateOrder(Order order) { if (order.getItems().isEmpty()) throw new IllegalStateException("Empty order"); for (Item item : order.getItems()) { if (!item.isInStock()) throw new IllegalStateException("Out of stock"); } } } // Good: Order has the items list, so it validates itself class Order { private List<Item> items; boolean isValid() { return !items.isEmpty() && items.stream().allMatch(Item::isInStock); } } ``` `Client` changes less. Stock logic lives in one place. When the validation rule changes, you touch one class. ### Creator: PaymentGateway Creates Charge Objects ```javascript // Inspired by Stripe's resource ownership model class PaymentGateway { createCharge(amount, customer) { // Gateway owns and manages Charges - it is the natural Creator return new Charge(amount, customer.id); } } class Charge { constructor(amount, customerId) { this.amount = amount; this.customerId = customerId; } } const gateway = new PaymentGateway(); const charge = gateway.createCharge(100, { id: 'cus_123' }); // Output: Charge { amount: 100, customerId: 'cus_123' } ``` The caller never writes `new Charge(...)`. All charge creation goes through the object that contextually owns charges. Swapping implementations later is straightforward. ### Pure Fabrication: AuditLogger Keeps Components Focused ```jsx // Bad: logging side effect inside a UI component function UserProfile({ user }) { console.log('Audit:', user.id); // UI component should not care about logging return <div>{user.name}</div>; } // Good: Pure Fabrication - AuditLogger is not a domain concept, // it exists to keep each class focused on one thing class AuditLogger { static logUserView(userId) { console.log('Audit:', userId); } } function UserProfile({ user }) { AuditLogger.logUserView(user.id); return <div>{user.name}</div>; } // Output: 'Audit: 123' ``` `AuditLogger` represents nothing in the business domain. It exists because the logging responsibility needed somewhere to live that was not a UI component and not a domain class.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.