CLOSE
Updated on 24 Jun, 202629 mins read 8 views

In the previous chapter, we learned that one of the most important questions in software design is:

Who should do this?

Suppose we are designing an online shopping system.

Requirement:

Calculate order total

Possible objects:

Customer
Order
Product
Payment

Who should calculate it?

Or consider:

Create a Reservation

Possible objects:

Guest
Hotel
Reservation
BookingService

Who should create it?

Without a systematic framework, responsibility assignment becomes guesswork.

To solve this problem, software engineering introduced: GRASP

What is GRASP?

GRASP stands for:

General Responsibility Assignment Software Patterns

Created by: Craig Larman

GRASP is not a design pattern catalog like Factory or Observer.

Instead:

GRASP is set of principles for deciding where responsibilities should live.

Think of GRASP as:

SOLID → How classes should behave

Design Patterns → Reusable solutions

GRASP → How responsibilities are assigned

Why GRASP Matters

Most bad design suffer from:

Wrong object doing the work

God Objects

Anemic Models

High Coupling

Low Cohesion

GRASP directly targets these problems.

The 9 GRASP Principles

1. Information Expert

2. Creator

3. Controller

4. Low Coupling

5. High Cohesion

6. Polymorphism

7. Pure Fabrication

8. Indirection

9. Protected Variations

These principles are often applied simultaneously.

Principle 1 – Information Expert

The Problem

Requirement:

Calculate Order Total

Who should do it?

Candidates:

Customer
Order
PaymentService
InvoiceGenerator

Principle

Assign responsibility to the class that has the information needed to fulfill it.

Example:

Order contains:

Items
Prices
Quantities

Therefore:

class Order
{
public:
	double calculateTotal();
};

Bad:

class Customer
{
public:

    double calculateOrderTotal(Order&);
};

Customer lacks required information.

Mental Model

Ask:

Who knows the data?

The answer often receives the responsibility.

Production Example

Library System

Requirement:

Is this book available?

Book knows:

Available Copies
Status

Therefore:

book.isAvailable();

Book is the expert.

Benefits

  • High Cohesion
  • Simple Design
  • Natural Behavior Placement

Princple 2 – Creator

The Problem

Requirement:

Create OrderItem

Question:

Who should create it?

Principle

A class should create another object if:

It contains it
It aggregates it
It records it
It closely uses it
It has initialization information

Example:

Order
  |
contains
  |
OrderItem

Therefore:

class Order
{
public:

    void addItem(...)
    {
        items.push_back(
            OrderItem(...)
        );
    }
};

Order creates OrderItem.

Why?

Order owns:

Lifecycle
Collection
Business Rules

Bad Design

class Customer
{
public:

    OrderItem createOrderItem();
};

Custsomer has no natural relationship.

Production Example

ATM

ATM creates Transaction

because ATM manages transactions.

Principle 3 – Controller

The Problem

Suppose a user clicks:

Place Order

Which object receives the request?

Bad:

UI directly manipulates every domain object.

Creates chaos.

Principle

Use a controller object to handle system events.

Example:

User
  |
  v
OrderController
  |
  v
Order

Example:

class OrderController
{
public:

    void placeOrder()
    {
        // coordinate workflow
    }
};

Controller responsibilities:

Receive requests
Coordinate workflow
Delegates work

Controller should NOT:

Contain business logic

Bad:

class OrderController
{
public:

    void placeOrder()
    {
        // 500 lines
        // all business logic
    }
};

Good:

controller
    ↓
order
    ↓
payment
    ↓
inventory

Controller coordinates.

Domain objects work.

Principle 4 – Low Coupling

Definition

Coupling measures dependency between classes.

Goal:

Minimize dependencies

Bad Example:

class Order
{
private:

    PaymentGateway gateway;

    Database database;

    Logger logger;

    Cache cache;

    Email email;
};

Order depends on everything.

Problems:

Difficult Testing
Difficult Changes
Fragile Design

Better:

class Order
{
private:
	PaymentService* payment;
};

Fewer dependencies.

Mental Model

Ask:

If this class changes, how many classes break?

Fewer is better.

Principle 5 – High Cohesion

Definition

Cohesion measuress how focused responsibilities are.

Good Example:

class Order
{
public:

    addItem();

    removeItem();

    calculateTotal();

    markPaid();
};

Everything relates to orders.

Bad Example:

class Order
{
public:

    calculateTotal();

