Code Architecture – Laying The Foundations | Opinionated Pattern Picking

Welcome to Opinionated Pattern Picking (OPP), a monthly session we run at Arinco to foster an environment of discussion and learning for our application developers and anyone else interested. Each month the team discusses a topic and attempts to elect a “best default” pattern for developers to use on future projects. View the rest of the blog series here.


What solution are we designing for?
Instead of looking to build an enterprise solution, we take the approach of starting with a straightforward solution: we create a solution that involves an API and some data that can be retrieved either in response to an end-user request or by a daemon service running in the background. This simple approach is still quite detailed, providing us with enough substance to delve into before adding further complexity.



December – Clean Architecture vs Domain-Driven Design vs Modular Monolith

The opinionated pattern picking session this month explored three architectural approaches that have been around in one form or another for quite a while now, which gave everyone lots of opinions to pick from. We went through examples of what each architecture is, defined their particular nuances, and discussed which one we should use.

Pattern Picking

Clean Architecture

To start we discussed clean architecture, which involves frameworks, controllers, presenters, and gateways that feed into the domain layers, with entities and business rules at the core. The discussion revealed that one of clean architecture’s main strengths lies in being opinionated and removing cognitive load for people trying to figure out where to put things, allowing developers to defer decisions or have an opiniated decision making framework. Therefore, the architecture decides for you, which enforces consistency across the project.

Another advantage noted was that project-based clean architecture is the only time you can actually do separation of concerns at compile time, allowing you to structurally enforce which project can depend on which project. However, maintaining all these layers to map between results requires significant code, with DTOs everywhere just to maintain the layers. Some participants felt this created overhead for smaller applications with lots of contracts and mappers. The group noted that while some view creating separate projects as overhead, it’s actually relatively easy to create and having this foundation in place helps when the project gets complex.


Domain-Driven Design

The discussion highlighted that DDD isn’t really a software architecture, it’s a methodology. The group found DDD to be much more relatable to business language and particularly effective when you have a very clear understanding of business use cases. It helps get business understanding of why you’re building something, which proves valuable throughout the project lifecycle.

However, several issues were raised during the discussion. The group noted that domains can be hard to define, and handling separation of concerns presents its own difficulties. DDD is big, it’s a lot to learn and you need to really know it all. It needs to be well disciplined and maintained, and as consultants, it’s particularly hard to understand the boundaries.

An interesting point raised was whether DDD makes sense in consulting. The group discussed that walking into an organisation and saying “we’re going to do DDD” might be too heavy-handed, though it could work well for organisations ready to adopt it.


Modular Monolith

The modular monolith approach generated significant discussion, particularly around its practical benefits. The approach can support multiple architectures inside a module, with each module solving problems the way necessary for that domain. Modules can be simple or complex as needed, and compute-heavy modules can be easily split out to separate services. The pattern proves particularly valuable for plugin or extensible architectures.

The group challenged the common myth that monoliths don’t scale, noting that this simply isn’t true. They discussed various ways modules can communicate, from in-memory approaches to queues, and emphasised the importance of architecting it like a distributed application to enable future splitting if needed.

An interesting point raised during the discussion was that while Microsoft documentation often pushes toward microservices, monoliths can actually scale effectively. The group noted that the serialization and deserialization cost of network traffic in distributed systems is quite expensive at scale.


Opinionated Pattern Picked

The group arrived at a “it depends” approach, but with some clear guidelines. Ideally you can go modular monolith, and you’d create it in a way presuming you can pick an architecture. You create it in a way that you can slice off modules if needed if they’re higher throughput than others. You don’t take DDD to any solution unless they have a very complex domain that has the time and space to really dive into it. Whilst bringing clean architecture to an organisation is a safe default.

The choice depends heavily on various factors including the client’s technical maturity, team structure and communication patterns, project complexity and requirements, and need for future flexibility. Clean architecture provides a safe foundation, Modular Monolith offers flexibility for growth, and DDD concepts can be selectively applied where the additional effort and design can have a tangible return on investment.

Read more recent blogs

Get started on the right path to cloud success today. Our Crew are standing by to answer your questions and get you up and running.