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?

2 Answers 2

31

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
  • 10
    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)? 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
2

Use cases should not be reused inside another use case, as this leads to a spaghetti scenario where a modification in one use case breaks another. Use cases should handle all necessary changes because it is their responsibility.

Use cases must be independent and contain their own rules and validations.

If some logic or process is repeated, it should be moved to an application service, which can be reused by all the use cases that need it.

In this diagram, you can see an example how service is used:

enter image description here

Of course, the scenario could be more complicated, but I tried to represent a simple scenario that shows the flow and communication between components.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.