13

Does we need to create UseCases for each method from Repository interface in domain layer?

For example assume that I have such Repository interface

interface ThingRepository {
    void create(Thing thing);
    void delete(Thing thing);
    List<Thing> readAll();
    int size();
}

As you can see there is size() method that returns number of records in database or in file, whatever. And this method is pretty fast. I guess that there is no need for UseCase for this method because it wouldn't block UI thread and can be executed synchronously.

So could you explain me when you create UseCases and when you don't. Basically is there any rules for UseCase creation?

Sorry if there is some misunderstanding in this question.

Thanks in advance ;)

Also I opened the same issue on Android-CleanArchitecture repo on github but nobody answered it yet that's why I'm asking here.

Mike Herasimov
  • 1,319
  • 3
  • 14
  • 31
  • 2
    UseCases are meant to represent high level domain logic, like "fetch user list". Fetch user list may pull things from a network, or a local repository, or some other method. You wouldn't want it to be a 1-to-1 mapping to your repository because the repository sits on a different layer in your architecture. 1-to-1 mapping between domain and data would defeat the purpose of separating them. – drhr Apr 03 '17 at 18:45
  • @drhr so in my case you suggesting me DO NOT create UseCase? – Mike Herasimov Apr 03 '17 at 18:53
  • @drhr "1-to-1 mapping between domain and data would defeat the purpose of separating them" I see, I guess usage of MVP is better in such case, but what do you can suggest in my case? – Mike Herasimov Apr 03 '17 at 18:56
  • What I mean is that you don't necessarily want to build your UseCases up strictly from lower levels of abstraction. There will likely be plenty of situations where a UseCase just needs to use one lower level function - that's OK. But you shouldn't feel like you need your higher level logic to represent each and every piece of lower level logic. Notice how the domain & data layers are separate in the README. A UseCase could end up pulling many of them together, which is where they really fulfill their purpose. Might help to think top down instead of bottom up here. – drhr Apr 03 '17 at 19:00

1 Answers1

5

Fun question!

The easy answer. You as a programmer do not write the use-cases. Your specifications document is where you derive your use-cases from. Once you have your use-cases all lined up nice in your kanban board, then you start solving those problems. One at a time.

Notice I said programmer? That's only if you go to work, sit down, boss hands you a specification, and you code for 8 hours and then go home. However, that's usually not the case and some of us are architects as well. (This is an oversimplification for my following point.)

From the context of your original post, and why everyone in the comments is jumping on you is because of this...

Does we need to create UseCases for each method from Repository interface in domain layer?

Simply put: In test driven development, you don't write a single character of code until you write a failing test first. The same goes for use-case driven development; you don't write a single character of code until you have a use-case you are trying to solve.

and

As you can see there is size() method that returns number of records in >database or in file, whatever. And this method is pretty fast. I guess that >there is no need for UseCase for this method because it wouldn't block UI >thread and can be executed synchronously.

What that sounds like is. "I didn't have a use-case to display the number of records in a database so I added a size()function to the repository interface because I thought it should have one, and I'm trying to write a use-case for it." That simply not the goal of use-case driven development.

So all that being said, let's come back to the size() function in your ThingRepository. The only reason you should have added the size() function is to solve a use-case.

Example: "The application should display the total number of all Things in the database.

The problem with that use-case is, if I'm displaying Things to a user, then more than likely my Presenter has a _ThingRepository injected into it. I would much rather run a _ThingRepository.readAll().Count() because it's either already in memory, or needs to be at some point for other Presenter functions, which is much faster than making another trip to the database (which could possibly be in another country) for a simple record count.

If you were trying to solve the size() use-case first, your kanban board is probably out of order, as "Displaying things to user" is a Presenter function and an implementation detail that should be put off until the last responsible moment.

So, does the size() function even really need to be there? Not unless you have a really good reason to put it there, and not until you need it.

Adam Vincent
  • 3,281
  • 14
  • 38
  • I wish you focussed you answer more on the general question more so than the size detail. The answer started very well but it could be expanded quite a bit – Ced Dec 12 '21 at 08:01
  • 4 years ago, I was about 1 year into my career and not very experienced lol. I agree this could be expanded to a more general audience, but then I'd be re-writing the book I read that gave me the ideas that drove the answer. So my expanded answer is simply; Check out a couple of books: Clean Architecture - Robert C Martin. Domain-Driven Design - Eric Evans – Adam Vincent Dec 12 '21 at 08:48
  • I'm reading it as we comment ahah – Ced Dec 12 '21 at 17:50