Previously, when I wrote code, I thought about the one-way dependencies of modules (in this case, a single source file), the orthogonality and compactness of interfaces. I think I’m doing good design with low coupling.

However, I have found that other programmers write code with messy dependencies and bloated interfaces, but they still feel that their code is poorly coupled and well-designed. I realized that I understood coupling differently than they did. They understand low coupling as taking code out of the way so it doesn’t “mess up.” However, they know of no objective measure of what is “coupling” and what is “chaos”.

So now I believe that “coupling” is a ambiguously bad word, and “low coupling” is a theory that programmers often misuse. Instead of using unmeasurable terms like “coupling” and “chaos” when designing architecture and examining the relationships between modules, I suggest using three measurable metrics: dependency, orthodonality, and compactness.

The big difference between dependency and coupling is that when we say “A and B are coupled,” A and B are literally equal. However, the correct module relationship should not be equal at all, but should be a one-way dependency. So we should say “A depends on B”, which is much clearer. A dependency on B means that module A can call the API exposed by module B, but module B is never allowed to call module A’s API. One-way dependence is a red line, and good design must not violate it.

Note: In accordance with the substance over form principle, “dependency” in this article refers to the dependency of the brain, not the dependency of the compiler. A’s dependence on B exists as long as programmers writing module A need to know that module B exists and what functions it provides. Even if module A does not need to import B or include “B.h” through so-called “decoupling” such as named lookups, the dependency in the brain remains the same. The only effect is to fool the code scoring tool, which will be mentioned later, into thinking there is no dependency between the two modules.

Many programmers think “coupling” is a bad thing and write code in circles to eliminate it. But when we switch to the term “dependency”, we find that one-way dependencies are not a bad thing to bother with, because what really matters is whether the interfaces exposed by the dependent parties in a dependency are sufficiently “orthogonal” and “compact”.

Orthogonality refers to whether there is duplication of functionality between multiple methods in the API provided by a module. If you have repetitive functions, you have bad orthogonality. In general, modules with high orthogonality are more stable and do not have to change code because of upper-level business changes. There should be no duplication of functionality between methods in a good API, just an orthogonal mechanism.

If you feel that it is too thin to use, you should wrap a layer of Helper and Utility glue around the underlying API. The glue layer invokes the underlying primitive API to implement common patterns for use by the upper layer. For modules in the glue layer, the requirements for orthogonality can be slightly lower. Note that the upper layer code can call either the orthogonal underlying API directly or the common patterns of the glue layer.

Compactness means that the API provided by a module must have a small number of public methods and a small number of parameters for each method. The Unix Programming Arts says that a module should have no more than seven methods or it will be difficult to understand. However, IN my practice, I usually write modules with no more than 3 public methods.

All in all, the three indexes of one-way dependence, orthogonality and compactness are practical and can be measured by objective methods. I think it might be a good alternative to the “low coupling” theory. The other day, for example, someone on our Consultant mailing list at ThoughtWorks shared tools that automatically check code quality using the above criteria. So when you’re in a fight with another programmer, and you’re telling him that his code sucks, you’ll have something to back it up, because you’ll be able to use the tool to grade the code.

On the other hand, if a colleague or Internet user uses confusing terms like “coupling,” “decoupling,” and “chaos” when discussing programming in the future, you can send him this article and dismiss him.


Forward to Weibo
Forward to Weibo