The calling module passes only what's needed
In software engineering, the design phase of the Software Development Life Cycle (SDLC) aims to produce a solution that satisfies the Software Requirements Specification (SRS). Two of the most foundational metrics for evaluating the quality of that design are cohesion and coupling. Together, they determine how well a system is decomposed into modules — the building blocks of any software architecture.
What is Cohesion?
Cohesion refers to the degree of interrelatedness and focus among the elements within a module, class, or component. It measures how well the internal components of a module work together to achieve a single, well-defined purpose. High cohesion indicates that all elements are closely related and contribute collectively to a specific functionality. Low cohesion suggests the elements are scattered and serve multiple unrelated purposes — a classic "dumping ground" module.
What is Coupling?
Coupling refers to the degree of interdependence between software modules. High coupling means modules are tightly connected and changes in one ripple through others. Low coupling means modules are largely independent — changes in one have minimal impact on others. The design goal is always low coupling, which promotes modularity, flexibility, and testability.
The Golden Rule of Design
The overarching design principle is:
High cohesion ensures each module has a clear, focused responsibility (making it easier to understand, test, and reuse). Low coupling ensures that modifying one module does not cascade changes across the entire system. These two properties are inversely related: highly cohesive modules are often loosely coupled, because grouping related functionality together makes a module more self-contained.
Footnotes
-
GeeksforGeeks — Coupling and Cohesion in Software Engineering — Overview of coupling and cohesion as design quality metrics. ↩ ↩2
-
Scaler Topics — Software Engineering: Coupling and Cohesion — Detailed definitions and types of both cohesion and coupling. ↩ ↩2
-
The Valuable Dev — Cohesion and Coupling in Software with Examples — In-depth guide tracing origins and providing real-world examples. ↩
-
Wikipedia — Coupling (computer programming) — Formal taxonomy of coupling types and their definitions. ↩
-
Medium — Low Coupling and High Cohesion — Discussion of the inverse relationship between cohesion and coupling. ↩
Cohesion and Coupling in Software Engineering — Gate Smashers
Types of Cohesion
Cohesion is classified into seven types, ranked from the least desirable (weakest) to the most desirable (strongest). This spectrum, originally formalized by the Structured Design movement (Yourdon and Constantine), provides a taxonomy for judging module quality.
[!NOTE] Note
The order from worst to best is: Coincidental → Logical → Temporal → Procedural → Communicational → Sequential → Functional.
1. Coincidental Cohesion (Worst)
Coincidental Cohesion occurs when elements are placed together by chance or for convenience, not by any logical or functional relationship. A common real-world example is a "utility" module that contains a date formatter, a string reverser, and a random-number generator all in the same file. There is no clear reason these functions coexist.
Example (Python):
1def misc_operations(): 2 format_date() 3 reverse_string() 4 generate_random_number()
2. Logical Cohesion
Logical Cohesion occurs when elements contribute to activities that are logically related (e.g., all "input" functions or all "error-handling" functions), but do not call each other or collaborate on a single task. A module that reads from keyboard, file, and network — all bundled because they "read data" — exhibits logical cohesion.
Example (Python):
1def read_input(source): 2 if source == "keyboard": 3 read_from_keyboard() 4 elif source == "file": 5 read_from_file() 6 elif source == "network": 7 read_from_network()
3. Temporal Cohesion
Temporal Cohesion occurs when elements are grouped because they are activated at the same time — for example, all initialization and startup tasks grouped into one init() function, or all cleanup tasks in a shutdown() function. While temporally convenient, the elements may serve entirely different purposes.
Example (Python):
1def system_startup(): 2 load_config() 3 initialize_database() 4 start_logging() 5 clear_cache()
4. Procedural Cohesion
Procedural Cohesion occurs when elements are grouped because they follow a specific sequence of execution. The output of one step does not necessarily become the input to the next (that would be sequential cohesion). The focus is on the order of operations — like a workflow where steps are performed one after another.
Example (Python):
1def process_order(): 2 validate_order() # Step 1 3 charge_credit_card() # Step 2 4 generate_invoice() # Step 3 5 send_confirmation() # Step 4
5. Communicational Cohesion
Communicational Cohesion occurs when elements work on the same data structure or share common input/output data, even though they may perform different operations. For example, a module that both search_records() and sort_records() on the same data array exhibits communicational cohesion.
Example (Python):
1def student_report(student_data): 2 calculate_gpa(student_data) # Uses student_data 3 generate_transcript(student_data) # Uses same student_data 4 rank_student(student_data) # Uses same student_data
6. Sequential Cohesion
Sequential Cohesion occurs when the output of one element serves as the input to the next element in a pipeline-like arrangement. This is stronger than procedural cohesion because there is an actual data dependency between the steps.
Example (Python):
1def data_pipeline(): 2 raw_data = read_file() # Output: raw_data 3 parsed_data = parse(raw_data) # Input: raw_data → Output: parsed_data 4 filtered = filter(parsed_data) # Input: parsed_data → Output: filtered 5 results = aggregate(filtered) # Input: filtered → Output: results 6 return results
7. Functional Cohesion (Best)
Functional Cohesion is the highest and most desirable level. Every element in the module contributes to a single, well-defined task. The module does one thing and does it well. A module that only computes the factorial of a number, or only encrypts a string, has functional cohesion. This level promotes maximum clarity, modularity, reusability, and testability.
Example (Python):
1def compute_factorial(n): 2 """Single responsibility: compute factorial.""" 3 result = 1 4 for i in range(2, n + 1): 5 result *= i 6 return result
Footnotes
-
Gary Drocella, Medium — The 7 Types of Cohesion — Detailed breakdown of all seven cohesion types with Python code samples. ↩ ↩2 ↩3 ↩4 ↩5
-
The Valuable Dev — Cohesion and Coupling in Software with Examples — In-depth guide tracing origins and providing real-world examples. ↩
-
Scaler Topics — Software Engineering: Coupling and Cohesion — Detailed definitions and types of both cohesion and coupling. ↩ ↩2
-
Code Smells Substack — Understanding Cohesion, Coupling and Connascence — Detailed comparison of cohesion types with refactoring examples. ↩
Cohesion Spectrum — From Weakest to Strongest
Relative design quality of each cohesion type (higher = more desirable)
Types of Coupling
Coupling is classified into seven types, ranked from the most desirable (loosest) to the least desirable (tightest) by the Structured Design methodology. The goal is to move toward the looser end of the spectrum.
1. No Coupling (Best)
No direct coupling means modules have no interdependence at all — they neither call one another nor share data. This is the ideal state for independent components and is the loosest form of coupling. In practice, a system with zero coupling would be non-functional (modules must interact), but individual pairs of modules can aim for this level.
2. Data Coupling
Data Coupling occurs when two modules communicate by passing only the necessary data (primitive values or simple parameters) to each other. This is the most desirable form of inter-module coupling because modules maintain independence and communicate through a minimal, well-defined interface.
Example (Python):
1def calculate_area(length, width): 2 """Receives only primitive data values.""" 3 return length * width 4 5# The calling module passes only what's needed 6area = calculate_area(5, 3)
3. Stamp Coupling (Data-Structured Coupling)
Stamp Coupling occurs when a complete data structure (a record, object, or struct) is passed between modules, but the receiving module uses only some of its fields. This is weaker than data coupling because the receiving module is exposed to unnecessary parts of the data structure, and changes to the structure can ripple.
Example (Python):
1def print_student_name(student_record): 2 """Passed an entire Student object but only uses the name field.""" 3 print(student_record.name) # Ignores GPA, courses, address, etc.
4. Control Coupling
Control Coupling occurs when one module passes a control flag or signal that influences the internal logic or execution path of another module. The calling module essentially tells the callee what to do, not just what data to process. This makes the callee less reusable, as its behavior depends on external decisions.
Example (Python):
1def process_data(data, mode): 2 if mode == "encrypt": 3 return encrypt(data) 4 elif mode == "decrypt": 5 return decrypt(data) 6 elif mode == "compress": 7 return compress(data) 8 9# Caller controls behavior via the 'mode' flag 10result = process_data(my_data, "encrypt")
5. External Coupling
External Coupling occurs when two modules share an externally imposed data format, communication protocol, or device interface. Since they depend on an external specification (such as a fixed file format or hardware protocol), changes to that external contract affect all coupled modules.
Example (Python):
1# Both modules depend on the same external XML format 2def read_config_xml(file_path): 3 tree = ET.parse(file_path) 4 return tree.getroot() 5 6def write_config_xml(config_data, file_path): 7 root = ET.Element("config") 8 for key, value in config_data.items(): 9 child = ET.SubElement(root, key) 10 child.text = value 11 tree = ET.ElementTree(root) 12 tree.write(file_path)
6. Common Coupling
Common Coupling occurs when several modules access the same global data (global variables, shared database tables, or common data areas). While convenient, this creates severe maintainability issues: a change to the global data structure requires tracing every module that uses it to evaluate the impact. It also reduces the ability to control data access and makes modules difficult to reuse independently.
Example (Python):
1# Module A 2global_counter = 0 3 4def increment_counter(): 5 global global_counter 6 global_counter += 1 7 8# Module B 9def get_counter_status(): 10 global global_counter 11 return f"Counter is at {global_counter}" 12 13# Module C 14def reset_counter(): 15 global global_counter 16 global_counter = 0
7. Content Coupling (Worst)
Content Coupling is the most harmful form of coupling. It occurs when one module directly references or modifies the internal data, code, or control flow of another module — for example, branching into the middle of another module's code or modifying another module's internal variables. This violates the principle of information hiding and makes the system extremely fragile.
Example (Python):
1class BankAccount: 2 def __init__(self): 3 self.balance = 0 # Intended to be private 4 5# Another module directly modifies internal state 6account = BankAccount() 7account.balance = 999999 # Direct manipulation — content coupling!
Footnotes
-
Scribd — Types of Coupling in Software Engineering — Seven coupling types ranked from worst to best with examples. ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
Dev.to — Software Engineering Coupling: A Practical Approach — Practical code examples of data, stamp, control, common, and content coupling. ↩ ↩2
Coupling Spectrum — From Loosely to Tightly Coupled
Relative severity of coupling (lower = more desirable)
Evolution of Cohesion and Coupling as Design Metrics
Modular Programming Emerges
Late 1960sEarly notions of decomposing programs into modules arise, driven by the need to manage growing software complexity."
Stevens, Myers, and Constantine
1974IBM researchers Larry Constantine, Wayne Stevens, Glen Myers, and Larry Yourdon publish the seminal paper defining cohesion and coupling as formal quality metrics."
Footnotes
-
Gary Drocella, Medium — The 7 Types of Cohesion — Detailed breakdown of all seven cohesion types with Python code samples. ↩
Yourdon and Constantine: Structured Design
1978The book 'Structured Design' codifies the seven levels of cohesion and the spectrum of coupling types, establishing them as industry-standard design metrics."
Object-Oriented Adaptation
1990sCohesion and coupling concepts are adapted from procedural modules to OOP classes, influencing SOLID principles and design patterns."
Connascence Refinement
2000sMeilir Page-Jones extends coupling analysis with 'connascence' — a finer-grained taxonomy of dependency types between modules."
Microservices & Domain-Driven Design
2010s–PresentHigh cohesion and low cou0pling are reinterpreted at the system architecture level — guiding bounded contexts in DDD and service boundaries in microservices."
Cohesion vs. Coupling — A Comparative Overview
While cohesion and coupling are often discussed together, they measure fundamentally different dimensions of design quality. Cohesion looks inward at a single module's internal focus; coupling looks outward at the relationships between modules.
| Aspect | Cohesion | Coupling |
|---|---|---|
| Scope | Within a single module | Between two or more modules |
| Focus | Internal glue and functional focus | External interdependence and interfaces |
| Goal | High cohesion (max internal relatedness) | Low coupling (minimize interdependence) |
| Impact of High/Low | High → easier to understand, test, reuse | Low → easier to maintain, modify, scale |
| Types (worst→best) | Coincidental → ... → Functional | Content → ... → No Coupling |
| Key Principle | Single Responsibility Principle | Dependency Inversion / Interface Segregation |
The relationship between the two can be summarized:
When you group only highly related functionality together (high cohesion), there is less need for a module to reach into other modules for what it needs — thus coupling naturally decreases.
Footnotes
-
Scaler Topics — Software Engineering: Coupling and Cohesion — Detailed definitions and types of both cohesion and coupling. ↩
-
Medium — Low Coupling and High Cohesion — Discussion of the inverse relationship between cohesion and coupling. ↩
How to Evaluate and Improve Cohesion & Coupling in Your Code
- 1Step 1
Examine each module or class and list every function it performs. If the module handles unrelated tasks (e.g., file I/O + email + date formatting), it has low (likely coincidental or logical) cohesion. Flag it for refactoring.
- 2Step 2
Classify the module against the seven-tier hierarchy. Do elements share data (communicational)? Do they execute in sequence (procedural)? Is there a single well-defined purpose (functional)? Aim to refactor toward functional cohesion by splitting modules.
Footnotes
-
Gary Drocella, Medium — The 7 Types of Cohesion — Detailed breakdown of all seven cohesion types with Python code samples. ↩
-
- 3Step 3
For each pair of interacting modules, determine what they share. Do they pass only primitive data (data coupling)? Do they share a whole object (stamp coupling)? Do they pass control flags (control coupling)? Do they access global state (common coupling)?
- 4Step 4
Map each dependency to its coupling level. If you find content coupling (one module reaching into another's internals), prioritize eliminating it immediately — this is the most harmful form. Replace with proper encapsulation and interfaces.
Footnotes
-
Scribd — Types of Coupling in Software Engineering — Seven coupling types ranked from worst to best with examples. ↩
-
- 5Step 5
Break large low-cohesion modules into smaller, functionally cohesive ones. Replace global data with parameter passing (data coupling). Eliminate control flags by using polymorphism or the Strategy pattern. Ensure all module interfaces expose only what callers need (minimize stamp coupling).
- 6Step 6
High-cohesion, low-coupling modules are independently testable. Attempt to write unit tests for each module in isolation. If a module cannot be tested without setting up a large context or global state, it signals a coupling problem that needs further refactoring.
The Design Heuristic
Aim for functional cohesion and data coupling as your default design targets. If every module does exactly one thing and communicates only via simple parameter passing, your system will be robust, maintainable, and easy to extend. When you must deviate — e.g., sharing a resource object — prefer stamp coupling over common coupling, and never allow content coupling.
Footnotes
-
Dev.to — Software Engineering Coupling: A Practical Approach — Practical code examples of data, stamp, control, common, and content coupling. ↩
Common Questions & Edge Cases
Beware the Utility Trap
The most common source of low cohesion in real-world codebases is the Utils or Helper class. These modules accumulate unrelated static methods over time and become a dumping ground with coincidental cohesion. Instead, group related helper functions into domain-specific modules — e.g., StringProcessor, DateFormatter, FileParser — each with a single, clear responsibility2.
Footnotes
-
The Valuable Dev — Cohesion and Coupling in Software with Examples — In-depth guide tracing origins and providing real-world examples. ↩
-
Dev.to — Software Engineering Coupling: A Practical Approach — Practical code examples of data, stamp, control, common, and content coupling. ↩
Cohesion & Coupling Key Concepts
Knowledge Check
Which type of cohesion is considered the strongest and most desirable?
Explore Related Topics
I/O Interfacing
I/O interfacing connects a CPU with peripheral devices by handling addressing, readiness detection, data movement, and timing synchronization through controllers, registers, and protocols.
- Devices are accessed via memory‑mapped I/O or isolated I/O, each with distinct address spaces and instruction sets.
- Transfer methods include programmed I/O (polling), interrupt‑driven I/O, and DMA, balancing CPU involvement, latency, and throughput.
- Handshaking and buffering reconcile speed mismatches, while parallel, serial, and analog interfaces extend functionality to various signal types.
- Design trade‑offs involve choosing the appropriate addressing scheme, transfer method, and synchronization technique for each device class.
Pass Coding Interviews: A Comprehensive Strategy Guide
A data‑driven, pattern‑based guide that covers foundational DS&A, the highest‑ROI algorithm patterns, a 6‑step coding interview framework, and behavioral STAR preparation.
- Recognize and master top patterns—DFS/BFS (~22%), Two Pointers (~16%), Sliding Window (~12%), Binary Search (~11%), Hash Map (~10%)—to cover most interview problems.
- Apply the 6‑step process: Clarify → Work examples → Brainstorm (state ) → Implement → Test/Debug → Optimize & discuss trade‑offs.
- Follow a 9‑week roadmap: foundation, pattern recognition, advanced patterns, mock interviews, then real interview execution, targeting ~150 curated problems.
- Use the STAR method (20‑10‑60‑10 split) with a story bank; be honest, use “I” statements, and choose the language you’re most fluent in.
Software Engineering: Foundations, Processes, Requirements, Design, Testing, and Maintenance