Review of the Advanced Web Application Architecture

What is the Book About

Writing Style & Code Examples

Personal Impression

  • develops (not only web) applications that have to survive at least couple of years
  • 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

✖ ORM Mappings in PHP Annotations (chapter 2.5.1)

  • Mixes two different languages — domain language and mapping language. We read different languages for different reasons. When we read the core code, we want to understand the logic. When we read the mapping, we want to understand how it is persisted. Once we mix these languages together, it is difficult to achieve the desired task because the code is obfuscated by a different language.
  • 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)

  • Makes unit testing almost impossible or very difficult
  • 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)

✔ Hide Low Level Details (chapter 3)

❓ How to Solve Naming Collisions (chapter 3)

✖ Naming “Application Services” (chapter 4)

  • Application service — the naming is too vague. There are so many things in IT called application service, so it can mean anything.
  • OrderEbookService - I'm bothered by the suffix Service, it signs wrong naming for me, because programmers calls *Service anything they can't properly name.
  • Use Cases — layer of, well, use cases (that encapsulate domain use-case, are isolated …)
  • OrderEbookUseCase or OrderEbook with method order()

✖ Using Mocks in Tests (chapter 5.7)

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

✖ Misinterpretation of Inversion of Control (chapter 5.9)

✔ Behavior of Objects (chapter 7.4)

✖ Validation (chapter 8)

Multiple Validation Errors

Translatable Exceptions

Different Exceptions

Double Effort Solution

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

✔ Structure of Application

✖ Connecting UI and Application Service Layers (chapter 13)

✖ Contract Testing (chapter 14.3)

✔ Gherkin Scenario Based Testing (chapter 14.5)

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€
  • Scenarios written in human language
  • Instant documentation
  • Forces us to focus on behavior, not data

✔ Development Workflow (chapter 14.7)

➕ 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




Developer interested in Domain-Driven Design & Modeling

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store