Archiv der Kategorie: Swift

Quick architecture review of Signal’s iOS App using SwiftAlyzer

Today, I want to present to you SwiftAlyzer, a tool to review Swift project’s, a tool to help refactoring and keeping it maintainable. As a software architect I find myself oftentimes reviewing projects. Either new projects that are taken over from other companies. Or monitoring the health of an ongoing in-house development. While every feature of a software can be well structured applying design patterns and code heuristics, it’s oftentimes the ensemble of all features to a whole app, that lacks a good structure. It’s where dependencies from one feature reach out to another and back and forth, that lead to an overall maintainance nightmare. Every feature on its own can be quality-checked by looking at the source code, reviewing in so called pull requests to review its quality. It’s hard to get an overview of the inter-class dependencies when looking at source code solely. But often it’s these dependencies that ruin the maintainability slowly but steadily when not supervised.

What makes a good (Swift) software project? That depends on a vast number of variables. In this article I don’t want to start a broad discussion on the „best“ architecture to choose or pinpoint Signal’s weaknesses. My aim is to demonstrate SwiftAlyzer and explain its unique strength as review tool. Therefore I will analyse Signal’s iOS app – but without ever looking at the source code or doing any analysis beforehand.

As mentioned above, I focus on dependencies as a main root of evil. This is explained further below. I try to give more information in these yellow boxes whenever I feel like my arguments could do with some more explanations.

Their’s a lack of tools that support a quick review and an oversight of the app’s structure and its dependencies. That’s why I started SwiftAlyzer. Today I want to demonstrate it’s review capabilities using Signal’s iOS app. If you want to follow along you can get your free copy of SwiftAlyzer on and download Signal’s source code here
(I checked out the develop branch at commit 962369b2676a10da9cf130aa27c87f7c45c325cb)

Analysing the building blocks on 1st level

Displaying the first building block view level zero of Signal iOS app
The first impression are the modules the app is separated into. Swift’s standard libraries (and Cocoapods dependencies) can be shown too, but are hidden by default. These modules are the building blocks on the highest level. We will dive deeper into those later on and see building blocks for every Xcode group down to the classes at the lowest level.
What we see here is the four modules the app consists of and what is immediately noticeable, is the interconnection of each pair of modules. While it’s a good idea to break down big projects into several modules, these should have as few dependencies as possible. Modules should (as far as possible) work on its own, consisting of features that belong together. Features of different modules should (as far as possible) stay independent and therefor should have no connection among each other. The current situation leads to a very high CCD value which is definitely a thing to avoid.

Dependencies are unavoidable, but the number of dependencies should be as low as possible. Since every dependency introduces some complexity. If a class A depends on class B, changes on class B could lead to bugs and incompatibilities in class A. If class B has 10 dependent classes, every change on B could lead to followup changes on those 10 further classes. If furthermore class B depends on a class C, these dependencies sum up and can lead to maintainability nightmares.

The correct term is Cumulative Component Dependency or CCD in short.
It’s defined as follows:
CCD is the sum over all components Ci in a subsystem of the number of components needed in order to test each Ci incrementally. This is true for direct and indirect dependencies. 
SwiftAlyzer calculates this metric for classes, Xcode groups and modules.

The difference between Signal module and Signal Messaging module is not clear, but SignalShareExtension module will probably implement an iOS share extension according to App Extension Programming guide. The NotificationServiceExtension module will be used to implement notification previews, using iOS notification services. So what’s more interesting here is the first mentioned two modules. So let’s dive deeper.

As mentioned before, I didn’t take a look at the source code. But that would not help here too much, since we’re looking at bigger structures than classes. At this level it’s not as easy to guess the purpose of a structuring unit. We can make an educated guess looking at the names and hope that the content follows the semantic proposed by the naming.
At this level I usually resort to architecture documentation like ARC42. But in one of SwiftAlyzer’s upcoming versions, there’ll be a documentation feature. Hovering over or selecting a unit fades in its description – provided as contained readme or so.

