I have a Java EE application using standard stack of spring/hibernate/jsp and typical layers:
- @Repository (or DAO)
- @Service
- @Controller
Each repository has a number of find... methods (e.g. for a BookRepository: simple findById, findByTitle, findByAuthor, more complex findMostUsed, findMostCommented etc.)
Service layer contains the business logic calling repositories as it supposed to be.
Controllers call service methods and populate ModelAndView to be used in JSP.
Of course, there are methods with some complex business logic in services. But it is annoying that there are a lot of stupid methods like this:
public List<Book> findMostUsed() {
return repository.findMostUsed();
}
public List<Book> findMostCommented (boolean includeRating) {
return repository.findMostCommented(includeRating);
}
...
So they are just a simple delegation (there is no business logic in these find methods - a DB query in the repository does all the selecting and grouping).
If I need to change a method in the repository the service needs to be changed as well. After 2 years of developing there was no need to add any logic to those methods - only queries and its parameters were changed.
I saw even worse design where people created Controller -> Facade -> Service -> Repository -> DAO with every layer teeming with methods like this.
What would be the better design?
Maybe to remove all those methods and transform service to be more generic (such as BookPricingService, BookRatingService, etc. instead of single BookService (which violates single responsibility principle btw)? Then the Controller will call both Service and Repository layers which is not good.
Maybe to make find methods more generic such as findByCriteria(criteria) to reduce their number. But the problem is that the queries are so different and this will end with a kind of switch-case block that picks the correct query/parameters based on the criteria type. Btw, Spring-Data also recommends one method per query with @Query annotation.
Maybe this is just the price we should pay to have the abstraction layer?