Skip to content

Component Cohesion Principles (REP, CCP, CRP)

Introduction

In software architecture, cohesion refers to how well the elements within a module or component belong together.
At the class level, cohesion ensures each class has one focused responsibility.
At the component level (modules, packages, microservices), cohesion determines:

  • How reusable a component is across systems.
  • How resilient it is to change.
  • How independently it can evolve without ripple effects.

Robert C. Martin (Uncle Bob) identified three key principles that define component-level cohesion:

  1. REP – Reuse/Release Equivalence Principle
  2. CCP – Common Closure Principle
  3. CRP – Common Reuse Principle

These principles guide architects in deciding which classes belong together and how components should be structured for long-term maintainability and scalability.


1. REP – Reuse/Release Equivalence Principle

“The unit of reuse is the unit of release.”

Concept

A component cannot truly be reusable unless it is independently releaseable — with its own versioning, distribution, and release lifecycle.

Think of software like Lego blocks.
Each block (component) can only be reused easily if it’s shaped and standardized correctly — that’s what REP demands.

Why REP Matters

  • Encourages formal versioning and controlled releases.
  • Prevents the “copy-paste” anti-pattern of sharing source code.
  • Promotes stability and consistency across teams or systems.

Without REP, teams end up duplicating code and losing track of which version of a library is being used — making debugging and upgrades painful.

✅ Example: Good REP in Java

java
// Payment module packaged as a reusable JAR
module com.officialcto.payment {
    exports com.officialcto.payment.api;
}

// Public API
package com.officialcto.payment.api;

public interface PaymentProcessor {
    void charge(Order order);
}

Here, the payment module:

  • Has a defined API surface.
  • Can be versioned (e.g., 1.0.0, 1.1.0).
  • Can be reused by multiple services independently.

❌ Violating REP

java
// Payment logic scattered across modules
public class StripeHelper { ... }
public class RazorpayUtils { ... }
public class PaymentValidator { ... }

These classes are scattered, unversioned, and tightly coupled — not releaseable as a single unit.

🔍 Quick REP Checklist

  • [ ] Can this component be versioned and released independently?
  • [ ] Does it have clear release notes or API documentation?
  • [ ] Are its dependencies clearly defined and stable?

2. CCP – Common Closure Principle

“Classes that change for the same reasons should be grouped together.”

Concept

The CCP ensures that when a requirement changes, only one component needs to be modified.
It extends the Open/Closed Principle (OCP) to the component level.

In other words:

If two classes usually change together, they belong together.

Why CCP Matters

  • Minimizes ripple effects when making changes.
  • Keeps build times and testing effort localized.
  • Enhances maintainability — a single change = one component rebuild.

✅ Example: Good CCP

java
// Order domain module
public class Order { ... }
public class OrderValidator { ... }
public class OrderRepository { ... }
public class OrderService { ... }

All order-related classes are grouped together.
If business rules for orders change, only this component is affected.

❌ Violating CCP

java
// Scattered across modules
public class Order { ... }         // in core module
public class OrderValidator { ... } // in utils module
public class OrderRepository { ... } // in repository module

Now, a single change in order logic impacts multiple modules, creating friction and regression risk.

🧠 Analogy

Imagine a restaurant kitchen where the chef, stove, and ingredients are in separate rooms. Every change in the recipe requires coordination across rooms — inefficient and error-prone.
CCP says: Keep everything needed for a specific recipe together.

🔍 Quick CCP Checklist

  • [ ] Do all classes in this component change for the same reason?
  • [ ] Does a requirement change trigger multiple component builds?
  • [ ] Can one team own and modify this component without cross-team coordination?

3. CRP – Common Reuse Principle

“Classes that are used together should be packaged together.”

Concept

If two classes are always reused together, they should be in the same component.
If not, keep them separate — otherwise, consumers are forced to depend on things they don’t need.

This principle focuses on dependency hygiene.

Why CRP Matters

  • Prevents unnecessary dependencies and bloated imports.
  • Keeps build and deploy cycles fast.
  • Makes components lightweight and focused.

❌ Violating CRP

java
// Utility package (bad cohesion)
public class StringUtils { ... }
public class FileUtils { ... }
public class NetworkUtils { ... }

A user who only needs StringUtils is forced to import and depend on FileUtils and NetworkUtils too — adding unnecessary baggage.

