I am the technical reviewer of The Chinese version of Clean Architecture, and I have some insights in the process of review, so I hope to share them with you by writing a guide.

Component aggregation

Component Definition

A component is the smallest unit of software deployment and the smallest entity that can independently deploy the entire software system during the deployment process. For example, for Java applications, Jar packages are components; Components in Ruby are Gem files; Egg or Wheel files in Python as well. Net DLL file.

As we said last time, the nature of programming paradigms is constraints. Subprocedures, classes, or functions are fundamental elements of our programming process, so programming paradigms are the building blocks of programs. If these basic building blocks are compared to the sand stones of a building, then the components in the program can be compared to bricks. The brick process focuses on the ratio of materials, components are the same, the appropriate ratio of foundation components is the basis of component stability. The content composition of components is more difficult to quantify, but in practice it is still governed by guidelines.

Constraint triangle in software engineering

In software engineering, we’ll see a lot of constraints represented by triangles. This is because, in addition to being stable, triangles also exhibit a tension.




Triangulation in software development

In Agile project management, for example, we often hear about the constraint triangle of time, resources, and cost; In distributed computing, the well-known CAP principle (consistency, Availability, and Partitioning fault tolerance) is the same; There is also the impossible triangle (performance, security and decentralization) in blockchain. All of these triangles reflect a constraint — not all of them, trade-offs.

Component aggregation tension diagram

The content ratio of components is finally reflected in the practice of components, which is the disassembly and integration of basic components. Uncle Bob gives three guiding principles for uncoupling: REP (reuse/release equivalence), CCP (Common closure) and CRP (common reuse).




Component aggregation tension diagram

  1. REP (Reuse/distribution Equivalence Principle) : The minimum granularity of software reuse should be equal to the minimum granularity of its distribution
  2. CCP (Common Closure Principle) : classes that have been modified at the same time for the same purpose are placed in the same component; It does not change at the same time, and puts different classes in different components for different purposes
  3. CRP (Principle of common Reuse) : Do not force users of a component to rely on something they do not need

At first glance, these principles may seem like new ideas, but when looked at, they look like old tricks in new bottles. Isn’t CCP SRP? Isn’t CRP ISP (Interface Isolation Principle)? REP, wait, it’s a truism! No wonder some of my architect friends say uncle Bob is getting old and trying to make money out of SOLID again.

When we talk about SOLID, high cohesion, low coupling, stable dependency, and stable abstraction, which part of the software system life cycle are we in? Not surprisingly, everyone started from the point of view of writing source code, that is, Development. However, it is clear that the software system life cycle also includes deployment, release, operation and maintenance in addition to development. So the question is, what are the guidelines that apply in all of this?

Taking a break from the development mindset, let’s analyze these three principles in two ways.

To separate the

The REP principle states a simple principle: software reuse is essential. In the pursuit of software reuse process, gradually formed a standard release process, such as: version number (semantic version), release time, change content and so on. This requires that both modules and classes contained in the component be publishable at the same time, and the underlying meaning of publishable is both a promise to the user and a constraint to the author. Is the component backward compatible? Does it contain disruptive changes? What are the precautions for upgrading?

The CCP principle is to try to put modules and classes in the same component with the same frequency of change. The advantage of this is that when functionality is updated, we can limit source code changes to a single component rather than across multiple components, thus reducing deployment, validation, and release times. In a nutshell, this is the advantage of localized influence. CCP is also related to the “closure” emphasized in OCP (Open and Close Principle). The so-called encapsulation of variable factors is the process of forming a closure. CCP requires the aggregation of changes at the same time to achieve the effect of closure.

The CRP principle says there should be a tacit understanding of component-to-component dependencies — if you don’t need to use all the modules and classes in a component, don’t rely on it. This may seem unlikely, but it is instructive that modules and classes that are not closely linked should not be placed in the same component. Because we know that once a component changes and upgrades, the components that depend on it often change and upgrade passively, even those that have nothing to do with it. Each change means recompiling, deploying validation, and publishing.

Close watch

The REP principle states that software reuse is the foundation, and reuse is achieved by publishing process specifications. In the context of reuse and distribution, the CCP principle requires that modules and classes with the same change frequency should be put into the same reuse unit — component as much as possible for the convenience of later maintenance. The CRP principle to avoid frequent releases, each component should be split small enough to reduce the cascading release reaction of unrelated changes leading to a chain of dependencies.

If we only take into account REP and CCP principles, we run the risk of many unnecessary releases due to a chain reaction of releases; If you only consider REP and CRP principles, you may have too many component changes because you need to change across multiple components to implement a function. If we focus only on CCP and CRP, we may forget about reuse, as we did earlier when we criticized Uncle Bob.

summary

The life cycle of software system is full of constraint conditions everywhere. Every extra link often leads to a contradiction, and then derives constraints in multiple directions. Component aggregation tension diagram reflects the contradiction between release and development. REP, CCP and CRP principles should be followed as far as possible to meet their constraints in order to reduce change costs.

In addition to the principle of aggregation, there is also the principle of coupling, which describes the dependencies of components. The aggregation principle tells us the smallest element in the software system, while the coupling principle refers to the relationship between elements. When these two elements are combined with the functions of the system, a running system is formed [1]. Systems evolve gradually, and even if we are familiar with the PRINCIPLES of REP, CCP, and CRP, there is no way to say that a perfect component structure can be drawn by following these principles at the beginning of system construction. This is the basic explanation for the fallacy of top-down design.

There are deeper reasons why tailor-made designs are unreliable. The answer will be found in chapter 14, “Component Coupling,” which will be broken down next time.