20

Trying to apply Uncle Bob's clean architecture to an application I'm maintaining and I'm having difficulties with use cases and duplication/reuse. It's my understanding that usecases should be self contained and that duplication is to be expected but this does not seem to make sense with what I'm dealing with. I feel there are multiple use cases that should end up using other use cases.

Here is a very simplified example of 4 use cases that exist separately but that are also dependent on each other in the following way.

BulkSendUsersToUnit               
    SendUserToUnit   
        AddUserToMandatoryGroups  
            AddUserToGroup 

Each of them have validation, repository calls and conditions that always apply. Basically if I was doing this with services they would simply be methods that I would call from where I need them.

Can I/should I inject use cases in other use cases using DI?

What am I missing here?

1 Answer 1

30

A use case is not a method.
A use case is not an object.
A use case is not a layer.

A use case is a story about a user, using the software, in a particular case.

So it should come as no surprise that different use cases can reuse the same code.

But maybe you watched one of the video'spaywalled where Bob makes out like a use case is part of your architecture.

enter image description here

Well don't worry. It's just a name for the boxes in one of his layers. He's used other names for it:

enter image description here

Does this mean Uncle Bob is wrong? No. The Interactor / Use Case / Application Business Rule / Oh-pick-a-name-and-stick-with-it layer is where you ignore all of the needs of your application (details) and focus on the needs of the user going through a particular use case. But this location in your code is not THE use case. The use case is the whole story from when the user clicks a button to when they see the result.

So should interactors (or whatever you want to call them) use other interactors? Well this is the rub of following DRY to the extreme. You're not allowed to put the code from AddUserToGroup anywhere else right?

Baloney. If AddUserToMandatoryGroups means something different, has a different reason to want to change than AddUserToGroup does then it's ok to give AddUserToMandatoryGroups its own add-user code. Even if right now it's a character for character copy of the code in AddUserToGroup. If you have good reason to think these need to be able to change independent of each other it doesn't matter if right now they look identical. Apply DRY to repeating ideas. Not code.

As for Dependency Injection, that still works fine whenever you want to decouple what from when.

Bulk shitlist = new Bulk(annoyingUsers, bannedForLifeUnit);

Register.OnIveHadAllICanTake( ()-> shitlist.send() ); 
9
  • 3
    Nice code example. ;) Commented May 1, 2018 at 21:02
  • 9
    To follow Java naming conventions you should capitalize the "l" in "shitlist" i.e. shitList - oh wait!! Why is MY name in there!? Commented May 2, 2018 at 3:01
  • 1
    Duplication is indeed fine if two use cases have different reasons to change. But what about similar use cases that have pretty much the same reason to change(e.g. FollowUserUseCase and UnfollowUserUseCase)?
    – Max
    Commented Oct 31, 2020 at 13:52
  • 1
    @Max reusing code can still be a good thing. But the more code is used the more care must be taken when refactoring it. Commented Oct 31, 2020 at 13:59
  • 1
    @konrad A user subscribing to a magazine, getting monthly issues of it, and getting sent a "time to renew" email sounds a lot like a use case to me. Commented Feb 27, 2022 at 18:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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