    sendEmail();

    resizeImage();

    uploadVideo();

    generateReport();
};

Low cohesion.

Mental Model

Ask:

Do these responsibilities belong together?

If not:

Split the class.

Principle 6 – Polymorphism

The Problem

Suppose:

Credit Card
UPI
PayPal

All support payment.

Bad:

if(type == CREDIT)
{
}
else if(type == UPI)
{
}
else if(type == PAYPAL)
{
}

Principle

Use polymorphism instead of conditionals.

Example:

class PaymentMethod
{
public:

    virtual void pay() = 0;
};
class CreditCard : public PaymentMethod
{
public:

    void pay() override;
};
class UPI : public PaymentMethod
{
public:

    void pay() override;
};

Usage:

paymentMethod->pay();

No conditional logic.

Benefits

Extensible
Maintainable
OCP Friendly

Principle 7 – Pure Fabrication

The Problem

Sometimes no natural domain object fits.

Example

Requirement:

Save Customer to Database

Question:

Should Customer save itself?

Bad:

class Customer
{
public:

    saveToDatabase();
};

Now Customer knows SQL.

Violation:

Low Cohesion
High Coupling

Solution

Create artificial class.

class CustomerRepository
{
public:

    void save(Customer&);
};

Repository doesn't exist in business domain.

We create it to improve design.

This is Pure Fabrication

Benefits

Better Separation
Higher Cohesion
Lower Coupling

Principle 8 – Indirection

Problem

Two objects become tightly coupled.

Example:

Order
   |
directly
   |
PaymentGateway

If gateway changes:

Order changes

Solution

Introduce intermediary.

Order
   |
PaymentService
   |
PaymentGateway

Example:

class PaymentService
{
public:

    virtual void process() = 0;
};

Benefits

Reduced Dependency

Flexibility

Testability

Principle 9 – Protected Variations

Problem

Some parts of systems change frequently.

Examples:

Payment Providers

Notification Systems

Databases

Shipping Providers

Principle:

Protect stable parts from unstable parts.

Bad

  Order
    |
    v
Stripe API

Order tied directly to Stripe.

Better

 Order
   |
Payment Interface
   |
Stripe
PayPal
Razorpay

Example

class PaymentProcessor
{
public:

    virtual void process() = 0;
};

Implementations

StripeProcessor

PayPalProcessor

RazorpayProcessor

Order depends on abstraction

Not implementation.

How GRASP Principles Work Together

Real design rarely use one principle.

Example

E-Commerce Checkout

Information Expert: Order calculates total.
Creator: Order creates OrderItem.
Controller: Order depends on Payment Interfaces.
High Cohesion: Order manages only order concerns.
Polymorphism: Different payment methods.
Pure Fabrication: OrderRepository.
Indirection: PaymentService.
Protected Variations: PaymentProcessor Interface.

Complete Example

User
  |
  v
CheckoutController
  |
  v
Order
  |
  +------> OrderItem

Order
  |
  v
PaymentProcessor
      |
      +---- Stripe
      |
      +---- PayPal
      |
      +---- UPI

Industry Perspective

Many enterprise architectures unconsciously follow GRASP.

Examples:

Spring Applications

.NET Applications

Large C++ Systems

Microservices

GRASP influenced many later concepts including:

SOLID
DDD
Clean Architecture
Hexagonal Architecture

Expert Notes

One of the most important realizations in software design:

There is rarely a perfect for a responsibility.

Design is often about choosing the least problematic option.

GRASP provides a framework for making those decisions consistently.

Another insight:

Information Expert and High Cohesion solve most beginner design problems.

If you simply ask:

Who owns the information?
Will this increase cohesion?

your design improve dramatically.

Finally:

GRASP is about thinking, not memorization.

The goal is not remembering nine names.

The goal is learning how architects reason about responsibility placement.

GRASP provides a systematic framework for assigning responsibilities.

The nine principles are:

PrinciplePurpose
Information ExpertAssign responsibility to information owner
CreatorDecide who creates objects
ControllerHandle system events
Low CouplingReduce dependencies
High CohesionKeep responsibilities focused
PolymorphismReplace conditionals
Pure FabricationCreate helper abstractions
IndirectionDecouple components
Protected VariationsIsolate change
Buy Me A Coffee

Leave a comment

Your email address will not be published. Required fields are marked *

Your experience on this site will be improved by allowing cookies Cookie Policy