Swift code metrics
How to measure the metrics of your Swift project.
In almost every live software product, code evolves with dynamics that are driven by multiple factors, such as product requirements, architectural decisions, developers skills, tools adopted, dependencies, language maturity and others.
In medium/big size projects, this leads to a growth in complexity that is hard to control without measuring how the codebase is evolving. Assessing the growth of the total LOC (Lines of Code) or the degree of coupling between internal dependencies in a modularized application can give great help in understanding the bigger picture.
There are several paid and open tools for various languages. For Swift, I’m introducing swift code metrics, an open Python package that will analyze your project’s source code directly to inspect for two types of KPIs:
Synthetic metrics
They measure the absolute number of a specific entity, such as:
- LOC (Lines Of Code)
- NOC (Number Of Comments)
- POC (Percentage Of Comments)
- NOM (Number of Methods)
- Number of concretes (Number of classes and structs)
- NOT (Number Of Tests)
- NOI (Number Of Imports)
They can help to understand the distribution of the code inside the project (e.g. by assessing the relative size of a module) or to predict the growth of the software over time.
Modules coupling
For modularized codebases, they measure the degree of coupling between all imported libraries.
The most important one is probably the dependencies graph. It helps to immediately visualize the dependencies between modules (internal or external). The library computes the total number of import
calls from each folder identifying a framework (instead of checking the imports from SourceKit) to immediately understand the general level of coupling.
Another important coupling metric is the distance from the main sequence, that it’s used to represent the relation between the instability and abstraction of an internal component:
D³ = abs( A + I — 1 )
The instability is defined as below:
I = FanOut / ( FanIn + FanOut)
where:
- FanOut: identifies the number of classes inside a component that depends on classes outside the component (outgoing dependencies)
- FanIn: identifies the number of classes outside this component that depend on classes within the component (incoming dependencies)
With I = 1, the component has no dependents and thus unstable and “irresponsible”, making it very easy to change. With I = 0, the situation is the opposite since it doesn’t depend on other components and it has dependents, making it very hard to change.
The abstraction is obtained by:
A = Na / Nc
where:
- Na: number of abstract classes and interfaces in the component
- Nc: number of classes in the component
Not all components should be stable because the system would be hard to change. In general, a component considered stable should be abstract so that it can be easily changed. At the same time, an unstable component should be concrete because its instability allows the implementation inside it to be easy to change.
In an I/A plot, it’s possible to represent the distribution of the components relative to the distance from the optimum ( D = 0 ) and therefore visually determine two areas that should be ideally avoided by a module:
- zone of usefulness: components very abstract with few dependents (mostly useless)
- zone of pain: components that are very ‘concrete’ with a lot of dependents, very rigid and hard to change (e.g. usually foundation libraries)
Additional metrics
In a versioned project (e.g. in a git repository) it can also be possible to compute metrics around code changes over time, such as the git churn rate of certain modules and classes or the overall number of commits/merges. There are already several tools available for scm (some of them provided directly from the host) that are outside the scope of this article.
Get involved
Swift Code Metrics is an open source Python tool available on GitHub (https://github.com/matsoftware/swift-code-metrics).
Please read the documentation and get involved in improving and extending it with your contribution by raising an issue or opening a pull request.
For a more detailed explanation of the distance from the main sequence and on components coupling please read “Clean Architecture: A Craftsman’s Guide to Software Structure and Design (Robert C. Martin Series)”.
📝 Read this story later in Journal.
🗞 Wake up every Sunday morning to the week’s most noteworthy Tech stories, opinions, and news waiting in your inbox: Get the noteworthy newsletter >