7

I have two service beans called PowerUserManager and SimpleUserManager. Both @Service annotated classes have about 20% of the code in common.

I've built an inheritance tree with a common abstract class (BaseUserManager) to reduce redundancy between the two classes.

                               BaseUserManager
                                      |
                               ---------------
                               |             |
                       PowerUserManager  SimpleUserManager

Then in my @Controller or whatever client class, I use the @Autowired annotation to inject both PowerUserManager and SimpleUserManager and I use one of them depending on the instance of the User I'm dealing with.

I'm not comfortable using inheritance to factorize code especially in the service layer. Do you Spring fellows see a better way to do this ?

webpat
  • 1,889
  • 16
  • 21
  • Are the public interfaces the same, with differing behaviour, or do they have distinct methods that only apply to each type of user? – Romski Mar 01 '13 at 06:22
  • @Romski the PowerUserManager have distinct methods that only apply to the PowerUser – webpat Mar 05 '13 at 00:31

1 Answers1

3

You should ask yourself some fundamental questions before considering inheritance over composition in this case, and in general:

  1. Are all user managers a BaseUserManager? Is this a IS-A relationship in any possible case?
  2. Does it make sense to expose BaseUserManager public API everywhere where a user manager is invloved?
  3. Does BaseUserManager have a single responsibility?

If the answer is yes, then inheritance is the right way to go. Otherwise, you should probably redesign into several smaller components and treat PowerUserManager and SimpleUserManager as service facades.

Community
  • 1
  • 1
Szymon Jednac
  • 2,969
  • 1
  • 29
  • 43
  • What do you mean by single responsability for BaseUserManager ? – webpat Mar 05 '13 at 00:32
  • Does BaseUserManager follow the principles of OOP or is it a messy utility class, that just simplifies common use cases in other managers? For example, if BaseUserManager would be responsible for: permission & role management, registration, account activation, account listing and making coffee, then it might be a good idea, to delegate those tasks to a set of more specialized components. – Szymon Jednac Mar 05 '13 at 09:15
  • @SzymonJednac we have the same situation. we have four(maybe more in future) integrations with accounting software. We are on spring boot, rest api. All of them have common endpoints like addAccount, editAccount, validateCode, validateType, validateName. I used the same approach. One abstract class lets say, AccountService and for each child one like XeroAccountService. I have the same scenario again for their oauth. I am thinking about delegation or composition. do you have any reference I can use? Controller is receiving the callback for all of them but i do not know about the Service layer. – Mohamad Eghlima Oct 28 '22 at 23:00
  • 1
    @MohammadEghlima I'd start a new question, if I were you - it's a different use-case after all (+ you could provide more details about your current approach). That being said, I would avoid sharing code via _inheritance_ in the integration realm (at all costs; external interfaces are likely to change), but also in general. It leads to all kinds of mess in the long run. If you need some inspiration, you should look up `Hexagonal Architecture` as a design pattern. It's not a sliver bullet, but it might help you out. – Szymon Jednac Oct 30 '22 at 00:30
  • thanks. i will read about this design pattern. – Mohamad Eghlima Oct 31 '22 at 16:35