Skip to main content

Posts

Showing posts with the label Architecture

A complex system designed from scratch never works

A few years ago, I worked as an architect on a big mainframe rewrite. I still count it as one of my failures. Not because the technology was wrong, but because I couldn't convince the management team to simplify the approach. Years later, the organization is still struggling to get the new system up and running. I left the project at the time, because I couldn't put my name behind an approach that would take very long and cost a lot of money without a working system to show for it along the way. Gall’s Law That memory keeps coming back to me, because it's a textbook case of Gall's Law playing out in real life. Gall's Law , from John Gall's Systemantics , states it plainly: A complex system that works is invariably found to have evolved from a simple system that worked. A complex system designed from scratch never works, and it cannot be patched to make it work. You have to start over with a simple system that works. What does that mean in practice,...

Respect what came before

A colleague told me a story recently. A new architect joined his project. Experienced, credentialed, confident. And from day one, all he did was explain what was wrong with the existing system. The choices that were made, the patterns that were used, the technical debt that had accumulated. An endless inventory of flaws. I've seen this before. And it always makes me uneasy. Not because criticism is bad. Codebases do accumulate real problems. Patterns do become outdated. But there's a specific kind of criticism — reflexive, premature, delivered without curiosity — that reveals something troubling about the person offering it. The most dangerous person in a technical team isn't the one who doesn't know enough — it's the one who arrives certain they know better. Every system is a set of scars Software systems carry history inside them. A module that looks over-engineered almost certainly went through a painful incident that demanded it. A seemingly arbitra...

Understanding your project architecture and how it evolves over time using Gource

Have you ever wanted to see your project's Git history come to life? Gource is a fantastic tool that transforms your commit history into a mesmerizing animated visualization, showing how your codebase grows and evolves over time. It's like watching a time-lapse of your project's development, with files appearing, changing, and moving as contributors work on different parts of the code. But Gource is more than just eye candy. I like to use this tool to spot architectural patterns, identify hotspots where code changes frequently, understand how the team collaborates, and even detect potential coupling issues before they become problems. It's a powerful lens for understanding not just what a team has built, but how they've built it. In this post, I'll walk you through everything you need to know to create your first Gource visualization and use it to gain valuable insights into your codebase's architecture. What is Gource? Gource is an open-source vis...

You don’t need cloud

A recent survey by Flexera found that businesses waste an estimated 30% of their cloud spend on unused or unnecessary services. For small businesses with tight margins, this isn't just inefficient—it's potentially devastating. While tech giants promote cloud solutions as essential for every modern business, the reality for most small operations is quite different. Cloud is flexible, not cheap. Although you can build cost-effective solutions on a cloud platform, you have to be purposeful about this and design your solution specifically for it. The cost predictability problem One of the most frustrating aspects of cloud services is their variable pricing models. While providers advertise low entry prices, costs can quickly spiral as your usage increases: Pay-per-use pricing makes monthly bills unpredictable Resource provisioning often requires overestimation to prevent outages Hidden costs for data transfer, API calls, and storage can shock you at month...

Autonomy and loose coupling are not only an important characteristic for a software architecture

A utonomy in software design refers to the ability of a system or component to operate independently, making decisions and performing tasks without requiring other components or systems. Autonomy goes hand in hand with loose coupling , limiting the number of dependencies between components. These concepts are crucial for creating systems that are resilient, adaptable, and capable of handling complex tasks in dynamic environments. But could we apply the same concepts outside software design? Let's find out... Some observations If I showed you the following component diagram; what would be some observations, you could make?   Here are some of mine: Information is flowing up from components B, C and D to A. Probably there is some centralized decision making where most of the power is residing in component A. There is a high dependency on component A inside the system. Although without extra details we can misinterpret this diagram, but the risk exists that the co...

Embracing change requests: a mindset shift

In software development, change requests(CR) often get a bad reputation. As developers and architects it can feel frustrating to have to redesign and change existing features(especially if the change request has a big impact on the existing system). However, we should see them as a positive sign for a product's success, evolution, and continued relevance. Let’s explore why… Reason 1 - Our system is used! The fact that we get a CR means that at least someone tried our system and even better they see value in using it further because they want to improve it. When users ask for changes, it's because they're actively engaging with the software. They’re uncovering real-world use cases and scenarios that may not have been anticipated during initial design. This feedback loop confirms that the software is doing something valuable—and that users believe it can do even more. Reason 2 – We have learned something! Software, by its nature, is built to be flexible and adaptabl...

Architecting Your Team Setup: Aligning Teams with Software Design (and Vice Versa)

