GRASP: Why Real Architecture Starts Not with SOLID
Many developers start with SOLID and GoF patterns, but feel a gap in understanding responsibility distribution and domain modeling. GRASP fills this gap by providing a design methodology that precedes and complements SOLID.
Introduction
Many developers start with SOLID and GoF patterns, but feel a gap in understanding responsibility distribution and building a domain model. GRASP fills this gap by providing a design methodology that precedes and complements SOLID.
The Author's Personal Backstory
The author read the classics: "Clean Code" by Robert Martin, "Code Complete" by Steve McConnell, and studied SOLID, KISS, DRY. However, when reading Eric Evans' DDD, a problem emerged: the book shows tactical patterns (aggregates, value objects, specifications) and strategic approaches, but doesn't explain the methodology of designing a domain model from requirements.
Key revelation: everyone talks about OOP, but writing code in an OOP language and designing in the OOP paradigm are two different things.
Craig Larman and "Applying UML and Patterns"
Larman's book (1997) preceded DDD and offered a clear methodology:
- Requirements and use-case analysis
- Building a conceptual model
- Identifying roles and responsibilities
Larman and Evans complement each other:
- Larman provides the process of transitioning from scenarios to a model
- Evans formalizes the language and patterns for working with the domain
Martin Fowler recommends Larman's book as the best introduction to object-oriented design.
The Nine GRASP Patterns
Group 1: Fundamental Model Principles
High Cohesion
Logically grouping responsibilities within a component simplifies maintenance, understanding, and makes the system more resilient to changes.
Low Coupling
Minimizing dependencies between modules increases modularity, reduces cascading changes, and facilitates testing.
Information Expert
If an object possesses the information to perform a task, that object should be assigned the task. This increases cohesion, eliminates duplication, and transitions from anemic models to rich domains where data and behavior are inseparable.
Creator
An object that contains, records, or actively uses another object should be responsible for its creation. This reduces coupling and localizes responsibility.
Group 2: Engineering Extensions
Pure Fabrication
Creating synthetic abstractions that don't reflect the domain but are necessary for architectural cleanliness. Example: a repository as a layer between logic and storage.
Indirection
Creating a controlled layer between objects to reduce coupling. It manifests in Proxy, Decorator, Adapter, Facade, and Repository — all of these are implementations of Indirection at different levels.
| Pattern | Function | Indirection |
|---|---|---|
| Proxy | Intercepts calls | Intermediate object between client and implementation |
| Decorator | Extends behavior | Wraps with additional logic |
| Adapter | Transforms interface | Mediator between incompatible interfaces |
| Facade | Simplifies access | Intermediary between client and multiple components |
| Repository | Abstracts access | Mediator between business logic and infrastructure |
Controller
The first-link coordination pattern. A component at the system boundary (HTTP controller, gRPC endpoint, Kafka consumer) receives input data, determines the scenario, and delegates execution. A Controller can exist at different levels (UI controller, use-case controller).
Group 3: Flexibility and Resilience
Polymorphism
The ability of a function to work with objects of different types. Forms:
- Parametric: generics
List<T> - Ad-hoc: method overloading
- Subtype: inheritance and interfaces
Without polymorphism, code contains conditions (if instanceof). With polymorphism, each type implements its own behavior, achieving the OCP principle (open for extension, closed for modification).
Protected Variations
Isolating potentially changeable areas with stable abstractions. Anticipate variability in advance:
| Area | Example |
|---|---|
| DDD | A repository protects the domain model from database changes |
| Hexagonal Architecture | Adapters protect the core from APIs, UI, and brokers |
| Clean Architecture | Outer layers depend on inner ones through interfaces |
Protected Variations is close to SOLID's Dependency Inversion Principle (DIP): high-level code should not depend on details. It's also related to the Liskov Substitution Principle (LSP): implementations must correctly follow the abstraction's contract so that replacement is safe.
GRASP's Impact on Cohesion and Coupling
| Pattern | Impact |
|---|---|
| Information Expert | Increases Cohesion |
| Creator | Reduces Coupling |
| Pure Fabrication | Increases Cohesion |
| Indirection | Reduces Coupling |
| Controller | Reduces Coupling between UI and business logic, increases Cohesion |
| Polymorphism | Reduces Coupling, increases extensibility |
| Protected Variations | Localizes Coupling, creates buffers for changes |
Intersection of Meanings: Repository as an Example
A repository simultaneously demonstrates several patterns:
- Pure Fabrication: it's an artificial abstraction that doesn't exist in business
- Indirection: it serves as a layer between business logic and storage, reducing coupling
This shows how GRASP patterns complement each other at different levels of architecture.
Connection with SOLID
- OCP (Open/Closed): achieved through Polymorphism and Protected Variations
- DIP (Dependency Inversion): implemented by Indirection and Protected Variations
- LSP (Liskov Substitution): guarantees the correctness of Protected Variations through behavioral contracts
- SRP (Single Responsibility): reflected in High Cohesion and proper responsibility distribution
Key Takeaway
A mature architectural approach starts not with practices and frameworks, but with understanding principles. GRASP expresses how to think about a system at the level of architectural intuition, to choose the right tools and styles.
"He who understands the principles will find the right methods himself. And he who tries methods while ignoring principles will inevitably encounter problems." — Ralph Waldo Emerson
Knowing the principle, you can derive the practice. Knowing only the practice, it's easy to get lost in real complexity.
FAQ
What is this article about in one sentence?
This article explains the core idea in practical terms and focuses on what you can apply in real work.
Who is this article for?
It is written for engineers, technical leaders, and curious readers who want a clear, implementation-focused explanation.
What should I read next?
Use the related articles below to continue with closely connected topics and concrete examples.