#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2011
    Posts
    3
    Rep Power
    0

    Object Design tips: Users with multiple roles / functionalities


    I'm working on a webapp which will have two, possibly more, user types that will have different functionalities available to them once they log in.

    For example, there is a Company user who can post news / info about their company and there are ordinary users who can subscribe to company notifications etc.

    Some sites have a completely separate login for different user types and appear to keep them separate. However I still ultimately see them as "users" and will share some core functionalities, I also do not want to close the possibility of users having multiple roles. So I would like to have a single login which directs the user to a profile area that displays the core user functionalities, then, depending on their roles, have the additional functionalities and privileges appended.

    I gather this is actually pretty common so is there a conventional design for this?

    Right now I'm thinking of having a User class with the different role classes inheriting from it:

    Code:
    User
    int id;
    string username;
    string firstName;
    string surname;
    List<String> roles;
    etc;
    
    
    Company extends User
    string companyName;
    List<News> articles;
    etc;

    The problem I see is that while both are "users" of the site, a User perhaps relates more to an individual and a Company is obviously an organisation. The User might have properties such as "First Name", "Surname", "Gender", etc. Which are not relevant to an object such as "Company" and I wonder whether this might cause design problems in the future.

    Another smaller issue is that if a user has multiple roles, the "User" variables will be loaded more than once in a session which might cause issues when persisting the object to a database.

    Any ideas on a good design for this situation?
  2. #2
  3. Did you steal it?
    Devshed Supreme Being (6500+ posts)

    Join Date
    Mar 2007
    Location
    Washington, USA
    Posts
    14,054
    Rep Power
    9398
    If you're dealing with .NET, have you looked into the built-in Membership and Role stuff?

    If you have inheritance, be specific about it.
    Have a generic User class for generic user stuff. There's going to be a username and list of roles, but not much else beyond that.
    Inherit from there. You can have a Person class with firstname and lastname and all that, then a Company class with company name and code to retrieve articles.

    The problem with that kind of inheritance is you'll end up doing a lot of coding that tests object types. So instead, aim for more like
    Code:
    abstract class User {
    	int id;
    	string username;
    	List<string> roles;
    
    	abstract bool canHaveArticles;
    	abstract List<News> getArticles();
    
    	abstract Dictionary<string, object> getProperties();
    	abstract string toString();
    }
    
    class Person : User {
    	bool canHaveArticles = false;
    	List<News> getArticles() { throw new InvalidOperationException(); }
    
    	string companyName;
    
    	Dictionary<string, object> getProperties() { return { "Company Name" => companyName }; }
    	string toString() { return companyName; }
    }
    
    class Company : User {
    	bool canHaveArticles = true;
    	List<News> getArticles() { ... }
    
    	string firstName;
    	string lastName;
    
    	Dictionary<string, object> getProperties() { return { "First Name" => firstName, "Last Name" => lastName }; }
    	string toString() { return firstName + " " + lastName; }
    }
    Try to put as much stuff into the base User class that you can. Make the derived classes provide required functionality, not add more. Avoid code that requires knowing exactly what type of User it's dealing with.

    For instance, could you make the whole article thing be a role? And provide the business logic to make sure it only gets added to companies? Then you can push it into User...
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2011
    Posts
    3
    Rep Power
    0
    Thanks for your reply! I'm working with Java, I'm not too familiar with .NET.

    Yeah, I definitely want to avoid the trap of checking user types.

    Thinking more about your design, I'm wondering how to handle a user that has multiple roles - they are both a Person and a Company. Doesn't seem that I can avoid loading multiple user types, and thus some type checking?

    I want to make registration as simple as possible - the user just provides an email/password. Once they are registered and logged in, they get the option to add company details. So I guess everyone is a Person, with the option to also be a Company.

    Right now I only envisage three roles, Admin / Person / Company but I'm aiming for a scalable solution so it is easy to add more roles in the future.
  6. #4
  7. Did you steal it?
    Devshed Supreme Being (6500+ posts)

    Join Date
    Mar 2007
    Location
    Washington, USA
    Posts
    14,054
    Rep Power
    9398
    How can someone be both a person and a company?

    What you're describing isn't user->person and user->company, it's user->person->company. Once you qualify as a Person you shouldn't be going to a different branch in the hierarchy. Only down. Siblings should be mutually exclusive.
  8. #5
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2011
    Posts
    3
    Rep Power
    0
    Well, I also see them as being "roles" each with their own privileges and it's entirely possible for users to have multiple roles in a system. I think this idea loses out in my case though because my understanding of Roles is that the User should be the same type, but they are just granted permission to perform different actions.

    This is why I'm struggling with it logically. I don't know if it makes sense for a Company to inherit from a Person. It makes sense from the standpoint that they are both users of the system, but a Person refers to an individual, a Company to an organisation of individuals.

    I could instead have an Account object and instead of using inheritance I could have a Person and Company object as variables of Account?
  10. #6
  11. Did you steal it?
    Devshed Supreme Being (6500+ posts)

    Join Date
    Mar 2007
    Location
    Washington, USA
    Posts
    14,054
    Rep Power
    9398
    But the way you're describing a Company makes it sound like it's just one person acting on behalf of them.
    Plus
    So I guess everyone is a Person, with the option to also be a Company.
    means that everything a Person can do, a Company can do. Without inheritance you'd have to duplicate all the Person stuff into the Company.

    The only "roles" I see are
    1. Acts like a Person (which everybody can do).
    2. Acts like a Company.

    And all that points to a Company inheriting from a Person. If you're still thinking of a Company as a "company", okay, but that doesn't model what you want to do in the system. For one, a company itself cannot have an account - a company is a collection of people, and if anything happens it has to be a particular person doing it.
    Think of Company as more like CompanyRepresentative.

IMN logo majestic logo threadwatch logo seochat tools logo