3

I have something like this

//A marker Interface
public interface User {
}

//2 DTO Classes
public class Administrator implements User{
//getters and setters
}

public class OperativeUser implements User{
//getters and setters
}

//A generic interface
public interface UserService<T extends User>{
    public void createUser(T user);    
}
//Two concrete clases
public class AdministratorService implements UserService<Administrator>{
    public void createUser(Administrator user){
       //specific stuff for an administrator
    }    
}
public class OperativeUserService implements UserService<OperativeUser>{
    public void createUser(OperativeUser user){
       //specific stuff for an operative user
    }    
}

All this because if I write a simple UserDTO then in order to differenciate them I will end with an spagetti code like if is administrator do this and if is operative user do that, so a need to classify the users of my system as a common interface but no common behavior

So my questions are

1.-There is a better way to achieve this kind of hierarchy without inheritance(extends) if yes could you give me some guidence?

2.- Is a good use of markers interfaces the way I did or I misunderstood?

This is base on the following questions and answers

Nice way of factory method pattern with inheritance

Interfaces for DTOs

Thank you very much!

Community
  • 1
  • 1
jam
  • 489
  • 1
  • 4
  • 19

2 Answers2

1

Adminstrator vs other User is really an issue of roles/permissions. And in a mature system, you might have more than just two..

I would suggest you start by adding "roles" & a convenience isAdministrator() check:

public class User {
    public String getName();

    public Set<String> getRoles();
    public boolean isAdministrator();
}

I have proposed Roles as Set<String>'; this will be make it easy to check roles using string constants. (The alternative could beSet`).

This provides a concise way of checking for administrator role, enables User to be a concrete class & removes the need for separate types for "plain" User and Administrator, and enables your role system to be refined & expanded in future.

Bigger systems than this take the Role structure further: they model "Permissions" and allow flexible assignment of Users -> Roles and Roles -> Permissions. However, that degree of sophistication is beyond your current problem.

Thomas W
  • 13,940
  • 4
  • 58
  • 76
1

This question is opinion based.

I'm sharing my views on it.

What you have is a slightly modified version of an Abstract Factory Pattern. The real question here is, do you need all this?

If Administrator and OperativeUser are value objects (as indicated in your question) and will have different properties, why bother creating a super type (User) for them? You will anyways end up doing instance of checks somewhere in your code. In this case your UserService is simplified to something like this (yes plain old method overloading!)

public class UserService {
    public void createUser(Administrator administrator) {
        //create an admin
    }

    public void createUser(OperativeUser operativeUser) {
        //create an operative user
    }
}

On the other hand, if you do have common methods for your Adminstrator and OperativeUser , then they should be declared in the User interface which now is no longer a marker interface.

So to answer your questions

1.-There is a better way to achieve this kind of hierarchy without inheritance(extends) if yes could you give me some guidence?

Answer: Don't use inheritance unless you need it.

2.- Is a good use of markers interfaces the way I did or I misunderstood?

Answer: I don't feel this usage is correct. The reason I say so is because in order to create, let's say and Administrator as per your code sample, I would have to write something like this

new AdministratorService().createUser(new Administrator());

The same can be achieved if you simply overload the methods as I explained above with less code and less hierarchy!

More on why marker interfaces here.

Community
  • 1
  • 1
Pravin Sonawane
  • 1,803
  • 4
  • 18
  • 32
  • Hi Pravin, the thing about the type user is because in that way I just can do the following `@Inject @User(Type="Administrator") User administrator;` and `@Inject @User(Type="OperativeUser")User operative;` so If a new user added nothing that already have relase need to be edited and violate Open Close Principle – jam Nov 29 '16 at 17:35
  • @jjam But will you be able to use a `User` as an `Administrator` elsewhere without casting it?. Its not about the convenience of instantiation/injection but about being able to use a `User` instance polymorphically. Besides, I'm not sure if I understand how this violates open/close principle. – Pravin Sonawane Nov 29 '16 at 23:15
  • Yes you are right, I did not realize that my code will work just fine in my particular case but in other part of my project when I need to use a particular user I need to check if that particular object is instance of an x object as you mention early and it will end with the spaghetti code that I trying to avoid at first, so this solve my particular problem and answer my specific questions, thank you very much, – jam Nov 29 '16 at 23:51