As software architects, we tend to focus heavily on the design of the systems we build—how the various components interact, the data flow, and the technology choices. But architecture doesn’t exist in a vacuum. One often overlooked element is how the structure of our teams can (and should) align with the architecture itself. The relationship between team setup and software design is symbiotic: your team’s structure influences the system’s architecture, and the architecture shapes how teams need to work together. Getting this alignment right can be the key to efficiency, scalability, and long-term success. Why Team Setup Matters in Software Architecture There’s an adage known as Conway’s Law , which states:  Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization's communication structure. In simple terms, the way your teams are structured will be reflected in your system’s architecture. If your teams d...

You don’t have a platform if it doesn’t have self service

Although the concept is not new (it was introduced in the Thoughtworks technology radar in 2017), I see a recent grow in platform teams at my customers. Partially this could probably be explained by the success of the great Team Topologies book that can be found on the bookshelf of almost every IT manager today.   What are platform teams? Platform teams are specialized groups within an organization that focus on building and maintaining the foundational technology and infrastructure that other development teams use to create applications. Their primary goal is to provide reusable tools, frameworks, and services that streamline the development process and enable feature teams to focus on delivering business value without worrying about underlying technical complexities. Platform teams typically handle: Infrastructure Management: Setting up and maintaining cloud services, CI/CD pipelines, monitoring tools, and other foundational infrastructure. Developer T...

Don’t talk about non-functional requirements, talk about quality attributes

When discussing software development, terms shape our perception and priorities. One such discussion revolves around the terminology used for requirements that go beyond direct functionalities. Traditionally, when talking about architectural needs, I used to call them non-functional requirements (NFRs). However, I switched recently to a  more fitting term—quality attributes—as it may better emphasize their importance and value.    Generated by AI Let me explain why this more than just a semantic change but a strategic enhancement… What are non-functional requirements? Before I explain my reasoning, let me shortly define what non-functional requirements are: Non-functional requirements (NFRs), also known as quality attributes, refer to criteria that judge the operation of a system rather than specific behaviors or functions. These requirements define the overall qualities and characteristics that the system must possess, ensuring it meets user needs and performs ...

Understanding Pure Domain Modelling: Bridging the Gap Between Existing Systems and the Real Domain

Domain modelling plays a crucial role in the way that I design systems to reflect the business's needs and processes. However, I experienced there is often a disconnect between the idealistic view of domain modelling and the practical reality faced by domain experts. One key issue is that domain experts tend to start from their existing systems rather than describing the 'real' domain. In this post I want to talk about pure domain modelling as a way to overcome the bias that domain experts have when explaining their needs. The domain expert bias When domain experts contribute to domain modelling, they frequently start from the perspective of the existing systems they are familiar with. These systems, whether they are legacy products, databases, or other technological solutions, shape their understanding and descriptions of the domain. While this approach has its advantages, it also introduces several challenges: Bias Towards Existing Systems: Domain experts may de...

The Red Hat cloud native architecture solution patterns

Being a software architect, I'm always looking for good resources that can help me design better solutions. One of these resources I can recommend are the Solution Patterns from Red Hat . Although mainly focused on Red Hat technologies, most of the described patterns are applicable in a broader context. For every solution pattern, you get more information about the problems it tackles and uses cases it solves, a reference architecture and a technical implementation. For example, let’s have a look at API versioning . As you can see you get some use cases where API versioning plays a role: And a high level solution: If you want to further drill down in the details, you can have an in-depth look at the solution’s architecture. With all this information you can make an informed decision if this solution pattern could help you in solving your specific needs. So bookmark this link and go explore the other solution patterns . More information Solution Patterns from Red H...

Building platforms–Strike the right balance

There is a lot of hype around platform engineering these days. The concept of creating platform teams and building platforms to deliver software at scale is not new as companies like Google, Facebook, Netflix etc. have a long history of building developer platforms. And also the much quoted Team Topologies book by Matthew Skelton and Manuel Pais was already released in 2019. Some wonder if this is just a fancy new name for existing practices and if there is a risk that these developer platforms become a bottleneck, exactly what they are supposed to alleviate.  Some dare even say that we made today’s development landscape so horrendously complex that we need these platforms to hide all this complexity. No matter if you think Platform Engineering is overhyped or not, before you go on this journey I would like to share the following quote: If your users haven’t build something that surprised you, you probably didn’t build a platform I saw this quote in the Build abstr...

Autonomous Computing and how it influenced the way I build software

There are a lot of concepts and papers that have influenced the way I design and build software. One concept that certainly should be on the list is 'Autonomous Computing' as introduced by Pat Helland more than 20 years ago. If you have never heard about this concept, I would recommend to first read this paper before you continue reading my blog post. Back? Let’s continue. In the paper Pat introduces the concept of Fiefdoms and Emissaries and Collaborations . Fiefdoms refer to independent, autonomous components within a computing system. Each fiefdom is responsible for a specific aspect or function of the overall system. They operate independently and have their own decision-making capabilities. Emissaries are entities that facilitate communication and coordination between fiefdoms. They act as messengers, relaying information and requests between different components of the system. Emissaries enable fiefdoms to interact and collaborate without direct dependencies o...

