rss twitter gitlab github linkedin linkedin instagram
Software Architecture in Go: Measuring Instability as Software Package Metrics
Jun 18, 2021

Disclaimer: This post includes Amazon affiliate links. If you click on one of them and you make a purchase I’ll earn a commission. Please notice your final price is not affected at all by using those links.

Building software goes beyond to only writing the required code and making it live, it involves collecting and keeping track of metrics of that said software. This data is used to keep a history of its performance and to define a baseline we can refer to when releasing new versions, it’s an indicator that tells us how a new version compares to a previous one.

It helps answer the question: Did the new version make things better or worse?.

Those metrics involve the well-known ones that usually refer to web services like latency and requests per minute but also include those that apply to the actual code.

In this post I will cover one specifically to measuring code: Coupling.



What is Coupling?

In the context of software packages, coupling:

… indicates the degree of interdependence between software modules.

Coupling

This definition is attributed to Robert Martin in a book he published in 2002 called Agile Software Development. The book also includes a mathematical formula to calculate the instability of a package:

Formula to calculate instability

Which reads as:

… instability can be calculated as the ratio of Efferent Coupling to Total Coupling.

Where Total Coupling is the sum of Efferent Coupling (Ce) and Afferent Coupling (Ca).

Formula to calculate instability - 2

Let’s describe both types of couplings.

What is Efferent Coupling?

It refers to Outgoing Dependencies: the amount of dependencies a package has with relation to other packages, for example a package A depends on B, C, D and E.

Efferent

What is Afferent Coupling?

It refers to Incoming Dependencies: the amount of dependencies other packages have in relation to another one, for example a package B, C, D and E depend on A.

Afferent

Measuring Instability in Go

If we humanize the variables a bit more, the formula above can be read as the following:

The ratio of Outgoing Dependencies to the sum of both Outgoing Dependencies and Incoming Dependencies.

Formula Translated

The result of this calculation determines how stable or unstable a package is:

  • The closer it is to 0 indicates a stable package, and
  • The closer it is to 1 indicates an unstable package.

Rephrasing the above results means that Instability indicates the amount of work required to make a change to a particular package, how much effort will be required when modifying existing code.

The code used for this post is available on Github.

In Go the tool I’ve used for creating a report of coupling details is spm-go, this tool allows you to generate reports for things like Instability and Dependencies.

To install spm-go you can use (in Go 1.16 or higher):

go install github.com/fdaines/spm-go@v0.11.1

If you use Go 1.15 or lower you can refer to the tools.go paradigm so you can track it part of your go.mod dependencies.

As an example we can use our To-Do Microservice Project which I’ve used in the past, running the following command:

spm-go instability --html

Will generate an output similar to:

spm-go report

That allows us to clearly see the total instability for each package included in our project.

If you notice internal in this case is considered stable, this is because internal represents our domain types and all other packages depend on it; making changes to an stable package is more difficult because of that, breaking API for example will require more effort.

On the other side a package like main (in cmd/cli) is consider unstable, this is because this package is literally connecting all the dots from other packages, making changes to this package is easier because no other package depends on it, so we have the freedom to refactor and make changes as we see fit.

Conclusion

Measuring Instability looks like an overkill but really the goal of doing it is to determine how easy or difficult making a change could be. Determining the package’s instability allows us to provide a better estimate when thinking about improvements, it may sound overcomplicated but the goal is clear: to help us identify problematic packages that can make future changes more difficult.

If you’re looking to sink your teeth into more Software Architecture-related topics I recommend the following books:


Back to posts