Analysing the Signal module and its packages

A deeper look into the „Signal“ module, one of Signal app’s main modules, unfolds a series of packages. There’s a separation of test code from production code and some further packages filled with resources.
A deeper look into the Signal module reveals six packages.

Actually they’re Xcode groups but I like to call it packages which should not be confused with Swift packages. In the Java world packages are the means to structure classes into groups of common functionality. In Swift projects we got Xcode groups to structure classes into bigger units. SwiftAlyzer makes use of classes, Xcode groups and modules to give a higher level overview of the project and its dependencies.

Four resource packages filled with fonts, sounds, Lottie animations and support files. The remaining two are distinct into test and production code. Hiding all resource and test packages and further extending the src package shows the following:
Eight packages inside the src package: Storyboards, User Interface, util, network, Models, Jobs, environment, Calls.
The first thing that comes to mind, is that the Signal messaging module has a bi-directional dependency to almost every package. And a circular dependency to every package due to inter-dependencies among the packages. As mentioned earlier, this breeds a maintenance nightmare and reads as very high CCD value.

The cause of the dependencies between these packages and the Signal Messaging module is left as exercise for the reader 😉 I’ll take a closer look at the inner-package dependencies of the src package further blow.

The second thing that strikes me as odd, is the organisation of content by source type, i.e., user interface, model, Jobs, etc, instead of a feature-based separation. This type of partition does not grow well. When implementing a new feature, it’s models, user interfaces, etc are distributed among several packages, mixed with classes of every other feature. This has two main drawbacks. Firstly, there’s no limit on the growth of a package, which makes it harder to navigate around the Xcode project. Secondly, there’s no (semantic) correlation between the classes of a package, which makes it impossible to plan dependencies on a package or feature level.
A look into the UserInterface > ViewControllers package confirms this issue. There’s a huge amount of ViewController classes, all stuffed together without a semantical connection. With a huge amount of files per package, and a huge amount of dependencies, the project’s complexity explodes and even a package-based visualization gets to its limit. But that is not solely a visualization problem, it’s also an understanding problem. It’s easier to comprehend a feature that consists of 10 files instead of 100. It’s easier to navigate and grasp a project one feature at a time instead of being confronted with all the view controllers at the same time. If a project is separated into distinct features, each as a separate package, it becomes possible to trace and monitor a feature’s dependencies on other parts of the app by tracing it’s package dependencies. If all view controllers of all features are bundled into the same package, it’s impossible to distinguish the good dependencies from the superfluous or wrongly created ones.

Deep dive into a package to discover applied design patterns and infringements

Investigating the inter-dependencies of packages inside the „src“ package. The connections from Model to network package alongside User Interface to network package clearly indicate a lack of communication architecture.
At this level the dependencies disclose a lack of communication plan. Without looking into the source code and investigating the underlying design patterns, a connection from Model to Network indicate a smart, reactive (View) Model. MVVM as a design pattern suggests View layer classes (View Controllers) to use View Models, which in turn take care of data retrieval, typically isolated by Use Case or Interactor classes. Here we see View layer classes (originated from User Interface) using Model classes but also directly classes of the Network module. This mix of communication pipelines further increases the project’s complexity. An application of a common pattern helps to understand and navigate the source code, since one can rely to come across the same structures. Assuming MVVM is the preferred way to go, the illegal dependencies are the ones from the UI layer to the Network layer. To eliminate those lets first hide the other packages. It won’t help much to expand the View Controller package due to its size. Instead the information panel can be used to investigate the incoming and outgoing edges section as seen in the following screenshots:
The incoming edges section lists the ContactViewController and GifPicker classes as directly accessing the Network layer. One improvement can be to move that dependency into the Model layer and eliminate the direct connection to the Network layer. This makes the communication pattern more uniform and thus easier to understand and maintain.

Where to go from here:

