The author emphasizes the importance of treating technology as a detail rather than the focus in software projects, advocating for pushing technology to the boundaries of the codebase and letting the business domain take center stage.
Abstract
In the context of software development, the author argues that technology should be seen as an enabler of business goals rather than the primary focus. They note that technology can hinder a codebase and distract from the core purpose of the project. To combat this, the author recommends practices such as screaming architecture, domain-centric architectures, and isolating technology to minimize coupling with specific technologies and improve maintainability. By abstracting technology, developers can create a more domain-driven software that prioritizes the business goals and user needs. The author also acknowledges that abstracting technology is not without its challenges, including the law of leaky abstractions, and provides guidance on how to approach technology decisions systematically.
Bullet points
Technology should be seen as an enabler of business goals, not the primary focus
Screaming architecture and domain-centric architectures (hexagonal, ports and adapters, clean architectures) help put the business domain at the center of the project and push technology to the outer boundaries
Isolating technology reduces coupling with specific technologies and improves maintainability
Abstracting technology makes automated testing easier and allows for safer and quicker refactorings
The law of leaky abstractions acknowledges that no abstraction is perfect and that technology can fail
A systematic approach to technology decisions can help prevent hype-driven picks
Inversion of control and dependency injection can help isolate technology and make it pluggable and replaceable
Software should be domain-driven rather than tech-driven.
Technology is a detail
I feel lost when I look at a project and all I see is technology. Technology is the enabler of business goals, but it’s only a detail. This looks like a paradox so bear with me.
📝 Since we’re talking about software, everything is technology. To avoid confusion, when I say technology I mean the things that are outside the scope of your business domain, like databases, queuing systems, I/O, interacting with APIs, frameworks, etc.
Technology is pervasive and can hinder your codebase. However, many of us are technology evangelists so it’s easy to fall into that trap on a new project. Fast forward a few months and all you see are HTTP filters, monitors, JSON, command handlers, SQL, etc. Now look at your code, take a step back, and think about how you can make technology just a detail. Push it to the boundaries. Don’t let it take control of your codebase.
Don’t get hung up on the tech! Choose tools that are appropriate at the time and be prepared to change them when you need to. Design, approach, patterns and techniques matter much more, and last much longer, than specific technologies. Continuous Delivery Pipelines
Screaming architecture is one of my favorite practices. When you browse a codebase, it should be obvious what the app aims for — its intents should scream at you. You’ll feel more connected to the app’s purposes because the terminology is separated from the technology. This is closely related to the reason to avoid tech stories — it’s much easier to empathize with users/business needs if we see them reflected in the team’s board and the codebase — technology should be seen simply as the means to achieve those needs.
Domain-centric architectures (hexagonal, ports and adapters, and clean architectures) tell you to put the business domain at the center and push technology to the outer boundaries of your app. Isolating technology is achieved with the creation of adapters that intermediate the inner language (domain) with the outer language (infrastructure). This is a big topic to discuss here and I’ve written an article about it:
We should find ways to reduce coupling with specific technologies like data stores, data formats, etc., to keep the buy-in under control and allow swapping technologies with a small blast radius. By isolating technology, technical details are abstracted so the maintenance is improved — refactorings get to be safe and quick. Abstracting technology also makes automated testing easier, allowing you to resort to ‘test doubles’.
The center of your application is not the database. Nor is it one or more of the frameworks you may be using. The center of your application are the use cases of your application. […] Databases and frameworks are details! NO DB
You might argue that you’re not swapping the database any time soon so why bother? The reasons for abstract technology are deeper than that. Imagine trying to browse a codebase and keep stumbling onto technical terms while trying to understand the problem it solves. Don’t let your projects revolve around technology.
Separating the technology from the domain also aligns with the principle of the single level of abstraction which suggests that code has different levels of abstraction and you should not mix them. A codebase has three categories of abstraction:
Why/who: why did you build the app and who does it serve? This information should be granted by high-level tests (e.g. acceptance).
What: what is the app able to do? What are its use cases? What entities does it manage? The app should scream what it can do.
How: how is the app able to accomplish the “what”, technology-wise? This is the concretization of things — it’s mainly the app’s side effects (e.g. storing data, showing it to the user) and it’s enabled by technology.
In a well-designed system, each layer provides a different abstraction from the layers above and below it. […] As a module developer, you should strive to make life as easy as possible for the users of your module, even if that means extra work for you. Another way of expressing this idea is that it is more important for a module to have a simple interface than a simple implementation. A Philosophy of Software Design
Abstracting technology seems to be the right path but it’s not perfect. Keep in mind the law of leaky abstractions:
TCP attempts to provide a complete abstraction of an underlying unreliable network, but sometimes, the network leaks through the abstraction and you feel the things that the abstraction can’t quite protect you from. This is but one example of what I’ve dubbed the Law of Leaky Abstractions: All non-trivial abstractions, to some degree, are leaky. Abstractions fail. Sometimes a little, sometimes a lot. There’s leakage. Things go wrong. It happens all over the place when you have abstractions. The Law of Leaky Abstractions
Delay technology decisions as much as possible; this is known as the last responsible moment;
Once it’s time to decide on any technology, apply a systematic approach to prevent hype-driven picks;
Isolate technology (from the business core of your app) and make it pluggable and replaceable. Inversion of control helps to achieve it, namely through the use of dependency injection.
To sum it up, make sure your software is domain-driven rather than tech-driven.
When you learn about a “new” technology, don’t readily accept the inevitable hype associated with it. Read carefully. Be realistic with respect to payoffs and risks. Run experiments before making major commitments. 201 Principles of Software Development
Further reading
Another way technology can be pernicious is when you start creating technical hotspots:
Until the Cabal process got underway, technology was added to Half-Life freely. It was assumed that “if we build it, they will come,” meaning that any new technology would just naturally find a creative use by the content creation folks. A prime example of this fallacy was our “beam” effect, […] It was added to the engine, the parameters were exposed, and an e-mail was sent out explaining it. The result was … nothing. After two months only one level designer had put it in a map. Engineering was baffled. The Cabal: Valve’s Design Process For Creating Half-Life
In fact, Apple didn’t introduce the iPod until twenty two months after Creative’s entry into the market. […] The problem was, they advertised their product as a “5GB mp3 player.” It is exactly the same message as Apple’s “1,000 songs in your pocket.” The difference is Creative told us WHAT their product was and Apple told us WHY we needed it. Start With Why