Encapsulating business logic using the Command Pattern

Implementing Use Cases in Swift

What is a Use Case?

Source: https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html

By Uncle Bob's definition, a Use Case is basically an Interactor, which is responsible for encapsulating our Business Logic, and should have a well defined intention. But in the real world, it's very common to end up with bloated Interactors, in architectures like VIP/Clean and Viper, for example.

To avoid that kind of problems and really use interactors as a layer for logic integration, we can look back at the Command Pattern and think of a use-case a single command or logic operation.

With that in mind, our UseCase will represent a single operation, with an Input and Output, inspired on the Command Pattern.
Which can be either synchronous or asynchronous, consumingCore Dependencies” like Networking, Analytics, Services, etc.

Another very interesting path to take is to define domain specific errors, which will kind of translate some Core Dependency error or logic error to a readable and well defined output, that can make your code base easier to understand.

The common case

An Interactor without Use Cases

Refactoring to the Use-Case approach

Previous example, refactored with the Use Case approach

UseCase examples

Synchronous example.
Asynchronous example.

Conclusion

This way, we end up with a very well defined operation/command, with a simple API that can bring you a great deal of reusability possibilities.
This technique also fragments your logic into smaller parts, while applying the SoC (Separation of Concerns) concept with a SRP-friendly approach that also simplify your tests.