A Use Case in a Nutshell

Let's look at a use case to guide us on what we need to build.

First, let’s discuss what a use case actually does. Usually, it follows these steps:

  1. Take input.
  2. Validate business rules.
  3. Manipulate model state.
  4. Return output.

A use case takes input from an incoming adapter. You might wonder why this step was not called “Validate input”. The answer is that use case code should care about the domain logic, and we shouldn’t pollute it with input validation. So, we’ll do input validation somewhere else, as we’ll see shortly.

The use case is, however, responsible for validating business rules. It shares this responsibility with the domain entities. We’ll discuss the distinction between input validation and business rule validation later in this chapter.

If the business rules were satisfied, the use case then manipulates the state of the model in one way or another, based on the input. Usually, it will change the state of a domain object and pass this new state to a port implemented by the persistence adapter to be persisted. A use case might also call any other outgoing adapter, though.

The last step is to translate the return value from the outgoing adapter into an output object that will be returned to the calling adapter.

With these steps in mind, let’s see how we can implement our “Send Money” use case.

To avoid the problem of broad services discussed in the chapter “What’s Wrong with Layers?”, we’ll create a separate service class for each use case instead of putting all use cases into a single service class.

Creating the SendMoneyService class

Here’s a teaser:

Get hands-on with 1200+ tech skills courses.