Previous blogs talk about how you design and evolve business models, but how do you structure the whole application? The author advocates the following layered architecture:
- UI layer is for users to interact with the system.
- Application layer is a thin layer that contains no business logic, it coordinates tasks and invokes other layers to accomplish business functions.
- Business logic is encapsulated into the domain layer. This layer is the heart and core of business software.
- Infrastructure layer provides generic technical capabilities, such as MQ, email notification, persistence.
This idea might not seem very interesting, but it is worth noting, because it is common to another approach of layered structure: the lowest layer is DAO, on top of it is Business Objects (BO) which contain some business logic, on top of it is an application layer which contains most of the business logic, and then UI layer. Even packaging is done horizontally: each layer is packaged into separate packages and compiled into separate jars. Hunting down a business logic needs to dig through multiple layers.
In the author’s structure, the application layer doesn’t contain business logic, which is encapsulated into the domain layer. Take an example of transferring funds:
- Application layer will have a Fund Transferring Service, which does:
· Digests inputs (such as an REST request)
· Invokes a domain service to transfer funds
· Listens for confirmation
· Sends notification using infrastructure service
- Domain Layer will have a Funds Transferring Service, which does:
· Interact with necessary Account and Ledgers to make appropriate debts and credits; accounts and ledgers will enforce corresponding business rules
· Responds with result
- Infrastructure layer will have a Sending Notification Service, which does:
· Send emails to recipients
· Handles infrastructure failure (timeout, email rejection etc)
This take cares of one application (the book actually devoted a few chapters to large-scale application, alas, they are written so boringly, I am just going to skip them), how do you interact with other application (which is a common challenge with Microservice)? The author offers a pattern “anti-corruption layer”.
Take the cargo-delivery example, the sales department has a new requirement for the booking application: some categories of cargo are more profiting, they want to reserve spaces for these categories and limit spaces for other categories. The trouble is: the two applications do not have the same model. The booking application doesn’t have a model for cargo categories, it uses model “EnterpriseSegment” to differentiate cargoes.
The booking application can transfer between EnterpriseSegment and Category, but that will mean its domain will be polluted by a concept that is not inherently its own. Instead, use an “anti-corruption layer” to do the dirty job.
AllocationChecker acts as the “anti-corruption layer” that translates the models between the Booking Application and the Sales Management System. In this example, AllocationChecker also enforces the business rule: only accept a Cargo booking if its booking quantity doesn’t exceed the limit defined by the Sales Management System. I probably would enforce the logic inside the BusinessApplication.
The point of “ACL” is not only to provide interfaces (acting as a Façade) for consuming application, but to transfer models between two applications, so that the integrity of models can be maintained.