Skip to main content

High Cohesion

Keep class responsibilities focused and strongly related to its purpose

TL;DR

High Cohesion is a principle that encourages classes to have a single, well-defined purpose with responsibilities that are closely related to each other. Classes with high cohesion are easier to understand, test, reuse, and maintain because all their functionality focuses on accomplishing one clear goal.

Learning Objectives

  • Understand what cohesion means and its relationship to class design
  • Learn to identify low-cohesion classes that need refactoring
  • Apply techniques to improve cohesion in your designs
  • Balance High Cohesion with Low Coupling for optimal designs
  • Recognize when a class has too many unrelated responsibilities

Motivating Scenario

You have a UserManager class that handles user authentication, email sending, file storage, and database queries. When you need to change how emails are sent, you must modify UserManager, affecting authentication logic. If instead responsibilities are split so each class handles one concern, changes are localized and tests are simpler.

Core Concepts

Cohesion measures how strongly related and focused the methods and variables in a class are. High Cohesion means a class has a single, clear responsibility, with all its methods working together toward that goal.

Low cohesion creates problems:

  1. Difficulty Understanding: Classes do too many unrelated things
  2. Difficulty Testing: Testing one responsibility requires creating complex test setups for others
  3. Difficulty Reusing: A class doing five things can't be reused when you need only one
  4. Difficulty Maintaining: Changes to one responsibility affect the entire class
  5. High Coupling: Unrelated responsibilities create unnecessary dependencies

High cohesion benefits include:

  • Clarity: Each class has one clear purpose
  • Testability: Testing focuses on one responsibility
  • Reusability: Classes can be used in different contexts
  • Maintainability: Changes are localized
  • Extensibility: New functionality fits cleanly into the design

Achieve High Cohesion by keeping methods closely related, with strong relationships between attributes and methods. If you find yourself explaining a class as "it does X and Y and Z," it probably has low cohesion.

High Cohesion: Focused Responsibilities

Practical Example

Let's refactor a low-cohesion class to achieve High Cohesion:

high_cohesion_example.py
# LOW COHESION (avoid this)
class LowCohesionUserManager:
"""Does too many unrelated things"""
def authenticate(self, username, password):
# Authentication logic
return username == "admin"

def send_email(self, recipient, message):
# Email logic
print(f"Sending email to {recipient}")

def save_file(self, filename, content):
# File storage logic
with open(filename, 'w') as f:
f.write(content)

# HIGH COHESION (good design)
class AuthService:
"""Single responsibility: authentication"""
def authenticate(self, username: str, password: str) -> bool:
# Authentication logic only
return username == "admin"

def validate_password(self, password: str) -> bool:
return len(password) >= 8

class EmailService:
"""Single responsibility: sending emails"""
def send_email(self, recipient: str, message: str) -> bool:
# Email logic only
print(f"Sending email to {recipient}: {message}")
return True

class FileService:
"""Single responsibility: file operations"""
def save_file(self, filename: str, content: str) -> bool:
# File storage logic only
with open(filename, 'w') as f:
f.write(content)
return True

class User:
"""High cohesion: only user data"""
def __init__(self, username: str, email: str):
self.username = username
self.email = email

class UserController:
"""Coordinates multiple services for user operations"""
def __init__(self, auth: AuthService,
email: EmailService, files: FileService):
self.auth = auth
self.email = email
self.files = files

def register_user(self, username: str,
password: str, email: str) -> bool:
if not self.auth.validate_password(password):
return False

user = User(username, email)
self.email.send_email(email,
f"Welcome {username}!")
return True

# Usage
auth = AuthService()
email = EmailService()
files = FileService()
controller = UserController(auth, email, files)

controller.register_user("john", "password123", "john@example.com")

When to Use / When Not to Use

Use
  1. Keeping each class focused on one responsibility
  2. Grouping only closely related methods and attributes
  3. Naming classes after what they do, not what they contain
  4. Splitting classes when they become too focused on unrelated tasks
  5. Designing for clarity and maintainability
Avoid
  1. Creating classes that do multiple unrelated things
  2. Mixing different concerns in a single class
  3. Over-fragmenting into too many micro-classes
  4. Separating related operations into different classes
  5. Designing for imagined future needs too early

Patterns and Pitfalls

High Cohesion Implementation

Keep methods related: Methods in a class should work together. If a method seems unrelated, it might belong elsewhere.

Use descriptive names: Name your class after its single purpose. If you need "and" in the name, it might have multiple responsibilities.

Split when cohesion drops: If you find yourself explaining a class as "it does X, Y, and Z," split it. Each class should do one thing well.

God objects: Don't create classes that do everything. AuthService, EmailService, and FileService should be separate, focused classes.

Feature envy: If a class frequently calls methods on another class to get work done, that work might belong in the other class (Information Expert).

Over-splitting: Don't fragment related operations. If methods work closely together and modify the same state, they belong in the same class.

Design Review Checklist

  • Can you describe the class's purpose in one sentence?
  • Do all methods work together toward that purpose?
  • Are attributes used by most methods?
  • Could you reasonably split this class into smaller focused classes?
  • Would the class be easier to test if it had fewer responsibilities?
  • Do changes to one responsibility require modifying unrelated code?

Self-Check

  1. What is cohesion and how does it relate to class design? Cohesion measures how focused a class is. High cohesion means all methods work together toward one clear purpose.

  2. How do you improve cohesion? Split classes that have multiple unrelated responsibilities. Each class should do one thing well.

  3. How does High Cohesion relate to Low Coupling? They work together: High Cohesion keeps each class focused (internal organization), while Low Coupling limits dependencies between them (external relationships).

info

One Takeaway: Keep each class focused on one clear responsibility. All methods should work together toward that single purpose, making classes easier to understand, test, and maintain.

Next Steps

References

  1. GRASP (Object-Oriented Design) - Wikipedia ↗️
  2. Applying UML and Patterns by Craig Larman ↗️