We have explored strict layering and how to apply the DIP, but we still have multiple models. An alternative to copying models from one layer to another is to share a model between multiple layers, generally as an assembly. Visually, it looks like this:
Figure 14.9: Sharing a model between all three layers
Everything has pros and cons, so no matter how much time this can save you at first, it will come back to haunt you and become a pain point later as the project advances and becomes more complex.Suppose you feel that sharing a model is worth it for your application. In that case, I recommend using view models or DTOs at the presentation level to control and keep the input and output of your application loosely coupled from your model. This way of shielding your lower layers can be represented as follows:
Figure 14.10: Sharing a model between the domain and data layers
By doing that, you will save some time initially by sharing your model between your domain and data layers. By hiding that shared model under the presentation layer, you should dodge many problems in the long run, making this a good compromise between quality and development time. Moreover, since your presentation layer shields your application from the outside world, you can refactor your other layers without impacting your consumers.
This is pretty much how Clean Architecture does it but represented differently. Using that, the model is at the center of the application and is manipulated and persisted. While the layers have different names, the concept remains very similar. More on that later.
View models and DTOs are key elements to successful programs and developers’ sanity; they should save you many headaches for long-running projects. We revisit and explore the concepts of controlling the input and output later in Chapter 16, Mediator and CQRS Design Patterns, where inputs become commands and queries.Meanwhile, let’s merge that concept with an abstraction layer. In the previous project, the data abstraction layer owned the data model, and the domain layer owned the domain model.In this architectural alternative, we are sharing the model between the two layers. The presentation layer can indirectly use that shared model to dialog with the domain layer without exposing it externally. The objective is to directly persist the domain model and skip the copy from the domain to the data layer while having that data abstraction layer that breaks the tight coupling between the domain logic and the persistence.Here is a visual representation of that:
Figure 14.11: Diagram representing a shared rich model