Component Principles - vanskarner/CleanMovie GitHub Wiki
Components for principles can be viewed as the grouping of classes or other software artifacts that have a single purpose within a system and can be linked to other components.
On the other hand, component principles are indications of how to build and relate components in an architecture. There are two types of principles: Cohesion Principles and Coupling Principles, each composed of three principles:
Principles that determine the assignment of classes or other software artifacts in a component.
The granule of reuse is the granule of release.
- Robert C. Martin (Uncle Bob), Clean Architecture: A Craftsman’s Guide to Software Structure and Design, 2017
A component must be composed of software artifacts that share a purpose and a meaningful reason to be together for release.
Gather into components those classes that change for the same reasons and at the same times. Separate into different components those classes that change at different times and for different reasons.
- Robert C. Martin (Uncle Bob), Clean Architecture: A Craftsman’s Guide to Software Structure and Design, 2017
A component must have a closure strategy to minimize possible changes in the face of a change in requirements.
This principle is an extension of SRP, as it aligns with the description: "A component should not have multiple reasons to change". Furthermore, it is related to OCP, as it aligns with the description: "Bring together in the same component that which is closed to the same types of change".
Don’t force users of a component to depend on things they don’t need.
- Robert C. Martin (Uncle Bob), Clean Architecture: A Craftsman’s Guide to Software Structure and Design, 2017
A component should contain software artifacts that tend to be reused together, while those that are not closely linked to each other should not be part of the component.
This principle is an extension of ISP, as it aligns with the description: "Do not depend on components that have classes or modules that you do not need".
The following diagram was created based on the one presented in the book Clean Architecture: A Craftsman's Guide to Software Structure and Design (2017) and only a few elements were added.
| Diagram |
|---|
| This diagram represents the conflicting effects of the 3 cohesion principles when structuring components and helps us to identify and balance certain architectural concerns. For example, if we focus only on the CCP and CRP principles, the result will be a component that is difficult to reuse. It is also noted that following the REP and CCP principles increases the size of the component, while following the CRP principle does the opposite. |
![]() |
It is important to note that the structure of the components must respond to the current need, which is more related to the way the project is developed and used than to its actual functionality. Therefore, components will be placed in different positions in the diagram as the software system evolves and matures over time.
Principles that define how the components are related.
Allow no cycles in the component dependency graph.
- Robert C. Martin (Uncle Bob), Clean Architecture: A Craftsman’s Guide to Software Structure and Design, 2017
The dependency between components must be free of cycles, either by creating a new component or by applying dependency inversion to break the cycles.
| ADP Violation | Solution 1: Create a new component |
|---|---|
| We can see that there is a cycle represented by red arrows between the User, Project and Authorization components, which is a violation of this principle. | To break this cycle, a new component can be created in which the common elements for Project and Authorization would be placed. In this way, both components would depend on the new component Permissions |
|
|
| Solution 2: Dependency inversion |
|---|
| Another way to break this cycle is to resort to dependency inversion. For example, the Project component declares the services it needs, as in the case of Permissions, and the Authorization component implements that service. |
|
Depend in the direction of stability.
- Robert C. Martin (Uncle Bob), Clean Architecture: A Craftsman’s Guide to Software Structure and Design, 2017
Any volatile component should not depend on another component that is difficult to change, as it will also become complicated to change.
SDP aims at stability, where a component is considered stable when several other components depend on it, while it is considered unstable when it has no components that use it.
| Example: Stable and Unstable Component |
|---|
![]() |
SDP has a formula called Instability (I) and states that the metric I of a component must be greater than the metric I of the components on which it depends.
| Formula | Description |
|---|---|
|
I: Instability Fan-in: Number of external classes with incoming dependencies Fan-out: Number of internal classes with outgoing dependencies Where: I : range [0,1] I = 0 : Maximum stable component I = 1 : Maximum unstable component |
| Example: Calculating the metric in the User component |
|---|
| Metrics in Component User:: The value of Fan-in is 3 The value of Fan-out is 1 Therefore: It is useful when diagramming to place the changeable (unstable) components at the top, as shown with the Presentation and Persistence components, because if we notice arrows pointing upwards, they would imply a violation of the SDP and also of ADP. This is because stable components should not depend on unstable components. |
![]() |
| PDS violation |
|---|
| In this case, the Authentication component is designed to be easily modified (unstable) when necessary. However, someone in charge of the User component has established a dependency on Authentication, which causes any changes to Authentication to impact User and its dependents. Furthermore, if we compare the metrics of 0.33 for User and 1 for Authentication, this indicates an SDP violation. |
|
| Solution to the above problem |
|---|
| We can solve this problem by applying dependency inversion, which would result in the creation of a new abstract component called GeneralServices. In this abstract component, we place the abstraction that will use User and the one that will implement Authentication, so that the metrics for each component match. These abstract components are a common tactic in statically typed languages such as C# and Java, but do not exist in dynamically typed languages such as JavaScript and Python, as they do not require it. |
|
A component should be as abstract as it is stable.
- Robert C. Martin (Uncle Bob), Clean Architecture: A Craftsman’s Guide to Software Structure and Design, 2017
A stable component must be abstract to allow its extension through the use of interfaces, abstract classes or other abstract artifacts, and is oriented to encapsulate high-level policies. On the other hand, an unstable component must be concrete and include volatile software that can be easily changed.
This principle in conjunction with SDP is an extension of DIP for components.
SAP has the Abstractness (A) formula and its value represents the ratio of interfaces and abstract classes in a component to the total number of classes in the component.
| Formula | Description |
|---|---|
|
A: Abstractness Na: Number of abstract classes and interfaces in the component Nc: Number of classes in total of the component Where: A : range [0,1] A = 0 : Maximum concrete component A = 1 : Maximum abstract component |
| Example: Calculating the metric in the User component |
|---|
| Metrics in Component User: The value of Na is 3 The value of Nc is 6 Therefore: It can be observed that the User and Publication components are as stable as they are abstract. This abstraction allows them to be extended and, in addition, these components include high-level policies. |
![]() |
The following graphic is based on the one shown in the book Clean Architecture: A Craftsman's Guide to Software Structure and Design (2017). It helps us identify the areas to target (green zone) and the areas to avoid (red zone) when distributing the metrics shown in SDP and SAP for each component.
🟥 Exclusion Zones: In general, avoid having your components in the zone of pain and in the zone of futility.
- Pain zone: The components located here are difficult to change and extend. In this area you can find database schemas, utility libraries, among others.
- Zone of Uselessness: The components located here are unused software elements because they are very abstract and without dependencies. Interfaces or abstract classes that were never implemented can be found in this area.
🟩 The Main Sequence: This is the most desirable area where the components should be located. We should aim at the ends of the main sequence (green dots) or close to it (green line).
| Example: Locating components on the Instability/Abstraction Graph |
|---|
| It is essential to emphasize that this example is merely illustrative. To achieve a more adequate representation, it would be necessary to include many more components, and within these components, many more software elements. |
![]() |
This metric represents how far a component is from the Main Sequence. If the D metric of a component is not close to zero, it is advisable to review it and, if necessary, restructure it.
| Formula | Description |
|---|---|
|
D: Main Sequence Distance A: SAP Metric I: SDP Metric Where: D : range [0,1] D = 0 : The component is directly in the main sequence D = 1 : The component is as far away from the main sequence as possible. |
| Example: Calculating D in the User Component |
|---|
| Metrics in Component User: The value of A is 0.5 The value of I is 0.25 Therefore: |
![]() |
| Example: User Component Tracking |
|---|
| We can apply control limits when analyzing the versions of a component and its Main Sequence Distance metrics. For example, let's imagine that the User component has several versions, as shown in the image; in this case, we can notice that the control limit is exceeded in version 2.2, so it would be desirable to analyze this version. |
![]() |
All the metrics presented are not absolute laws, they are simply references to be taken into account when analyzing the components of an architecture. Also, all the examples presented are merely illustrative, as they should include many more software elements.











