In the previous chapter, we learned how to discover objects from requirements.
Suppose we analyzed an e-commerce system and identitifed:
Customer
Order
Product
Cart
PaymentNow a new question appears:
Who calculates the order total?
Who validates payment?
Who updates inventory?
Who creates orderes?
Who sends notifications?Finding objects is only half the problem.
The harder problem is: Assigning Responsibilities Correctly
This is where most poor designs are born.
The Fundamental Problem
Imagine we are designing an ATM.
Requirement:
Customer withdraws money.
Who should perform the withdrawal?
Possible answers:
Customer
ATM
BankAccount
Database
TransactionA beginner often chooses randomly.
An architect does not.
There must be a systematic way to decide.
Responsibilities Assignment was created to solve exactly this problem.
What Is a Responsibility?
A responsibility is:
Something an object knows or something an object does.
Every responsibility falls into one of two categories.
Type 1 тАУ Knowing Responsibilities
Information an object owns.
Example:
class Customer
{
private:
string name;
string email;
};Customer knows:
Name
Email
Address
Phone NumberThese are knowing responsibilities.
Type 2 тАУ Doing Responsibilities
Actions an object performs.
Example:
class Customer
{
public:
void placeOrder();
};Customer performs:
Place Order
Update Profile
Cancel SubscriptionThese are doing responsibilities.
Simple Mental Model
Every object should answer:
What do I know?
What do I do?Nothing more.
Nothing less.
Why Responsibility Assignment Matters
Consider the design.
class Customer
{
public:
void placeOrder();
void calculateTax();
void processPayment();
void updateInventory();
void generateInvoice();
void sendEmail();
void scheduleDelivery();
};Question:
Is Customer really responsibel for all of this?Obviously not.
This is the beginning of a: God Object
What Is a God Object?
A God Object is an object that knows too much and does too much.
Example:
class SystemManager
{
public:
void loginUser();
void processOrder();
void printInvoice();
void updateStock();
void sendEmails();
void generateReports();
void handlePayments();
};Everything goes into one class.
Symptoms:
Huge class
Thousands of lines
Many dependencies
Difficult testing
Frequent bugsGod Objects are among the most common design failures.
Responsibility Assignment Goal
The goal is:
High Cohesion
Low CouplingWe studied these concepts earlier. Now we apply them.
Example: Order Total Calculation
Requirement:
Calculate order total.Possible candidates:
Customer
Order
Product
PaymentServiceQuestion:
Who should calculate the total?Let's analyze.
Customer
Knows:
Profile
Address
OrdersNot ideal.
Product
Knows:
Price
InventoryOnly individual product information.
PaymentService
Responsible for payments.
Not totals.
Order
Knows:
Items
Quantities
PricesPerfect.
Therefore:
class Order
{
public:
double calculateTotal();
};Responsibility assigned correctly.
Responsibility Should Follow Information
One of the most important design principle:
Behavior should live near the information it uses.
Bad design:
class Customer
{
public:
double calculateOrderTotal(Order& order);
};Customer does not own order data.
Better Design:
class Order
{
public:
double calculateTotal();
};Order owns the information.
Order knows the behavior.
Example: Library System
Requirement:
Determine whether a book can be borrowed.Possible objects:
Book
Member
Library
LoanQuestion:
Who should decide availability?
Book knows:
Available Copies
Current StatusTherefore:
class Book
{
public:
bool isAvailable();
};Book has the required information.
Book gets the responsibility.
Information Expert Principle
This idea is so important that later GRASP formalizes it.
The rule:
Give responsibility to the object that has the information required to fulfill it.
Example:
Requirement:
Calculate Shopping Cart TotalWho has:
Products
Prices
QuantitiesAnswer:
CartTherefore:
cart.calculateTotal();Cohesion and Responsibility
High cohesion means:
Related responsibilities stay together.
Example:
class Order
{
public:
addItem();
removeItem();
calculateTotal();
markPaid();
};All responsibilities relate to order.
High cohesion.
Bad Example:
class Order
{
public:
calculateTotal();
sendEmail();
generateReport();
resizeImage();
uploadVideo();
};Low cohesion.
Responsibilities unrelated.
Responsibility Assignment Example
Food Delivery System
Objects:
Customer
Restaurant
Order
DeliveryPartner
PaymentRequirement:
Track Order StatusPossible owners:
Customer
Restaurant
OrderWho owns status?
OrderTherefore:
class Order
{
public:
void updateStatus();
OrderStatus getStatus();
};Requirement:
Prepare FoodWho owns preparation?
RestaurantTherefore:
class Restaurant
{
public:
void prepareOrder();
};Requirement:
Deliver FoodOwner:
DeliveryPartnerCorrect responsibility assignment.
The Danger of Anemic Models
A very common beginner design:
class Customer
{
public:
string name;
};
class Order
{
public:
double total;
};
class Product
{
public:
double price;
};No behavior.
Only data.
Then:
class OrderService
{
public:
void calculateTotal();
void validateOrder();
void processOrder();
};All behavior moved elsewhere.
This creates: Anemic Domain Models
Why Anemic Models Are Bad
Problems:
Objects become data containers.
Business rules become scattered.
Low cohesion.
Hard maintenance.
Weak encapsulation.Objects should contain meaningful behavior.
Rich Domain Models
Better:
class Order
{
public:
void addItem();
void removeItem();
double calculateTotal();
void markPaid();
};Behavior stays with data.
This creates stronger models.
Responsibility Assignment Workflow
Professional designers often follow this sequence.
Step 1: Read Requirement
Customer places order.
Step 2: Identify involved objects
Customer
OrderStep 3: Identify required behavior
Place OrderStep 4: Ask:
Who has the information?
Who owns the process?
Who naturally fits the responsibility?
Step 5: Assign responsibility
Example:
customer.placeOrder();or:
order.create();depending on domain analysis.
Leave a comment
Your email address will not be published. Required fields are marked *


