1

I'm working on a project that requires several different users in the system, all of which have overlapping responsibilities; we've isolated two possible ways of tackling this problem, but we're unsure which of them are the most correct way of going about it.

Option 1: Create a virtual super-class for all the user-classes to inherit from. This super-class will have a boolean field for each of the responsibilities, allowing us to toggle which of the sub-classes have which responsibility.

  • Pros
    • One single class for all the sub-classes to inherit from, letting us toggle responsibilities via boolean fields
  • Cons:
    • It's essentially a god-class, which means it holds too much responsibility

Option 2: Create nineteen (19) interfaces, each representing one of the available responsibilities, and then have each of the user-classes inherit from this pool of interfaces in order to determine their responsibilities.

  • Pros
    • It allows us to seperate the concerns into several interfaces
  • Cons
    • We'll be in over our heads with interfaces, making it difficult to keep track of

So which is the best way of doing it, or is there perhaps a better way?

To elaborate my question I'm including the graphic below; it showcases the relations between the different parts of the system and the different users.

enter image description here

R means read access and RW means read + write access.

As you can see it's a bit of a mess of interlacing attributes.

8
  • 4
    Composition over inheritance. You're welcome. Commented Oct 19, 2015 at 8:45
  • 1
    @SilviuBurcea that tells me nothing Commented Oct 19, 2015 at 8:45
  • 1
    Instead of having tons of interfaces to implement, use composition. Instead of storing tons of booleans, store more meaningful objects, like permissions and make a list of them. Another approach, if you like booleans, is a permission list implemented as a BitSet. Commented Oct 19, 2015 at 8:48
  • 1
    @SilviuBurcea define composition Commented Oct 19, 2015 at 8:49
  • I almost did it, instead of inheriting things, store them as properties. I just gave you an alternative for storing tons of booleans as properties, make a list of them and give them more semantics. You may want to Google the concept composition over inheritance, you will find plenty of examples. Commented Oct 19, 2015 at 8:52

2 Answers 2

3

Option 3: Create individual objects corresponding to specific responsibilities, and then have each user hold a collection of these.

The collection of responsibilities for a user will contain only the responsibilities assigned to the user, i.e. you don't need an object to indicate the lack of a responsibility.

You worry it is "overkill" to create 19 classes for 19 responsibilities, but actually it is the simplest solution. If you indicate the same with 19 boolean fields on the base class, you have the same number of semantic entities, but a much more complex system overall, since each new responsibility increases the complexity of all user classes. By having the responsibilities as objects separate from the user, a new responsibility will not affect the user classes at all, but only the specific parts of the program which check for this specific responsibility.

Also, you can easily separate the assignment of responsibilities into a configuration. This would be quite tricky with option 1 and impossible with option 2.

Note: If you need to distinguish between read and read/write you need more that 19 boolean fields or 19 interfaces. For option 1 you need tri-state enumerations rather than booleans. For option 2 you need 38 distinct interfaces. For option 3 you can have a boolean flag on each responsibility which indicate if it is read or read/write.

11
  • wouldn't that create a ton of classes instead? Commented Oct 19, 2015 at 9:10
  • 2
    @ElectricCoffee: One for each responsibility - but you get the same complexity with the other proposed solution, except in option 1 and 2 you let the complexity infect the user classes (with an explosion of flags or interfaces), here it is nicely separated.
    – JacquesB
    Commented Oct 19, 2015 at 9:13
  • I've expanded my question, elaborate your answer? Commented Oct 19, 2015 at 12:52
  • @ElectricCoffee: I would be happy to. What in particular do you find unclear in the answer? Or do you have further questions?
    – JacquesB
    Commented Oct 19, 2015 at 14:37
  • Well since it's one class for each responsibility, and there are 3 variants of each responsibility, it leads mme to believe I have to create 57 different classes, which seems a little beyond overkill. So I'm just wondering how it would make most sense to go about this Commented Oct 19, 2015 at 14:51
3

I'd opt for option 3, use composition.

Depending on what you are doing with the responsibilities, you might be able to use an enum for them:

public enum Responsibilities
{
    Responsibility1,
    Responsibility2,
    ...
}

Then your user class might be something like:

public class User
{
    private List<Responsibilities> _responsibilities =
        List<Responsibilities>();

    public void AddResponsibility(Responsibilities responsibility) =>
        _responsibilities.Add(responsibility);

    public bool HasResponsibility(Responsibilities responsibility) =>
        responsibilities.Contains(responsibility);
}

If your need logic behind each responsibility, replace the enum with an IResponsibility interface and have each responsibility class implement that interface.

1
  • I've expanded my question, elaborate your answer? Commented Oct 19, 2015 at 12:53

Not the answer you're looking for? Browse other questions tagged or ask your own question.