Skip to main content

Why We Use Clean Architecture to Implement Robust Air Traffic Control Systems

Manuel Ángel Suárez
September 13, 2023

Introduction:

Air traffic control systems play the pivotal role in maintaining the safety and efficiency of air travel in the aviation industry. These systems are considered critical infrastructures as they require exceptional reliability and safety to manage the complexity of airspace and to coordinate the movements of numerous aircraft. In recent years, machine learning has been increasingly integrated into these systems to enhance their capabilities and performance.

As the popularity of machine learning grows within air traffic control systems, so does the demand for robust and dependable ML models. These models must be able to process and analyse the intricate and variable nature of real-world data, ensuring that they can effectively contribute to safe and efficient airspace management. Furthermore, machine learning models in air traffic control must operate in conjunction with manually crafted business rules that have been developed by domain experts. These rules provide the necessary constraints and guidelines that enable the models to make accurate and informed decisions. As such, these rules must be incorporated into the design of the ML pipeline to ensure that the system is both effective and secure.

However, designing and implementing such models presents significant challenges.  In particular, it can be difficult to create pipelines that are both robust and adaptable to changing conditions. ML pipelines can become unwieldy and difficult to maintain if not designed with care, leading to potential errors and security risks. Considering that machine learning pipelines are essentially software systems, software design principles must be applied to these systems in order to improve their flexibility, effectiveness, and reliability. This is where the concept of Clean Architecture comes into play.

Understanding Clean Architecture:

Clean Architecture is a software design philosophy that emphasises the separation of concerns and independence of components. It is a set of principles and practices for creating robust, scalable, and maintainable software systems that are easy to understand, modify, and extend.

The core idea of Clean Architecture is to separate the business logic of an application from the technical details of how it is implemented. This is achieved by dividing the system into layers, where each layer has a well-defined responsibility and communicates only with inner layers through clear interfaces.

There are different flavors of Clean Architecture, each with its own set of guidelines and recommendations. However, they all share some common characteristics:

  1. Independence of Infrastructure: Clean Architecture advocates for a clear separation of concerns between the application’s business logic and the technical details of the frameworks used to build it. This means that the application should be built in a way that allows it to function independently of any particular infrastructure tool (think databases, frameworks, etc).
  2. Testability: Clean Architecture emphasises the importance of designing software that is easy to test. This means that the business logic of the application should be isolated from any dependencies that may be difficult to test, such as databases or external APIs.
  3. Separation of Concerns: Clean Architecture separates concerns by organising the application into distinct layers, each with its responsibility. This makes it easier to reason about the system as a whole and modify individual components without affecting the rest of the system.
  4. Dependency Inversion: Clean Architecture recommends that dependencies should be inverted, meaning that high-level components should not depend on low-level components. Instead, both should depend on abstractions. This reduces coupling and allows for greater flexibility and modularity.

If you have ever done some research about clean architecture, you have likely come across different versions of the concentric circle diagram shown above. This is because there are a variety of architectures that follow the principles above, such as clean architecture introduced by Uncle Bob,  Hexagonal Architecture, Onion Architecture, Explicit Architecture, etc. Even though they have slight differences, all of them share the common goal of creating software that is maintainable, scalable, and adaptable to changing requirements.

How we structure our code:

We use the three classic layers of the clean architecture with a domain, application, and infrastructure layer.

  • The Domain layer is the heart of the system and encapsulates the core business logic. It contains models, such as Entities and Value Objects, which represent the business’s essential concepts and rules. Additionally, this layer houses the driven ports definition.
  • The Application layer serves as a bridge between the domain and the external world. It contains the definition of the driving ports, which are interfaces that dictate how the application will interact with the domain, and use cases, which define the system’s behavior in terms of its domain model.
  • Last but not least, the Infrastructure layer provides concrete implementations for the driven ports defined in the Domain layer and wraps around the driving port definitions in the application layer. This layer may include adapters for REST APIs, database connections, or other external services necessary for the system to function. By containing all infrastructure-related concerns in a single layer, it is very easy to swap out or modify components without affecting the domain or application layers. This separation ensures that changes to external dependencies have minimal impact on the overall system and makes testing much simpler.

Conclusions:

I hope this article has provided you with some reasons to consider exploring the application of clean architecture principles in your ML system. Clean architecture has proven to be an incredibly productive paradigm, enabling rapid progress in the early stages of the modeling lifecycle with minimal investment while maintaining code quality suitable for later production use without costly rewrites.

The inherent uncertainty in any ML product often necessitates revisiting earlier phases of the modeling process in order to incorporate new insights and safely integrate them into the pipeline. Clean architecture helps to minimise expensive friction points, thus accelerating your iteration loop.

Employing clean architecture is just one step towards the goal of building clean code. There are additional aspects to consider, such as the use of clean architecture in conjunction with Domain Driven Design, following the SOLID principles, DRY, KISS, loose coupling, high cohesion, locality of change, and manageable-sized components, among others.

Author: Manuel Ángel Suárez