They grow hard to test
A common evolution within a layered architecture is that layers are skipped. We access the persistence layer directly from the web layer since we’re only manipulating a single field of an entity, and for that, we need not bother the domain layer, right?
Figure 2.4 – Skipping the domain layer tends to scatter domain logic across the code base
Figure 2.4 shows how we’re skipping the domain layer and accessing the persistence layer right from the web layer.
Again, this feels OK the first couple of times, but it has two drawbacks if it happens often (and it will, once someone has made the first step).
First, we’re implementing domain logic in the web layer, even if it’s only manipulating a single field. What if the use case expands in the future? We’re most likely going to add more domain logic to the web layer, mixing responsibilities and spreading essential domain logic across all layers.
Second, in the unit tests of our web layer, we not only have to manage the dependencies on the domain layer but also the dependencies on the persistence layer. If we’re using mocks in our tests, that means we have to create mocks for both layers. This adds complexity to the tests. And a complex test setup is the first step toward no tests at all because we don’t have time for them. As the web component grows over time, it may accumulate a lot of dependencies on different persistence components, adding to the test’s complexity. At some point, it takes more time for us to understand the dependencies and create mocks for them than to actually write test code.