Review of the Advanced Web Application Architecture

What is the Book About

Matthias shows how to focus on the business needs, on use cases and how to write it down into the code. He calls this code “core code”. The core code is decoupled from databases, frameworks or libraries. This is the general idea of the book — isolate the code containing business logic.

Writing Style & Code Examples

The book is using easy English and anyone who can read this review can read the book. Matthias seamlessly leads reader from known but messy code to new well-structured approach. Difficult topics like entities, repositories, ports, adapters, … are explained so easily that most of the readers will understand them immediately.

Personal Impression

The power of suggested architecture is that it leads to software that is clear, testable and maintainable. I just agree.

  • develops applications in team
  • wants to test code, but keep struggling
  • wants to apply Domain-Driven Design

Ideas that Made My Day

  • It’s OK to pass services to entities (chapter 3.1). Once we do it, we encapsulate the behavior into entity, where it belongs.
  • Matthias nicely explains domain events (chapter 3.3) as a synchronization mechanism write -> read model. Using domain events doesn’t mean doing event sourcing.
  • Matthias suggests taking a look on the use-case and imagine using CLI instead of web (chapter 4.1). Helps to reach point of the book — infrastructure (technology) independent code.
  • Architecture described in the book allows us postponing important decisions (chapter 4.5), like choosing e-mail sending technology. This advantage should be highlighted more.
  • Fast tests are important (chapter 5.7).
  • Objects should talk to external systems via services (chapter 7.2). A simple rule that makes thinking about external world much easier.
  • Eliminate code that forces us to jump from class to class, from layer to layer (chapter 7.5). This “jumping” code is a sign of putting code in wrong layer.
  • Entities are always valid (chapter 8.1).
  • Validation means applying pure functions (chapter 8.5). Nice simplifying idea.
  • Port = interface. Beautiful definition.
  • Unit testing isn’t about classes, it’s about “testing behavior of object” (chapter 14). If we need multiple classes for it, just use them.
  • deptrac seems to be a tool that helps with the architecture. Looking forward to using it in a real project.

Chapters in Detail

I like most of the book, sometimes I disagree and sometimes I’m missing important information. You can find here couple of my notes and confront them with your point of view.

✖ ORM Mappings in PHP Annotations (chapter 2.5.1)

Matthias suggests writing ORM mapping directly to PHP annotations

  • Mapping in annotations makes PHP classes very long and steals readers focus.
  • Matthias says that the mapping isn’t infrastructure code because of rules he defined. I disagree, it is infrastructure code because it is tied up to concrete technology.
  • For me this approach is similar to mixing PHP and HTML code.

✔ Don’t Use Active Record (chapter 2.8)

Matthias discourages us from using active record design pattern.

  • Extending from base class means relation IS. So our object like Order suddenly IS an Entity. Maybe sounds right at first look, but it means our Order IS and Entity of concrete library. That makes the Order to be an infrastructure entity.

✔ Use Read Model (chapter 3)

Matthias introduces read models and view models without any questions, and I like it. We need more view models and thinking that reading is very different from writing.

✔ Hide Low Level Details (chapter 3)

Matthias suggests to hide low level implementation like database queries behind abstractions. Sure, but why?

❓ How to Solve Naming Collisions (chapter 3)

The book doesn’t deal with possible naming collisions.

✖ Naming “Application Services” (chapter 4)

Application services are classes that encapsulate domain use-case, are isolated from infrastructure and belongs to core code. One such service could be OrderEbookService with method order(). The concept makes sense.

  • OrderEbookService - I'm bothered by the suffix Service, it signs wrong naming for me, because programmers calls *Service anything they can't properly name.
  • OrderEbookUseCase or OrderEbook with method order()

✖ Using Mocks in Tests (chapter 5.7)

Matthias suggests to use mocks in tests for external dependencies like Translator.

  • Supports automatic refactoring in IDE
  • Static analysis tools understands it and can detect problems

✖ Misinterpretation of Inversion of Control (chapter 5.9)

Matthias says that declaring required constructor arguments is called inversion of control, and we should never use service locator.

✔ Behavior of Objects (chapter 7.4)

“Value objects should offer no behavior that hasn’t been explicitly enabled and designed for your use case”

✖ Validation (chapter 8)

This chapter starts well — value objects and entities are always valid. Unfortunately the whole chapter feels unfinished, it is for me the weakest chapter in the book.

Multiple Validation Errors

Matthias suggests constructing value objects in validation layer to catch exceptions and perform validations, and then construct them again in core code for business logic. We can find this code listing 8.11 (chapter 8.3) and it isn’t the best and even Matthias isn’t satisfied with it. We have to double check inputs — once in the validation layer and once in the core layer. It is double effort for runtime, but also double effort for writing the code that may result in an inconsistency.

Translatable Exceptions

Matthias suggests to use translatable strings (chapter 8.4) in domain exceptions and translate these string in UI layer to user readable error message. Core code suddenly have an information that is useful only for the UI (not core layer). So we mix layers, and that is a bad idea.

Different Exceptions

The book unfortunately doesn’t distinguish runtime (catchable) and logic exceptions (chapter 8.4).

Double Effort Solution

We touched this topic in Multiple Validation Errors and we’ll combine it with commands.

  • Pass only raw data to commands
  • Create value objects in application services

✔ Structure of Application

Matthias suggests following structure of application

✖ Connecting UI and Application Service Layers (chapter 13)

The whole chapter focuses on connecting layers. The only thing that bothers me is connection between UI and Application Service layers. Matthias suggests two solution for this topic.

✖ Contract Testing (chapter 14.3)

Testing adapters (eg. repositories) should be done by testing heir public methods only. This idea is beautiful, but may not test enough.

✔ Gherkin Scenario Based Testing (chapter 14.5)

Matthias provides how-to tutorial for Gherkin scenario based tests.

Given the user has not ordered yet
When the user adds a book with price 100€ into the cart
Then the shopping cart total is 90€
  • Instant documentation
  • Forces us to focus on behavior, not data

✔ Development Workflow (chapter 14.7)

Matthias focuses on communication between programmers and other company members. That’s in my opinion the most important aspect to deliver software that has value and lasts.

➕ Topics I Miss in the Book

  • Matthias often mentions that proposed architecture helps with “framework migration”. That is quite rare case, similar to migration to a different database. What is often case is “framework upgrade”. The proposed architecture makes upgrading frameworks and libraries much easier.
  • I miss an important discussion when we start using domain events for delegating job (chapter 4.5). Is sending e-mail part of the order use-case and when it fails, ordering should fail? If no, using domain events and subscribers is fine. But if yes, we should keep sending e-mails in the application service.
  • Application service can accept not only primitive types but also value objects. I find sending value objects to application services pretty useful because then the use-case has fewer reasons to fail.

Thank You

Matthias, thank you for the book, it is great.


Do You want to improve your architecture? Hire me, I’ll help You.

Developer interested in Domain-Driven Design & Modeling