Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling different user types in an application

Many web applications I've contributed in (mostly ASP.NET), need to handle multiple and different user types.

Let's say you have a school portal, which both pupils and teachers use daily. On the front page of the application the users are met with almost the same GUI except some links to some tools only the teachers have access to. Let's say this is a messaging tool. A teacher can have different roles which defines who the teacher can send to.

For example:

  • A teacher with the role Publisher are allowed to send to everyone in the school.
  • A teacher with no extra roles are only allowed to send to everyone in his/her classes.
  • In the future, parents will also be able to access this portal and see detailed information about their children.

The problem I always get into is that my code is always getting cluttered with if-statements when handling different user types all over the application. Not only because of the different user types, but also by different business rules. I feel I can't find any way to properly handle different user types.

I guess the concept of roles in ASP.NET kind of solves this, but you would still end up with if-statements around the application.

My question is: Is there any best-practice on how to handle different users/user types in an application without infecting the code with if-statements?

like image 505
Anders Stensaas Avatar asked Oct 31 '22 13:10

Anders Stensaas


1 Answers

You should split these responsibilities (like the sending capabilities of a teacher for example). You can do this by using the strategy pattern.

So a teacher has an extra property Publishing, which serves as an interface. The implementation can have multiple realizations (e.g. NoPublishing for a teacher who does not have publishing functionality, or DefaultPublishing). Each teacher can have its Publishing property set to either NoPublishing or DefaultPublishing. It can even be changed runtime if needed.

An example:

public class Teacher
{
   public IPublishing Publishing { get; }
}

interface IPublishing 
{
   void Send();
}

public NoPublishing : IPublishing
{
  public void Send() 
  {
     // Implementatation
  }
}

public PublishDefault : IPublishing
{
  public void Send()
  {
    // Send a message the default way
  }
}

Create a teacher:

var teacher = new Teacher();

Create a publisher strategy.

var defaultStrategy = new PublishDefault();

Connect them

teacher.Publishing = defaultStrategy;

Now you can send a message by:

teacher.Publishing.Send();

Depending on which Publishing strategy has been connected it will either send nothing or send something the default way.

You only need to instantiate each used Publishing strategy once and reuse it for each Teacher (or even other classes who needs to be able to send).

When you need other publish functionality, just add a new strategy (e.g. SmsPublishing, LetterPublishing etc).

You can even change the strategy on the fly if it is needed (by reassigning the Publishing property).

Why not implementing the interface not directly in Teacher?

  • Separation of Concerns principle: IPublish contains a specific and different responsibility.
  • Possibly IPublish contains functionality that can be used later in different classes or even other projects, so it is more reusable.
  • Testing is easier since IPublish does not need any knowledge about Teacher.
  • Possibility to realtime change the behavior of publishing in Teacher.

(note: I don't have a compiler here, so code is only for explanation purposes).

like image 188
Michel Keijzers Avatar answered Nov 15 '22 06:11

Michel Keijzers