✅ Following CRP

Break it into separate components:

string-utils.jar
file-utils.jar
network-utils.jar

Now, consumers pick only what they need — lightweight, decoupled, and flexible.

🧠 Analogy

Buying a combo meal when you only wanted fries wastes resources and money.
CRP tells us: Package only what users always consume together.

🔍 Quick CRP Checklist

  • [ ] Do consumers of one class always use the others in this component?
  • [ ] Are unnecessary dependencies being introduced?
  • [ ] Would splitting this module make it easier to maintain or reuse?

⚖️ Balancing REP, CCP, and CRP

These principles often pull in different directions:

PrincipleEncouragesRisk if Over-Applied
REPLarger componentsHarder to modify quickly
CCPGroup by reason to changeComponents may grow large
CRPSmaller componentsToo many micro-modules, hard to manage

Visualizing the Tension

mermaid
graph LR
  REP[REP: Reusable & Releaseable] -->|Pushes| Large[Large Cohesive Components]
  CCP[CCP: Change Isolation] -->|Pushes| Focused[Focused Domain Modules]
  CRP[CRP: Dependency Hygiene] -->|Pushes| Small[Smaller, Reusable Parts]

Finding the sweet spot is the art of component design.
Well-balanced systems minimize change impact while maximizing reuse.


🧪 Real-World Case Studies

1. Android SDK

  • REP: Released as versioned SDKs (API 30, 31…).
  • CCP: Related APIs (e.g., UI widgets) grouped together.
  • CRP: Networking, storage, and UI packages separated.

2. Spring Framework

  • REP: Entire Spring stack versioned (e.g., 5.x, 6.x).
  • CCP: Spring Web, Spring Data, and Spring Security are logically grouped.
  • CRP: Developers can import only spring-web without pulling spring-data.

3. Amazon Microservices

  • REP: Each service is versioned independently.
  • CCP: Each domain (Orders, Inventory, Payments) is isolated.
  • CRP: Teams depend only on APIs they actually consume.

⚠️ Common Pitfalls

PitfallViolationImpact
God ModulesCRPForces consumers to depend on unrelated code
Over-FragmentationREPToo many small modules, heavy release management
Scattered Domain LogicCCPChanges ripple across multiple components

🧩 Extended Java Case Study

Scenario: Payment & Order Services

❌ Bad Design

java
// payment scattered across utils and repositories
public class PaymentHelper { ... }
public class PaymentUtils { ... }
public class OrderRepository { ... } // also has payment logic
  • Payment logic spread across unrelated modules.
  • Hard to reuse or version as one unit.
  • Changes ripple through the system.

✅ Good Design

java
// Payment module
public interface PaymentProcessor { void charge(Order order); }
public class StripeProcessor implements PaymentProcessor { ... }
public class RazorpayProcessor implements PaymentProcessor { ... }

// Order module
public class Order { ... }
public class OrderService { ... }
public class OrderValidator { ... }

Results:

  • Payment module = independently releasable (REP).
  • Order module = isolated from unrelated changes (CCP).
  • Consumers depend only on what they need (CRP).

💬 Interview Prep

Q1: What are the component cohesion principles?
A: REP, CCP, and CRP — they define how to group classes into stable, reusable components.

Q2: How do REP and CRP conflict?
A: REP encourages larger, stable components; CRP encourages smaller, reusable ones. Architects must balance them contextually.

Q3: Example of CCP in action?
A: Grouping all order-related logic in one module so business rule changes affect only that component.

Q4: What happens when CRP is violated?
A: Consumers depend on unnecessary code, creating bloated dependency graphs.

Q5: How do these apply in microservices?
A: Each microservice should group logic that changes together (CCP), be versioned independently (REP), and avoid exposing unneeded APIs (CRP).


🧭 Key Takeaways

PrincipleEssenceGoal
REPReuse = ReleaseEnables reuse through independent versioning
CCPChange TogetherMinimizes ripple effects from change
CRPUse TogetherPrevents unnecessary dependencies

Balancing these three is the hallmark of a modular, maintainable architecture.


🔗 Next Lesson

Now that we understand how to group components, the next step is to learn how they should depend on each other — the Component Coupling Principles (ADP, SDP, SAP).

Continue to Component Coupling Principles →


Connect: LinkedIn

© 2025 Official CTO. All rights reserved.