Visibility Metrics and the Importance of Hiding Things
Learn why it's important to hide the things a module contains from its consumers in microservice architecture.
Join the DZone community and get the full member experience.
Join For FreeIt was 1972 when an early pioneer of software architecture, David Parnas, published his now famous paper called On the Criteria To Be Used in Decomposing Systems into Modules. The idea was to separate design decisions from different modules so that they can be independent from each other:
Changed
Understood
Developed
Tested
(The final entry, "tested," was added by me and is not included in David Parnas publication).
I think we can easily agree that it makes sense to have these kinds of structure in your code or system. But how to achieve this? The key is to hide as many things as possible a module contains from its consumers.
Such a consumer cannot be dependent on things it does not know anything about. This is only possible to some extent, as the API will always make some aspects of the module visible.
How-To
There are a couple of ways to hide internal structures and design decisions from the outside world and from the consumers of a modules API. These days, microservices are very popular. The microservice community argues, that distribution over the network is the one and only way to actually hide the internals of modules (here services). If the network is the only way to access the functionality of such a service, it will be hard (or even impossible) to know about the classes that the service consists of. Where microservices are indeed an excellent way to separate resource-usage and technical choices from each other, it is not true that this is the only way to isolate inner structures and other design decisions of modules. We just need to take a quick look at good old Java, where we already have plenty of options for hiding, even without using tools or proprietary libraries.
A class can hide its members from the outside world by making them private.
Classes inside a package can be defined as package protected, which will make them invisible from outside.
JigSaw modules have an explicit definition of what packages they actually export to other modules.
But is this enough? My experience is, that developers are aware of the importance of hiding, and often create a lot of private members inside classes. But classes themselves are usually by default defined as
public class ClassName
Using this definition as a default is bad because it assumes that other packages might need this class as well. It will only be a matter of time until another developer will reuse this class, even if this was never the intention. Instead, the default in your IDE should rather be:
final class ClassName
Which makes it invisible outside of its package and prevents inheritance, which in most cases does not make any sense at all (see also: composition over inheritance).
If You Can't Measure It, You Can't Manage It
Just recently I was wondering, how to measure how well a piece of software is in hiding things. Surprisingly there was no software metric and no tool so far that offered a possibility to measure this. As it was up to me to come up with a new mechanism to do so, I invented the following Visibility Metrics:
RelativeVisibility (RV) = (NumberOfInnerComponentsVisibleOutside / TotalNumberOfInnerComponents) * 100
AverageRelativeVisibility (ARV) = SumAllRVValues / NumberOfComponents
GlobalRelativeVisibility (GRV) = (NumberOfVisibleSubcomponentsOfAllComponents / NumberOfAllSubcomponentsOfAllComponents) * 100
Looking at this figure, you will see an example, consisting of 2 modules (#1 and #2). When you are familiar with Java, think of the Encapsulating Components as packages and the Inner Components of classes. Component #1 decomposes into 3 further Inner Components called A, B and C, where #2 consists of D, E, F, G, H and I. Inner Components A, D, F, G and H are visible outside of their Encapsulating Components. The metrics described will now calculate:
RV for Encapsulating Component 1 = (1 / 3) * 100 = 33,33%
RV for Encapsulating Component 2 = (4 / 6) * 100 = 66,66%
ARV = (33,33% + 66,66%) / 2 = 50%
GRV = (5 / 9) * 100 = 55,55%
Conclusion
Hiding things is important when designing a sustainable architecture. Controlling this by using metrics and maybe even tool support can be crucial for success. These 3 new Visibility Metrics will provide a mechanism and should be implemented soon in one of the upcoming versions of Sonargraph by hello2morrow. As soon as it is released, download the free version (called Sonargraph Explorer), calculate ARV or GRV of your Java packages, and maybe consider changing the defaults of your IDE afterward.
Opinions expressed by DZone contributors are their own.
Comments