Introduction
Imagine two software systems.
System A:
Change one class
↓
20 other classes break
↓
10 tests fail
↓
Unexpected bugs appearDevelopers become afraid to modify code.
Every change feels dangerous.
System B:
Change one class
↓
Only one module affected
↓
No unrelated failures
↓
Easy deploymentDevelopers confidently evolve the system.
Why are these systems so different?
The answer lies in two of the most important concepts in software engineering:
Coupling and Cohesion
These concepts are so important that nearly every software engineering principle, design pattern, architecture style, and framework eventually boils down to improve one or both.
In fact:
Good software design is largely the art of achieving low coupling and high cohesion.
Everything else is often a consequence.
Historical Context
During the Software Crisis (1960s – 1980s), engineers noticed something strange.
Two systems with similar functionality could have drastically different maintenance costs.
Example:
System A:
100,000 lines
System B:
100,000 linesSame size.
But:
System A: Easy to modify
System B: Extremely difficult to modifyWhy?
Researchers began studying software architecture.
They discovered two characteristics repeatedly appeared in successful systems:
LOW COUPLING
HIGH COHESIONThese became fundamental software engineering principles.
Understanding Coupling
What Is Coupling?
Coupling measures:
How strongly one component depends on another component.
Or more simply:
How connected things are.
Real-World Analogy: Train Cars
Imagine train cars.
Loosely Coupled
[Car A] -- [Car B]Tightly Coupled
[Car A]
|
[Car B]
|
[Car C]
|
[Car D]Removing one affect everything.
Software behaves similarly.
Formal Definition
Coupling is:
The degree of dependency between software modules.
Higher dependency:
Higher CouplingLower dependency:
Lower CouplingWhy Coupling Matters
Every dependency introduces risk.
Example:
class PaymentService {
};Used by:
OrderService
InvoiceService
RefundService
NotificationService
AnalyticsServiceNow changes inside PaymentService may affect many places.
Dependencies create maintenance costs.
Visualization Coupling
Low Coupling:
+---------+
| ModuleA |
+---------+
+---------+
| ModuleB |
+---------+
+---------+
| ModuleC |
+---------+Independent modules.
High Coupling:
A → B → C → D → E
↑ ↓
+---------------+Complex dependency network.
Changes become dangerous.
Example: Tight Coupling
Consider:
class MySQLDatabase
{
public:
void save()
{
}
};class UserService
{
private:
MySQLDatabase database;
public:
void registerUser()
{
database.save();
}
};Problem:
UserService depends directly on MySQL.Suppose tomorrow:
MySQL --> PostgreSQLNow UserService must change.
This is tight coupling.
Better Design
Introduce abstraction.
class IDatabase {
public:
virtual void save() = 0;
};Implementation:
class MySQLDatabase: public IDatabase {
public:
void save() override
{
// ...
}
};Usage:
class UserService {
private:
IDatabase& database;
public:
UserService(IDatabase& db)
: database(db)
{
}
};Now:
UserService depends on abstractionCoupling decreases significantly.
Symptoms of High Coupling
Frequent Ripple Effects
Change:
Class AUnexpectedly affects:
Class B
Class C
Class D
Class EFear of Modification
Developers say:
Don't touch that code.Major warning sign.
Difficult Testing
Creating one object requires:
Databases
Network
Cache
Queue
LoggerToo many dependencies.
Difficult Reuse
Class cannot be reused because it depends on everything.
Types of Coupling
1: Content Coupling (Worst)
One module directly modifies internals of another.
Example:
class User
{
public:
std::string password;
};External code:
user.password = "345";Very dangerous.
2: Common Coupling
Shared global state.
globalConfig
globalDatabase
globalLoggerEverything depends on the same data.
Example:
GlobalSettings::debugMode = true;Suddenly entire sysetm behavior changes.
3: Control Coupling
Passing flags that control behavior.
Example:
generateReport(true);Question:
What does true mean?Bad design.
Better:
generateSummaryReport();
generateDetailedReport();4: Data Coupling
Passing only required information.
calculateTax(price);Simple.
Clear.
Independent.
Desired Goal
Move toward:
LOW COUPLINGNot:
ZERO COUPLINGImportant distinction.
Some dependencies are necessary.
Understanding Cohesion
What Is Cohesion?
Cohesion measures:
How strongly related the responsibilities inside a module are.Or:
How well things belong togetherReal-World Analogy: Toolbox
Good toolbox:
Hammer
Screwdriver
Wrench
PliersAll related. High cohesion.
Bad toolbox:
Hammer
Pizza
Laptop
Dog Leash
ToothbrushRandom items. Low cohesion.
Software works exactly the same way.
Formal Definition
Cohesion is:
The degree to which elements within a module belong together.
Higher relatedness:
Higher CohesionLower relatedness:
Lower CohesionExample: Low Cohesion
class EmployeeManager
{
public:
void addEmployee();
void calculateSalary();
void sendEmail();
void generateReport();
void connectDatabase();
void printInvoice();
};Question:
What is this class responsible for?
Answer:
EverythingLow cohesion.
Example: High Cohesion
class EmployeeService
{
public:
void addEmployee();
void removeEmployee();
void updateEmployee();
};Single responsibility. Strong cohesion.
Visualizing Cohesion
Low Cohesion:
EmployeeService
├─ Email
├─ Database
├─ Reports
├─ Payroll
├─ AuthenticationRandom responsibilities.
High Cohesion:
EmployeeService
├─ Add Employee
├─ Remove Employee
├─ Update EmployeeEverything belongs together.
Why Cohesion Matter
High cohesion improves:
Readability
Maintainability
Testability
ReusabilityBecause responsibilities are clear.
Cohesion Levels
Coincidental Cohesion
Completely unrelated functionality.
Example:
Utils
Helpers
CommonStuff
MiscFunctionsTypical anti-patterns.
Logical Cohesion
Related only by category.
Example:
class InputHandler
{
handleKeyboard();
handleMouse();
handleTouch();
}Better, but still weak.
Functional Cohesion
Everything contributes toward one goal.
Example:
class PaymentProcessor
{
validatePayment();
authorizePayment();
capturePayment();
}Coupling vs Cohesion
| Coupling | Cohesion |
|---|---|
| Between modules | Within module |
| Dependency measurement | Responsibility measurement |
| Want low | Want high |
| Affects flexibility | Affects clarity |
The Golden Rule
The fundamental design goal:
LOW COUPLING
HIGH COHESIONThis combination creates maintainable systems.
Leave a comment
Your email address will not be published. Required fields are marked *
