EN VI

Java - Designing System - User, Admin Subgroups?

2024-03-12 20:00:09
How to Java - Designing System - User, Admin Subgroups

I got to design a system where User will be of two different types - Admins, Customer. Admins can have roles of SUPER_ADMIN, ADMIN, MEMBER. Customer can have roles of OWNER, TEAM_LEAD, TEAM_MEMBER Can not decide what will be right approach.

  1. Use of ENUM, like
public class User {
    private UserType userType;
    private UserRole userRole;
    private AdminRole adminRole;
}

public enum UserType {
    ADMIN,
    CUSTOMER;
}
public enum UserRole {
    OWNER,
    TEAM_LEAD,
    TEAM_MEMBER,;
}
public enum AdminRole {
    SUPER_ADMIN,
    ADMIN,
    MEMBER,;
}
  1. Or use Inheritance, like
public class User {

}
 public class Admin extends User{
  private AdminRole adminRole;
}

 public class Customer extends User{
  private UserRole userRole;
}
 public enum UserRole {
  OWNER,
  TEAM_LEAD,
  TEAM_MEMBER;
}
 public enum AdminRole {
  SUPER_ADMIN,
  ADMIN,
  MEMBER;
}

Solution:

Software design rarely works in a way where there's universally correct ways to design things. Thus, asking what's the correct way? can rarely be answered unless you provide more context. What are your goals? What are the forces that work on the design of the system? This can be an exceedingly long and complex discussion. In a sense, I've already spent 25 years trying to figure out how to answer such questions, and I keep learning new things.

What we sometimes can say, however, is what not to do.

The first option seems to allow, nay even require, that we create user object of the form new User(UserType.ADMIN, UserRole.OWNER, AdminRole.Admin); (I do realize that as given, the User class has no public constructor, but it does have fields, and these fields are going to have values, regardless of whether or not they're explicitly initialized.) We may now ask ourselves: Why does an admin user have a user role?

That seems like a problematic design, so at least, we should, as Yaron Minsky puts it, make illegal states unrepresentable.

This doesn't mean, however, that just because the first option doesn't look like a good idea, that the second option is the one to choose.

What, then, is a good design? We don't know, because we don't know what problem this API is supposed to address.

In order to make a point, let's assume that I suggest this design:

public class Owner {}

public class TeamLead {}

public class TeamMember {}

public class SuperAdmin {}

public class Admin {}

public class Member {}

You're probably gong to protest: But, these classes have nothing in common!

True, which means that you now have to explain why they ought to have anything in common. This is probably because you wish to treat them in some polymorphic way. If so, it seems like a good first step is to have them derive from a base class, or implement a common interface.

If, however, that interface defines no methods, then you can't use it for anything. The same is true for a base class.

I often see people define an inheritance hierarchy that doesn't define any common behaviour, which means that all code needs to do type checks and downcasts before they can use the concrete classes. If so, then, the class already have a common ancestor: Object. The six classes I've defined above do inherit from Object.

If you still protest that that's bad design, then I agree. I'm not trying to argue that the above is good design. Rather, I'm using it as a showcase to demonstrate that having a base class or a common interface is just as bad; it's equivalent to treating everything as inheriting from Object and downcasting.

Thus, you'll need to figure out what you want to do with a polymorphic type, and then let the design evolve once you're able to answer that question.

I often find the Dependency Inversion Principle (DIP) useful in such situations. According to the DIP

"clients [...] own the abstract interfaces"

- Robert C. Martin, APPP, chapter 11

So, figure out what client code needs to do with these user objects, and design accordingly.

Answer

Login


Forgot Your Password?

Create Account


Lost your password? Please enter your email address. You will receive a link to create a new password.

Reset Password

Back to login