Domain-Driven Design by Eric Evans (Part II, chapter 4)
Layered architecture and Smart UI
In part I, the book clarifies the motivation behind using Domain-Driven Design and it laid the foundation of its goals and how to achieve them. It also defined what Model-Driven Design is. In chapter 4, The book explores two architecture frameworks and how they fit into Model-Driven Design.
Part II
Chapter 4: Isolating the Domain
It is important to understand that most of the code is not about the domain but about the technology of the software itself. We need to isolate the domain objects from the rest of the code so we do not lose sight of the domain.
For example, when you set the destination in a ride hailing app, you go through different parts of the system:
- The frontend widget
- The query that gets the possible destinations from the database
- User input validation
- Associate selected destination with the trip
- Commit changes to the database
Only a little portion of that is part of the business domain.
Often UI, database and other code is written directly in the domain objects because it is faster to get things done. This makes the project harder to understand and harder to scale. To avoid that, systems should be implemented with separation of concerns and that's what Layered Architecture aims at.
Layered Architecture
Layered architecture divides the program into layers where each layer is responsible of an aspect of computer science. The layers are:
- UI or Presentation layer
- Application layer which coordinates tasks between domain objects and it has no business rules
- Model layer or domain layer which is the most important layer for Model-Driven Design
- Infrastructure layer which provide technical capabilities to support the above layers
An example to that can consist of:
Layer | Component |
Presentation | Frontend web interface |
Application | Backend for Frontend (bff) |
Domain | Specialized Microservices handling different entities each |
Infrastructure | Interfaces that utilize infrastructure (ex. Rabbit MQ, Database) |
Layered Architecture Specifications
- Partition system to layers according to the responsibilities
- Each layer should depend only on the layers below it. This is achieved by using the public interfaces of the layers below.
- Each layer is loosely coupled to the layer above it. To achieve that, layers should communicate with the layers above them through callbacks or observers.
- Infrastructure layer should know nothing about the domain and should be used as services.
- The Domain-Driven Design approach requires only the domain-layer to be separated, other layers can be mixed and the system can still follow Domain-Driven Design.
Advantages of Using Layered Architecture
- Design is a lot cleaner
- Less expensive to maintain since layers are loosely coupled
- Easier to scale because each layer can evolve separately
Disadvantages of Using Layered Architecture
- Has a learning curve that inexperienced developers might struggle through
- Takes longer time to design and implement
That's why another architecture is introduced as an "anti-pattern" to Layered Architecture and that is Smart UI.
Smart UI
If the project is not very ambitious or is not expected to scale, or if the developing team is inexperienced then Smart UI is probably the way to go.
Smart UI specifications
- Business logic is implemented in the UI
- Application is divided to small functions and each function is implemented as a separate UI.
- Relational databases are used as a shared data repository
- Use the most automated UI building tools available. (I'm not sure what the book means by that exactly but I think it's about tools that let you drag and drop components to form the UI and then wire your code to it.)
- Use fourth generation languages (4GL)
Advantages of Using Smart UI
- Fast and easy to develop
- Can be changed quickly since it's divided to small functions and small UIs
- Easy to expand the system since the UIs are decoupled
- Using relational databases provides integrity at data levels
- 4GL tools work well
- Maintenance team can quickly redo parts of the code that they don't understand since changes should be localized to each separate UI
Disadvantages of Using Smart UI
- Integrating applications is difficult since the tools and languages are not flexible
- Business problem is not abstracted which means behavior cannot be reused
- Lack of abstraction limits refactoring options
- No flexibility to add richer behavior
- If need for scalability arises later, system cannot migrate from this approach except by replacing the entire app.
It's important not to use sophisticated design approaches unless the development team is committed to those patterns all the way or if the project does not need such approaches. It's better to use 4GL and automated tools instead of a sophisticated, flexible language like Java. Do not overengineer your project.
Conclusion
This chapter introduces to approaches to design a system based on how complex the system is and how skilled the developers are. It explained when to apply Domain-Driven Design and when not to showing the pros and cons of each of the 2 patterns introduced.
As always, it's important to remember that designing a system is a process of constantly making tradeoffs. You get fast development but it's harder to scale. You have flexibility but it takes longer to develop.