The Essence of Great Software
What makes software great? Is it enough for software to merely work? What does it mean for software to “work”? So long as it meets the requirements, it works. That implies that bugs are what causes software to no longer work, so for software to be great, it should preferably not have any bugs. What else makes software great? Perhaps it should be secure, scalable, reliable and performant, depending on the situation of course. So great software is bug-free, scalable, reliable, secure and performant. That must be it right? Well, you guessed it: no it is not. There’s not only a need for software to work in the moment, but to also continue working when faced with changing requirements. When requirements change, we’d rather fulfil those requirements as fast as possible, spending as little time as possible maintaining the software. So what are we missing here? We are missing an all-too-often neglected part of software development, and that is to know the business in which our software exists. There is a need to close the gap between the technology and the business. What does that mean? It means a lot of very useful things:
- The codebase lives in harmony with the business. Natural changes in the business domain maps to just as natural changes in the software.
- Customers and developers discuss problems to be solved using a shared language that aligns with the business. This allows for customers and developers to have much more involved discussions where they solve problems together. Those discussions can then be easily mapped into code.
- No technical lingo divides the customers and developers, they essentially work together as a team towards a common goal. No more us-and-them attitude.
- Domain knowledge is captured in the technical solutions. No more single point of failure where only a small handful of seasoned developers knows the business domain and how the codebase works. The domain knowledge is right there in the code for every developer to consume.
There are many other benefits to gain from closing the gap between business and technology, but those I’ve listed are what makes up the core of great software. Let’s jump right into what all of this means.
Tying the code and business together
Imagine you’re developing a fridge simulator for a customer who sells fridges. They want a simulator in which end-users can use the fridge as it would be used in real life. In order to close the gap between technology and business, there is a need to make the code reflect this business domain. When you read the code, not only will you know how the code works, but also how the software works in reality. By reading the code, you’ll also learn how the fridge works in reality. You will gain knowledge that can be used to discuss specific aspects of the software with the customer, and they will understand what you are saying. There is no need for technical lingo; just by reading the code you will gain insight into the business domain. What is there to gain from this? Well, for one, you no longer need to depend on some all-knowing wise architect who is familiar with the intricacies of the codebase or how the software works, you can gain this business knowledge by just reading the code. If something’s unclear, guess what, you can discuss those problems with the customer. This wouldn’t be possible if the codebase was completely disconnected from the problem domain, which, unfortunately, it usually is.
Another important thing to note is that if the software reflects the business domain, it’ll open up the possibility for a much tighter collaboration with the customer who may not be very technical. All discussions with them occur within the context of the business, and those discussions are easily mapped to code. The most important part however, is the fact that natural changes in the business domain correspond to just as natural changes in the software. Trivial changes proposed by the customer should be trivial to apply to the software. This is because the software and the customer’s mental model of the business lives in harmony with each other. The customer will always propose requirements with their mental model of the problem as reference, after all.
The code isn’t important – the business is
Quite a bold statement, right? That is not to say that code is useless; we need it to realize a solution to a real-world problem. However, we’d like to spend as little time as possible maintaining the code while maximizing time spent on delivering true business value. In the end, what matters is the software itself and the problems it solves. Focusing on the business domain in which the software exists is therefore essential. We’d like to spend less time trying to understand what the code does and why it’s there, and also spending less time on fixing bugs. Closing the gap between business and technology helps us do just that. It also fosters a great collaboration between developers and non-technical people involved in the software project.
At the end of the day, what matters is the software and how it can provide value to the customer. Code is just what we have to rely on to actually realize the software. Therefore it is essential that we take good care of the codebase, which means understanding the software, the domain in which it exists and why we develop it at all.
The software should depend on the business, not the other way around. What that essentially means is important: the business shall not be limited by the software. The software is there to support the business, not prevent it.
Summary
We’ve only touched the surface of the idea of closing the gap between the business and technology. So how do you actually tie the code to the business? How do you actually make it reflect the business domain? This is a very big question with an equally big answer: domain-driven design. The core philosophy behind domain-driven design is tying the software and business together. It presents an array of concepts, ideas, methodologies and philosophies with regards to object-oriented programming. It isn’t a silver bullet (as is almost nothing in software development), but its core philosophy of letting the code reflect the domain, through the ubiquitous language as it is called, is hard to argue against. You are in for a rough ride if you ever develop software that neglects the problem domain (you know, that thing the software actually solves). As the problem domain changes, so does the software. What is interesting, however, is how well the software can adapt to the changing problem domain. If the software completely reflects the problem domain, there should essentially be no problem making the corresponding changes to the software as the problem domain changes.
If you liked this post, I’ve discussed similar aspects of this topic (although a bit more technical) in another post some year ago. Also, I recommend checking out the blue book by Eric Evans (Domain-Driven Design: Tackling Complexity in the Heart of Software) which actually coined the term domain-driven design. It’s a bit dry, but it really put words to a problem I previously couldn’t understand myself. Another book to consider is Implementing Domain-Driven Design by Vaughn Vernon, although I am in the process of reading this book at the time of authoring this post.