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 '18 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. – schrödingercöder Jan 26 '18 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? – schrödingercöder Jan 26 '18 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 '18 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 '18 at 15:43

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. – schrödingercöder Jan 31 '18 at 13:01
  • Please suggest on stackoverflow.com/questions/50998636/… – Dipendra Sharma Jun 23 '18 at 11:24
  • Excellent answer! This question and many other similar posts seems to conflate use case steps (behavior) with objects (structure) which makes me think that OO isn't yet well understood by many. – Denis FB May 23 '20 at 20:38
  • @Denis: Objects are state + behavior. Perhaps that's why you see the conflation. – Robert Harvey May 23 '20 at 20:39
  • @RobertHarvey: I should've said "confuse" to be precise. What I meant is that I've noticed a tendency of defining Clean Code Interactors (classes) containing only one method corresponding to one use case step. IMO this produces a lot of unnecessary and tight coupled classes where none really owns the data and the whole use case. – Denis FB May 23 '20 at 21:02

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.


One reason to change is not as clear as Robert Martin corrected himself in his videos. IMHO, the better explanation is One role to change (c), which means that only one role should change a module. For example, some of the possible roles are DBA, a product owner, a business analytic, a designer, a lawyer with the new calculation rules etc. That means, that css changes should not affect the business logic, and the DB sharding shouldn't change use case logic. That's all. And this rule is for modules only, someone could apply it to classes or methods, but the reason this rule was created for is to split code by roles who can change the code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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