Implementing a use case (I) — Intro

Use cases implementation made easy

Maikel González Baile
4 min readJul 19, 2018

This post is part of Implementing a Use Case, a series of posts where I share my learnings on designing, architecting and implementing use cases.

You can either take a look at the code of the application example or the different tags which show the state of the application at the moment of the post.

Problem

When developing a product, as developers, we spend most of our time implementing new features in the form of use cases: “create an user”, “modify the address of an existing user”, “send an email to an user”, etc.

I frequently find developers wondering where to start when developing a new use case. Some of them start figuring out all the entities, their relationship and all the attributes the entities will have, not only for the use case they are currently implementing but also for all the use cases they guess will come in the future. Others start defining the API to allow an HTTP client to execute the use case, so the first code they implement is the controller. In my experience, both approaches tend to lead to the wrong direction because you are missing the important value of an use case, the business rules, the behavior, the acceptance criteria that defines whether a use case should success or fail and how.

Focus on the language your stakeholders (business experts) use to talk about their problems.

My advice is to forget about how the data is going to be persisted in the database, the database scheme for your entities, their relationship as well as how the use case will be finally get executed (HTTP, messaging, a console command, etc.). Instead, focus on the behavior. Focus on the language your stakeholders (business experts) use to talk about their problems. Look at the invariants they implicitly or explicitly describe. All these concepts are the ones that define what your business wants you to implement, the ones that will carve out your product independently of the persistence or communication mechanism you may choose finally. A good architect is who leaves the choice of the infrastructure details until the end and focus on the policies (business logic) instead.

A good architect is who leaves the choice of the infrastructure details until the end and focus on the policies (business logic) instead.

Table of Contents

  1. Implementing a use case (I) — Intro
  2. Implementing a use case (II) — Command Pattern
  3. Implementing a use case (III) — Command Bus
  4. Implementing a use case (IV) — Domain Events (I)
  5. Implementing a use case (IV) — Domain Events (II)
  6. Implementing a use case (V) — Given-When-Then Testing Style
  7. To be continued…

Series structure

How can we do that? This is the first post of a series where I want to show you step by step how I learned to do - what I consider - better maintainable and scalable code.

Along the journey I will be using a simple application example that I guess most of devs are familiar with. A simple code review system with some basic capabilities:

  • A writer can create a Pull Request.
  • A reviewer can request changes on a Pull Request.
  • A reviewer can approve a Pull Request.
  • Once two reviewers approve a Pull Request, the Pull Request is automatically merged.

Based on this simple example, I will be sharing my experience applying different patterns, principles and practices such as:

  • Test Driven Development as the mechanism to force ourselves to focus first on the behavior instead of technical details, as well as the documentation source for our code.
  • The Command Pattern to explicitly represent your application’s use cases.
  • Domain events to explicitly represent the facts that occur in your system.
  • CQRS as a way to horizontally scale your application and make easier the implementation and maintenance of the reading and writing operations of your application.
  • Event Sourcing by putting the events as the source of truth so you will have a detailed changes log of every single action ever done by your application.
  • The SAGA and Process Manager patterns to manage distributed transactions when your application consists of different microservices that co-operate together.
  • Domain Driven Design as the toolbox which explains most of the concepts we will be covering throughout the series.

In every post, I will be adding the explained patterns and code to the repository of the code review application which you can find here. Also, I will create a new release in the github repository for each post I publish so the post itself will have a link to the specific release which will allow you to see how the code looked like at that moment (you can see all the releases here). Therefore, you will be able to see the final design of the application as well as the evolution that the code suffered as long as I explain and introduce new concepts.

I will try to explain most of the concepts with my own words without going into too much technical detail. Posts will have a link referencing other documentation sources where you can find deeper and better explanations about all the concepts. The target audience are people who are learning and getting used to Domain Driven Design, Hexagonal Architecture, SOLID principles, event driven architecture, etc. So my intention is to guide you through all these concepts by using examples and from a high level perspective as there are already awesome books and documentation for you to learn deeply any of these topics.

The chosen language to implement and explain the app will be PHP, the only reason is that it is the one I have been using for the last 4 years so I feel more comfortable using it. Anyway, the same patterns are also already explained in many different languages so you should not have any problem finding a similar way to do the same in your preferred language. Also, if you understand the concept but have some doubts regarding the implementation details you can always post them.

Continue reading the next post where I introduce the Command Handler pattern.

--

--