Swift code metrics

How to measure the metrics of your Swift project.

Mattia Campolese
4 min readFeb 10, 2019
Dependency graph, deviation from the main sequence and code distribution of different example projects

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.

Example of a code distribution graph for an app based on LOC

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.

Example of an internal dependencies graph: the size of the box is relative to the size of the framework and the number indicates the number of imports of that module from the caller
Complete dependencies graph: external dependencies imports are indicated in orange

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)
Example of the deviation from the main sequence graph

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 >

--

--

Mattia Campolese

Engineering Manager, programming aficionado since the early '00