Building Software Like a Bag of Marbles: A ‘SOLID’ Approach for Software Developers

Updated on August 23, 2023

Hannes Lowette highlights the importance of using SOLID principles and the Onion Architecture to build modular and robust software systems.

The way we construct our applications has a profound impact on their maintainability, scalability, and adaptability. Imagine a world where your codebase is as easy to rearrange as a bag of marbles, where adding or removing features doesn't require tearing down entire sections like a Lego castle. This analogy forms the basis of a compelling talk given by Hannes Lowette, Head of Learning and Development at Axxes IT Consultancy at YOW! London 2022. Hannes focuses on the importance of using SOLID principles and the Onion Architecture to build modular and robust software systems.

The Transition to SOLID

Every developer has been through the phase of crafting their first "big ball of mud." A tightly coupled and complex system that quickly becomes unwieldy to manage. This is where the journey of software development starts, but it doesn't have to end there. Hannes emphasized the pivotal transition from chaotic code to a structured one by introducing the SOLID principles.

Solidifying the Code

As we know, SOLID is an acronym that represents a set of design principles that guide developers toward creating maintainable, scalable, and flexible code. While it's common to encounter challenges while initially applying these principles, they become remarkably powerful once grasped. The turning point often occurs when realizing that interfaces should be owned by the consumer. Instead of extracting interfaces from existing implementations, developers should first define what they expect from an implementation. This shift in perspective lays the foundation for a more modular and adaptable codebase.

From Lego Castles to Bags of Marbles

Picture a Lego castle, an intricate structure where replacing a single component often necessitates dismantling large portions. Now envision a bag of marbles, where elements can be effortlessly swapped in and out. The goal of a well-structured software system should always resemble the latter. Properly applying SOLID principles leads to code that is modular and easily reconfigurable. Hannes draws a parallel between these visualizations and emphasizes how SOLID principles make the codebase more malleable and adaptable to change.

The Onion Architecture

As developers strive for a cohesive and modular codebase, architecture becomes pivotal. Hannes advocates for the Onion Architecture, a concept that promotes clear separation of concerns and a structured application layout. In this architecture, the core domain model is at the center, free from any external references. Around it, layers of application logic and services are built, encapsulating different aspects of the software. How can one facilitate modularity through Onion Architecture, you ask? 

The essence of Onion Architecture lies in the unidirectional flow of dependencies. External integrations, such as databases, UIs, and file systems, reference the core domain, not the other way around. This architecture encourages the definition of interfaces within the core before building external integrations, ensuring clean and adaptable integrations. The modular structure also greatly aids testing, enabling distinct unit tests, integration tests, and acceptance tests, each in their appropriate layers.

Solving the Right Problem

Distributing a software system should only be pursued when it's necessary. Often, developers are eager to introduce complex deployment setups, but this can backfire if the underlying codebase isn't properly structured. According to Hannes, a pragmatic approach is key: start with a monolith and only transition to distributed systems when justified. "Never solve a code problem by introducing a deployment problem," serves as a reminder that clean code should precede complex distribution strategies.

Plugins: Adding Functionality Without Complexity

For scenarios where modular expansion is crucial, Hannes introduces the concept of plugins. Plugins are assemblies that add or remove functionality to an existing codebase without disturbing the core architecture. These plugins follow the same principles as the Onion Architecture – referencing the core, maintaining separation of concerns, and adhering to defined conventions. The startup behavior and dependency injection container facilitates the dynamic loading of plugins, enabling features to be toggled easily without disrupting the core system.

While the concept of plugins is empowering, it comes with its own set of challenges. These include integrating new UI elements or APIs into a monolithic structure, handling polymorphic deserialization, and managing database migrations. However, once these challenges are addressed, the system becomes incredibly agile, allowing developers to add, test, and remove features without destabilizing the core application.

Embrace Solid Principles and Modular Architecture

Crafting software like a bag of marbles – modular, adaptable, and flexible – is not only achievable but essential. By embracing SOLID principles, Onion Architecture, and the concept of plugins, developers can construct software systems that withstand change and effortlessly accommodate new features. This talk by Hannes serves as a compelling guide for software developers to create codebases that are not only functional but also built to evolve.