Reader small image

You're reading from  Get Your Hands Dirty on Clean Architecture - Second Edition

Product typeBook
Published inJul 2023
PublisherPackt
ISBN-139781805128373
Edition2nd Edition
Right arrow
Author (1)
Tom Hombergs
Tom Hombergs
author image
Tom Hombergs

Tom Hombergs is a software engineer by profession and by passion with more than a decade of experience working on many different software projects for many different clients across various industries. In software projects, he takes on the roles of software developer, architect, and coach, with a focus on the Java ecosystem. He has found that writing is the best way to learn, so he likes to dive deep into topics he encounters in his software projects to create texts that give structure to the chaotic world of software development. He regularly writes about software development on his blog and is an occasional speaker at conferences.
Read more about Tom Hombergs

Right arrow

Taking Shortcuts Consciously

In the preface of this book, I cursed the fact that we feel forced to take shortcuts all the time, building up a great heap of technical debt we never have the chance to pay back.

To prevent shortcuts, we must be able to identify them. So, the goal of this chapter is to raise awareness of some potential shortcuts and discuss their effects.

With this information, we can identify and fix accidental shortcuts. Or, if justified, we can even consciously opt in to the effects of a shortcut.1

1 Imagine talking about shortcuts in a book about construction engineering or, even scarier, in a book about avionics! Most of us, however, are not building the software equivalent of a skyscraper or an airplane. And software is soft and can be changed more easily than hardware, so sometimes it’s actually more economic to (consciously!) take a shortcut first and fix it later (or never).

Why shortcuts are like broken windows

In 1969, psychologist Philip Zimbardo conducted an experiment to test a theory that later became known as the Broken Windows Theory.2

His team parked one car without license plates in a Bronx neighborhood and another in an allegedly “better” neighborhood in Palo Alto. Then, they waited.

The car in the Bronx was picked clean of valuable parts within 24 hours and then passersby started to randomly destroy it.

The car in Palo Alto was not touched for a week, so Zimbardo’s team smashed a window. From then on, the car had a similar fate to the car in the Bronx and was destroyed in the same short amount of time by people walking by.

The people taking part in looting and destroying the cars came from across all social classes and included people who were otherwise law-abiding and well-behaved citizens.

...

The responsibility of starting clean

While working with code doesn’t really feel like looting a car, we all are unconsciously subject to the Broken Windows psychology. This makes it important to start a project clean, with as few shortcuts and as little technical debt as possible. This is because, as soon as a shortcut creeps in, it acts as a broken window and attracts more shortcuts.

Since a software project often is a very expensive and long-running endeavor, keeping broken windows at bay is a huge responsibility for us as software developers. We may not even be the ones finishing the project and others have to take over. For them, it’s a legacy code base they don’t have a connection to yet, lowering the threshold for creating broken windows even further.

There are times, however, when we decide a shortcut is the pragmatic thing to do, be it because the part of the code we’re working on is not that important to the project as a whole, because we...

Sharing models between use cases

In Chapter 5, Implementing a Use Case, I argued that different use cases should have different input and output models, meaning that the types of the input parameters and the types of the return values should be different.

Figure 11.1 shows an example where two use cases share the same input model:

Figure 11.1 – Sharing the input or output model between use cases leads to coupling between the use cases

Figure 11.1 – Sharing the input or output model between use cases leads to coupling between the use cases

The effect of sharing in this case is that SendMoneyUseCase and RevokeActivityUseCase are coupled to each other. If we change something within the shared SendMoneyCommand class, both use cases are affected. They share a reason to change in terms of the Single Responsibility Principle (which should be named the “Single Reason to Change Principle,” as discussed in Chapter 3, Inverting Dependencies). The same is true if both use cases share the same output model.

Sharing input and output models between...

Using domain entities as the input or output model

If we have an Account domain entity and an incoming port, SendMoneyUseCase, we might be tempted to use the entity as the input and/or output model of the incoming port, as Figure 11.2 shows.

Figure 11.2 – Using a domain entity as the input or output model of a use case couples the domain entity to the use case

Figure 11.2 – Using a domain entity as the input or output model of a use case couples the domain entity to the use case

The incoming port has a dependency on the domain entity. The consequence of this is that we’ve added another reason for the Account entity to change.

Wait, the Account entity doesn’t have a dependency on the SendMoneyUseCase incoming port (it’s the other way around), so how can the incoming port be a reason to change for the entity?

Say we need some information about an account in the use case that is not currently available in the Account entity. This information is ultimately not to be stored in the Account entity, however, but in a different domain or bounded...

Skipping incoming ports

While the outgoing ports are necessary to invert the dependency between the application layer and the outgoing adapters (to make the dependencies point inward), we don’t need the incoming ports for dependency inversion. We could decide to let the incoming adapters access our application or domain services directly, without incoming ports in between, as shown in Figure 11.3.

Figure 11.3 – Without incoming ports, we lose clearly marked entry points to the domain logic

Figure 11.3 – Without incoming ports, we lose clearly marked entry points to the domain logic

By removing the incoming ports, we have reduced a layer of abstraction between incoming adapters and the application layer. Removing layers of abstraction usually feels rather good.

The incoming ports, however, define the entry points into our application core. Once we remove them, we must know more about the internals of our application to find out which service method we can call to implement a certain use case. By maintaining dedicated incoming ports...

Skipping services

Aside from the incoming ports, for certain use cases, we might want to skip the service layer as a whole, as Figure 11.4 shows.

Figure 11.4 – Without services, we don’t have a representation of a use case in our code base anymore

Figure 11.4 – Without services, we don’t have a representation of a use case in our code base anymore

Here, the AccountPersistenceAdapter class within an outgoing adapter directly implements an incoming port and replaces the service that usually implements an incoming port.

It is very tempting to do this for simple CRUD use cases since in this case a service usually only forwards a create, update, or delete request to the persistence adapter, without adding any domain logic. Instead of forwarding, we can let the persistence adapter implement the use case directly.

This, however, requires a shared model between the incoming adapter and the outgoing adapter, which is the Account domain entity in this case, so it usually means that we’re using the domain model as the input model, as described...

How does this help me build maintainable software?

There are times when shortcuts make sense from an economic point of view. This chapter provided some insights into the consequences some shortcuts might have to help decide whether to take them or not.

The discussion shows that it’s tempting to introduce shortcuts for simple CRUD use cases since, for them, implementing the whole architecture feels like overkill (and the shortcuts don’t feel like shortcuts). Since all applications start small, however, it’s very important for the team to agree on when a use case grows out of its CRUD state. Only then can the team replace the shortcuts with an architecture that is more maintainable in the long run.

Some use cases will never grow out of their CRUD state. For them, it might be more pragmatic to keep the shortcuts in place forever, as they don’t really entail a maintenance overhead.

In any case, we should document the architecture and the decisions why...

lock icon
The rest of the chapter is locked
You have been reading a chapter from
Get Your Hands Dirty on Clean Architecture - Second Edition
Published in: Jul 2023Publisher: PacktISBN-13: 9781805128373
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime

Author (1)

author image
Tom Hombergs

Tom Hombergs is a software engineer by profession and by passion with more than a decade of experience working on many different software projects for many different clients across various industries. In software projects, he takes on the roles of software developer, architect, and coach, with a focus on the Java ecosystem. He has found that writing is the best way to learn, so he likes to dive deep into topics he encounters in his software projects to create texts that give structure to the chaotic world of software development. He regularly writes about software development on his blog and is an occasional speaker at conferences.
Read more about Tom Hombergs