0

I need to create a program to manage an association.

Members of this association have different roles and each role has specific characteristics. My problem is that I'm not able to abstract this concept in my program. This is what I thought so far.

Create a class Person that has generic attributes for members and not members such as Name, Surname, Birthdate, etc. Then create a class Member that inherits from Person adding some attributes for the members such as Id, EnrollmentDate, etc.

As regards the role, I thought to use interfaces. For example, if a member is an instructor, IInstructor, if he/she is a vehicles manager, IVehiclesManager, etc. and each one has a different behaviour.

My problem is that a member for example can be both an instructor and a vehicles manager and I don't know how to implement this. Do I have to create three different classes, one that implements IInstructor, one IVehiclesManager and one that implements both or is there another way to do this?

The problem is that there are various roles and each member can have any combination of these.

It's the first time I use interfaces and maybe I'm missing something. Am I on the right way or should I use a totally different approach?

  • 7
    Congratulations, you've unlocked "Wizards and Warriors"! ericlippert.com/2015/04/27/wizards-and-warriors-part-one – bitsoflogic Apr 10 at 14:02
  • @bitsoflogic: Nice. :-) – Eric Lippert Apr 10 at 21:35
  • Advice, drop the I in your IInterfaces. As far as your domain logic should be concerned it is dealing with an Instructor not an IInstructor unless its your domain is concerned specifically with Apple Instructors. Anything interacting with your domain logic will probably pass in SQLInstructor, data.Instructor, or who cares how it was defined and named type which are instances of domain.Instructor. – Kain0_0 Apr 11 at 0:31
  • 3
    @Kain0_0 Using an uppercase I in front of the name of every interface is the standard for C# though. Being the bad version of Hungarian notation, it's not the best option technically, but if you don't do this, your code will confuse pretty much every C# programmer. – R. Schmitz Apr 11 at 9:50
  • @R.Schmitz: It's not Hungarian notation, or even the moral equivalent of it. Java does the same thing with Interface and InterfaceImpl, just more poorly. – Robert Harvey Apr 11 at 14:50
1

The Spec

I'd advise you to take another look at the functional specification and identify nouns, because a lot of those will become class names in your program.

If there is no functional specification, create one. I don't like writing documentation either, but trust me, it will prevent so many headaches. If that seems a bit overwhelming right now, just have a relaxed read of this series of articles, it will explain why and how and has a template to get started. Ultimately it's just explaining to other people what the app does, so not that much different from what you did when you wrote this question.

Nouns

One of the sentences in this question will probably end up in that specification as it is:

Members of this association have different roles and each role has specific characteristics.

The nouns here are "Members", "association", "roles" and "characteristics". Your specific issue concerned the combination of members and roles. What's important to note here is that "role" is a noun. Long story short, a Role would make a good class. Even if a Role ends up containing nothing more than that name-string, it still makes sense because it allows you to say in code "There is a Role and I give it the name "Instructor". There is another Role and I give it the name "Vehicle Manager".

You can then connect these roles to members in different ways, the simplest among them being a Role just having a list of Members. If a Member wants to manage vehicles, you check if they have an entry in the vehicle manager Role. How exactly you solve that will depend heavily on the rest of your app though.

Some more advice

I'd advise you to avoid inheritance. It's overhyped by universities and tutorials. Every time you are tempted to use inheritance, think if you can't use composition instead. This wasn't really the issue in this case, but you will ultimately run into the problems described in the link user bitsoflogic commented under your question.

As an example, I'd like to cite your given structure, Person and Member. Does a non-member person even make sense in your application? If a person is a user who has not logged in yet, then you have no idea what their name, surname, and date of birth are.

Now, it's understandable if you want the personal information name, surname, and date of birth separate from other more business-oriented data. You will just run into less problems if you use composition instead: Just make every Member have an instance of a new class PersonalInformation which contains name, surname, and date of birth.

3

I would suggest to approach it from different angle.

Don't start with classes, start with behaviour your application should have.

In question you mentioned only static structure of the data you expecting to have in your application. So I assume that first behaviors you need to implement would be:

  • Create a member
  • Add a role to the member
  • Display member information
  • Member can execute actions provided by roles member has (press a button in UI for example)

Then working approach would look like below

Create a member

  • Create a class Member containing properties required for member creation
  • Create a view for Member class
  • Create a class which will receive member data and save it to the persistence layer of your choice(file system, database etc).
public class Member
{
    public string Name { get; set; }
    public string LastName { get; set; }
    public DateTime Birthday { get; set; }
    public DateTime EnrollmentDate { get; set; }
}

Add role to the member

  • Because different roles will have different behaviours, but from the member point of view should be treated in a same way - we will introduce roles as an abstraction IRole.
  • Create concrete Roles by implementing IRole
  • Add collection of roles to the member by adding Roles collection to the Member class
  • Create view where roles can be added to the member
  • Create class which will link members with their roles and saves this link to the persistence layer of your choice.
public interface IRole
{
    void ExecuteAction();
}

public class Instructor : IRole
{
    public void ExecuteAction() => { } // write instructions
}

public class IVehiclesManager : IRole
{
    public void ExecuteAction() => { } // allow to use vehicles by members
}

// Member class will change 

public class Member
{
    public string Name { get; set; }
    public string LastName { get; set; }
    public DateTime Birthday { get; set; }
    public DateTime EnrollmentDate { get; set; }
    public Dictionary<int, IRole> Actions { get: set; }

    public void Execute(int roleId) => Actions[roleId].ExecuteAction();
}

Display member information

  • Create a view(if not created already in previous steps) which will display member's information
  • Add a view with the button to execute action of member's roles

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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