From a layering standpoint, using my previous example, you will end up having two layers sharing the data model:
Figure 14.18: A façade-like presentation layer over a database application’s design
Nothing stops you from creating a view model here and there for more complex views, but the key is to keep the logic’s complexity to a minimum. Otherwise, you may discover the hard way that sometimes, rewriting a program from scratch takes less time than trying to fix it. Moreover, nothing stops you from using any other presentation tools and components available to you.Using this data-driven architecture as a temporary application while the main application is in development is also a good solution. It takes a fraction of the time to build, and the users have access to it immediately. You can even get feedback from it, which allows you to fix any mistakes before they are implemented in the real (future) application, working like a living prototype.
A good database design in these sorts of applications can go a long way.
Not all projects are that simple, but still, many are; the key is to make the program good enough while ensuring you cut the right corners. The presentation layer in these types of applications could leverage a low-code solution such as Power Apps, for example.
Summary
Layering is one of the most used architectural techniques when it comes to designing applications. An application is often split into multiple different layers, each managing a single responsibility. The three most popular layers are presentation, domain, and data. You are not limited to three layers; you can split each into smaller layers (or smaller pieces inside the same conceptual layer), leading to composable, manageable, and maintainable applications.Moreover, you can create abstraction layers to invert the flow of dependency and separate interfaces from implementations, as we saw in the Abstract layers section. You can persist the domain entities directly or create an independent model for the data layer. You can also use an anemic model (no logic or method) or a rich model (packed with entity-related logic). You can share that model between multiple layers or have each layer possess its own.Out of layering was born Clean Architecture, which guides organizing your application into concentric layers, often dividing the application into use cases.Let’s see how this approach can help us move toward the SOLID principles at app scale:
- S: Layering leads us toward splitting responsibilities horizontally, with each layer oriented around a single macro-concern. The main goal of layering is responsibility segregation.
- O: Abstract layers enable consumers to act differently (change behaviors) based on the provided implementation (concrete layer).
- L: N/A
- I: Splitting layers based on features (or cohesive groups of features) is a way of segregating a system into smaller blocks (interfaces).
- D: Abstraction layers lead directly to the dependency flow’s inversion, while classic layering leads in the opposite direction.
In the next chapter, we learn how to centralize the logic of copying objects (models) using object mappers and an open-source tool to help us skip the implementation, also known as productive laziness.