The SRP states that a class (module) should have only one reason to change. The "duties" of an Interactor in Bob Martin's clean architecture are, per use case: receive requests/inputs from a controller; orchestrate domain entities to fulfil the requests; and prepare the output data.

Does this imply three reasons to change? (ie whenever inputs change or domain functionality is expanded or extra output fields are added.) If necessary, what would be a good strategy to resolve this? (eg, CQRS?)

My current approach is to make a use-case Interactor module with three classes, one per each concern, and a fourth Facade/ Mediator class for orchestration and clients interfacing. However, doesn't this push SRP violation up onto the module level?


As pointed by @Robert Harvey, the term "duties" was used rather sloppily. The actual design issue has been the large changes to the interactor needed both when the domain changed, and the OutputData fields/formats changed (less so with input). Aren't these two distinct reasons for change?

As I realised from @Filip Milovanović and @guillaume31, SRP is not violated, esp. with three separate classes in the interactor module. Also, at the module level, the "Common Closure Principle" is perhaps more appropriate than the SRP. The CCP ("Gather into components ... classes that change for the same reasons and at the same times.") might suggest to separate the interactor classes. (But then the classes corresponding to the same use case would be spread out between locations.) Thanks to the answers and comments, these trade-offs have become much clearer to me.

  • Depends on how much logic or behavior there is in the receiving input and preparing output. I would agrue those should be just dumb "data mappers". – Euphoric Jan 26 at 14:24
  • There's some logic in preparing output. The main issue is that both the domain evolves (which is fine), but also formats/fields of the output data change often. The latter has caused a lot of rework in interactors. – Tupolev._ Jan 26 at 14:54
  • Perhaps an Interactor is essentially a three-side adaptor: Input to Domain and Domain to Output? Then it's natural for the Interactor to change once any of the three changes. With little input/output logic in the interactor (as commented by @Euphoric) SRP shouldn't matter much. With considerable (non-reducible) logic, it might be necessary to separate the responsibilities? – Tupolev._ Jan 26 at 15:26
  • 1
    I'd say its OK to separate responsibilities if you find that there's a need. But if you find that you always have to make changes in several classes that constitute the same Interactor, then perhaps the concerns should be separated in a different way (depending on what kind of change patterns show up, and what parts of code you wan't to isolate from change). P.S. "However, doesn't this push SRP violation up onto the module level?" - I'd say no, because the specific responsibilities still remain in the subcomponents. – Filip Milovanović Jan 26 at 15:43
  • Otherwise, when you take that to the extreme, you could argue that the whole program violates SRP because it "does everything" - but that's not the point of SRP. – Filip Milovanović Jan 26 at 15:43
up vote 9 down vote accepted

The "duties" of an Interactor in Bob Martin's clean architecture are, per use case: receive requests/inputs from a controller; orchestrate domain entities to fulfil the requests; and prepare the output data.

Does this imply three reasons to change?

You're confusing duties with responsibilities. More specifically, you're confusing "should have only one responsibility" with "should do only one thing."

The responsibility of an interactor is to "interact."

The responsibility of a data access class is to access data. It doesn't have four responsibilities because it creates, reads, updates and deletes; it has four duties.

If you're a short-order cook, your responsibility is to make meals. You don't split your duties into separate employees. You don't have one employee that cracks the egg, another employee that turns it over, and a third that puts it on the plate. You perform all three.

  • I definitely confused duties and responsibilities. The cook analogy made it much clearer - thank you! I still think there might be two reasons to change for the interactor module in my case, as I tried to corroborate in the question edit. Whether any remedies are justified is another matter. – Tupolev._ Jan 31 at 13:01
  • Please suggest on stackoverflow.com/questions/50998636/… – Dipendra Sharma Jun 23 at 11:24

For a method, receiving input parameters and returning an output are not responsibilities per se.

Mapping/formatting the data to make it ready for transfer to another layer might be considered one, but it can be externalized to a Mapper object.

And no matter if you orchestrate calls to one, 2 or ten collaborators, it's still a single responsibility, so no problem here.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.