Component Principles

1 minute read

The following notes are from Uncle Bob’s Clean Architecture.

In Clean Architecture, components are defined as groups of related classes which are revision controlled together.

Component Cohesion

The following principles help determine how to break a product into components.

REP - Reuse/Release Equivalence Principle

Consumers of a component library can only use that library with releases. Functionality that is grouped together must make sense as being releasable together.

CCP - Common Closure Principle

Components are made up of functionality that change for the same reasons. Similar to the Single Responsibility Principle.

The purpose of this principle is to simplify the release process. We don’t want divergent change in our components; or even worse, shotgun surgery across components.

CRP - Common Reuse Principle

Gather functionality that is reused together in the same component. Separate functionality that is not reused together into seperate components. Similar to the Interface Segregation Principle.

The purpose of this principle is to make the component better for the users. We don’t want the user’s code to have to depend on functionality that they don’t need.

Component Coupling

The following princinciples help determine how to handle dependencies between components.

Dependency Inversion is important to acheive these principles.

ADP - Acyclic Dependencies Principle

Cycles are not allowed in the dependency graph.

SDP - Stable Dependencies Principle

Depend in the direction of stability.

Instability of a component is defined mathematically:

\[I = \frac{N_{fan-out}}{N_{fan-in}}\]

Where:

  • \(I \in [0, 1]\) is instability
  • \(N_{fan-in} \ge 0,\) is the number of classes this component’s classes depends on.
  • \(N_{fan-out} \ge 0,\) is the number of classes that depend on this component’s classes.

Generally speaking, stable components are difficult to change and have reliable interfaces.

SAP - Stable Abstractions Principle

Components should be as abstract as they are stable.

There’s a formula for this too:

\[A = \frac{N_a}{N_c}\]

Where:

  • \(A \in [0, 1]\) is abstractness
  • \(N_a \ge 0,\) is the number of abstract classes
  • \(N_c \ge N_a,\) is the number of classes

It basically means use interfaces for stability.