An architect is not an evangelist

A trap I easily fall in to as an architect is that I can be become quite enthusiastic about a specific technology. If you are a long time reader of my blog, you certainly have seen me write about specific tools, techniques and products over the years. Unfortunately this enthusiasm got me into trouble a few times as an architect. Because I have an important stake into a project and some influential power it happened that I started spreading this enthusiasm and influenced the team to join my enthusiasm. Sorry team! But this means that I was no longer doing my job as an architect. Instead of seeing the trade-offs ; I fell in love with the good parts and turned blind for the bad parts. Although I know better and that I should  be wary of any tool or technique that promises to make everything better, I couldn’t resist. It's a trap that many architects fall into: becoming so enamored with the positive aspects of a technology that they overlook its shortcomings. In doing so, we negl...

Everyone should be an architect

In the world of software development, the role of the architect often looms large. Yet, what if I told you that architecture is not just the domain of a select few, but rather the responsibility of every member on the team? Let's delve into why this shift in perspective is crucial for the success of your projects. Gone are the days when software architecture was solely the concern of a designated architect. In today's landscape, it's imperative that every team member, from developers to testers, possesses a solid understanding of the architectural principles guiding their work. As an architect, your primary aim should be to ensure that everyone comprehends the architecture as thoroughly as you do. Each member should be equipped to answer the fundamental "why" questions about the architecture, breaking down barriers that often lead to miscommunication and inefficiency. Too often, we see organizations where the architect stands as the solitary guardian of th...

The importance of the ubiquitous language

We all know that the hardest thing in software development is naming things . Domain Driven Design tries to tackle this by focusing on the 'ubiquitous language'. The "ubiquitous language" refers to a shared language that is used by all team members, including domain experts, developers, and stakeholders, to discuss the domain and the software being developed. This language is designed to bridge the communication gap between technical and non-technical team members, ensuring that everyone has a clear understanding of the domain concepts and requirements. The ubiquitous language consists of domain-specific terms and concepts that are defined collaboratively and consistently used across all artifacts of the software development process, including code, documentation, and discussions. By using a common language, DDD aims to reduce misunderstandings and ambiguities, leading to more effective collaboration and better software designs. The best way to emphasize the imp...

Implement the mediator pattern using MassTransit

The mediator pattern is a behavioral design pattern used in software engineering. It defines an object that encapsulates how a set of objects interact .  In object-oriented programming, programs often consist of many classes. As more classes are added to a program, especially during maintenance or refactoring, the problem of communication between these classes becomes complex. Direct communication between objects can lead to tight coupling, making the program harder to read, maintain, and change. The mediator pattern introduces a mediator object that acts as an intermediary between interacting objects. Instead of direct communication, objects now communicate through the mediator. This reduces dependencies between objects and promotes loose coupling. A popular way to implement the mediator pattern in .NET is through the popular MediatR library . But if you are already using Masstransit ,  there is no need to introduce an extra dependency as Masstransit has built-in sup...

MassTransit–Avoid losing messages

At one of my clients we had a situation where messages got lost after sending them to RabbitMQ. This is quite bad as the whole point of having a message based solution was to improve the reliability of our solutions(even when of the involved systems is offline or unavailable). In this post I want to explain what got wrong and how we introduced a solution to prevent this from happening in the future. To understand the problem I first have to explain the concept of an exchange. In RabbitMQ, exchanges are message routing agents that are responsible for routing messages to different queues with the help of header attributes, bindings, and routing keys. A producer never sends a message directly to a queue. Instead, it uses an exchange as a routing mediator. Therefore, the exchange decides if the message goes to one queue, to multiple queues, or is simply discarded. Let me emphasize one sentence here: In RabbitMQ , a producer never sends a message directly to a queue Only que...

Building distributed systems–Retry storms

With the popularity of microservices, distributed systems have become the norm. Although distributed systems can certainly help ensuring scalability and resilience, they come with their fair share of challenges. One particularly I want to talk about today is the retry storm. What is a retry storm? A retry storm occurs when a large number of clients simultaneously attempt to retry failed requests, overwhelming the system and exacerbating the initial issue. In this blog post, we'll explore the causes of retry storms and provide practical strategies to avoid them. Let’s image we have a range of services calling each other: If each service has a retry policy installed which retries 3 times(resulting in a total of 3+1 requests), this would result in 64 times(!) the normal traffic. If retry policies are executed without context in cause traffic to grow exponentially. How can we avoid it? Some measures that can help avoid a retry storm are: Jittered Exponential Backoff: ...