Confusing term Interactors in Clean Architecture

Viewed 14290

As per clean architecture, design Interactor is part which contains all business logic. The term Interactor is quite confusing to me. Interactor seems to me like interacting between two different layers like data and presenter.

Is it the right term to use? Can anyone please clear the purpose of Interactor? Which pattern does it follow? If Interactor is not what it seems to me then what is the design pattern for layer-layer interaction?

6 Answers

In the clean architecture approach, the Use Case Interactor is a layer that express the specific business rules. The Use Case Interactor interacts with the Entities (agnostic business rules) to achieve the Use Case intention. Entities can be used in another applications, once they are agnostics, on the other hand, the Use Case Interactors are specific application objects.

Can be found in the Clean Architecture book by Robert C. Martin at chapter 20

If you're familiar with domain driven design, then an Interactor can be compared to an Application Service. Also, it is incorrect to say "As per clean architecture, design Interactor is part which contains all business logic." On the contrary, Entities would contain the business (application-agnostic) logic; whereas Interactors would contain the application-specific logic. The Interactors would call the Entities to fulfill a use case, where a use case might be something like Create Purchase Order.

Going back to using Clean Architecture terms that Robert Martin (Uncle Bob) uses in his training video Architecture, Use Cases, and High Level Design, Uncle Bob says the following:

Interactors are application-specific. That means that any application specific business rule belongs inside an interactor. The interactors achieve their goals with application-specific logic that calls the application-agnostic logic within the entities. For example, the CreateOrderInteractor invokes both the constructor and the GetId method of the OrderEntity. Clearly, these two methods are application-agnostic. It's the interactor that knows how to call those two methods to achieve the goal of the use case.

For your observation that the Interactor seems like it is interacting between two different layers like data and presenter, that job actually belongs to the Boundary. The Boundary sits between the delivery mechanism and the Interactor, where the delivery mechanism might be a desktop application, MVC app, API, etc. This keeps the actual application and business code separate and transferable from one delivery mechanism to another.

He also has a nice diagram in the Extras section showing the interaction if you purchase the video. It looks something like the following:

Delivery Mechanism ==> Boundary ==> Interactor ==> Entity

P.S. The video referenced above is highly entertaining and informational.

Interactors provides implementations for various use cases. Ideally, there should be one interactor per use case but it may differ according to the scale of your application.

Now, why it doesn't make sense for every application? Imagine you have two applications. In the first app, you just need to read a user. In the other application, you just update the very same user. You would have two different interactors like GetUserInteractor and UpdateUserInteractor. If you think about it, UpdateUserInteractor would make no sense for the first application (and vice versa), right? But your business/domain logic for both applications can still be the same where the implementations of both services (read and update) are included, for example, in the regarding business/domain object (or as separate use-case objects). These objects obviously encapsulate application agnostic business rules as they can be plugged under two or more different applications.

The communication takes place between the app and users is often application-specific. As others already mentioned, you can have your interactors execute commands on user actions. Or you can go for another similar way. But the command pattern is really convenient and arguably make the whole code more consistent, uniform, and easy to understand.

Last but not least, the other important aspect of interactors are 'boundary interfaces' which are the classes that polymorphically deployed for both input and output delivery.

(PS: For example, in Android, with the new architecture components, Fragment/Activity can be thought as an implementation of the input boundary as you deliver input events down to your business logic (or domain model) - it's the controller. LiveData is more like the output boundary implementation as it uses observer pattern under the hood and deliver the data back to the UI through the interactor. In this case, I think this makes the ViewModel a strong candidate for being the interactor since it receives the input events (and commands corresponding those events) and also contains the LiveData instance to be observed. Are all these decoupled nice, or, polymorphically deployed? Well, this is mostly related to your design. And with coroutines, now it seems like there's no need for callbacks/listeners - so another dimension into this picture.)

This is my take. I hope it's clear.

Related