If it made you curious feel free to sign up on and try it out on your own! There are more things that can and should be investigated, e.g. why the util package is not a sink.
Also feel free to reach out if you have any questions or comments. Love to hear feedback from other developers ❤️

Smartified Garage Door

Making the best out of Corona-wise cancelled sports evenings, there was suddenly enough time to smartify my garade door. It already has connectors on the garage door hardware. That way, I could connect a button to the board that is used to open and close the garage. But what was missing is a way to control it remotely. Since the remote went missing it was nearby to integrate the button into my smart home setup: Homematic actuators and a raspberry pie transferring all traffic via MQTT.
As there’s already the possibility to control radio-relays via MQTT, the next move was to replace the connection from the button to board with a circuit integrating the relay HM-LC-Sw1-FM.
But there was one problem. The relay works with an input and output voltage of 230V. That’s too much to control the board on the garage opener. So I had to integrate another relay that could switch an arbitrary input voltage but works with a rated Control Supply Voltage of 230V. I finally came up with an relay by Entrelec.

Now to the fun part. Connecting all parts together according to the wiring on the left. The Entrelec relay is directly connected to the garage opener board. The control supply is provided by the Homematic relay. The switch input of the Homematic relay is provided by the hardware button and finally some 230V to feed the relay. That’s it.

In order to test it, there’s no faster prototyping than to use Node-Red. It enables visually wiring up a control that either automates a workflow or provides a rudimentary GUI. In this case, it’s a simple UI consisting of one toggle labeled „Garage“ sending out a message to the MQTT broker to fire up the Homematic relay.
Since that’s quite a boring interface, the next step was to write a control app, fooling around with Combine and SwiftUI. But that’s a story for another time 😉

Swift Dependency Analysis

Almost 3 years ago I started a tool to analyse dependencies of Swift projects. For bigger projects it’s essential to plan dependencies between classes and among modules beforehand. Otherwise a project’s inter-dependencies grow wild and after a while, everything depends on everything.
Why that’s bad you might ask? Because then it’s impossible to replace a class with different functionality, since too many other depend on it. And thus, it gets harder to implement new features, adapt existing features and keep the bug count low. So that’s planning, but what get’s implemented is another story. It’s easy to forget about planned dependencies while implementing and that’s even more true when working in teams of 5, 10 or more people. That’s where tools for visualizing dependencies come into play. Every now and then, one can use these tools to check the actual inter-dependencies of a project and compare them with the planned ones. The existing tools all have one big shortcoming: They ignore ordering structures like modules. All classes are layed out in one space, which gets confusing when visualizing projects with more several hundreds classes:
Demo from
While this visualisation looks quite amazing it renders quite useless overwhelming when trying to check for unplanned dependencies. What’s more helping is a visualisation that considers modules and Xcode groups. Xcode groups can be used to organise a project’s classes in package-like structures.
Xcode project organising its classes into several nested groups
Like in the sample project above, one can see different features of the app organised in separate groups. There’s a Splash screen organised in the Splash group and an Integration group to accomodate a feature to setup smart kitchen appliances and a Network group to shelter the classes communicating to backends, etc. Inter-dependencies can be planned on these structures too. While it’s easily comprehensible why an Integration group is dependent on the Network group, the Splash group shouldn’t.
Swift dependency analysis tool showing one group, one contained file and its embedded class, enum and protocol definitions.
The above dependency tool shows dependencies between classes, enums and protocols. Furthermore, it depicts the groups and files as rectangles collapsable and expandable. When collapsed, the inter-dependencies of all contained elements to other elements outside this structure are still visible but depicted as dependency of the structuring element.
This tool is worked on by David Piper as part of his master thesis. I’m glad to be his advisor and very confident that at the end of his thesis, we’ll see a wonderful tool to supervise the dependencies of Swift projects. What’s even better: As soon as the master thesis is completed, the project will be open-sourced and as a contributor, I’ll gladly keep you updated with more to come feature. So stay tuned ✌️