The Role-In Stone (part I)
Hello,
There are always times during our journey as developers when we need to handle responsibilities according to several user roles, eg admin vs regular user privileges and so forth. This has been my case lately. I’ve been asked to implement a role based management tool which had to handle Administrators and Players by creating slightly different layouts for each one and paying attention to subtle differences on specific functionalities.
My very first try consisted of url driven request and shared templates in order to detect and display the roles accordingly. Sooner than later, as the functionalities grew, many if-else structures sprouted all across the code, littering and degrading the code significantly.
My next step was to refactor and plan a unique if-else at the earliest stage to detect the role, and then, use a service handler to deal with the specific role. As a result, I had a role factory which was initialized with the user and returned the corresponding role specific handler. There were two classes with the same methods and signatures but with different implementations. This would allow us to create safe abstractions and rely on implementations on execution time.
So, from that moment on, each specific handler will take care of each operation. For example, this is how the handler for the player role would deal with the dashboard action, see image below:
On the other hand, same method, same signature, but different implementation will provide different behaviour for the admin handler. Similar functionalities can be naturally moved up to the parent abstract class RoleHandler and take advantage of inheritance (Template Method pattern, GoF).
However, what if a new role had to be added along with a new bunch of functionalities. Let’s say the Referee role. And let's assume that Referees and Admins share some of the functionalities, and, what is more, they are not applicable to Players. Should we move the common methods up to the RoleHandler class? If we do so, we are also making players inherit the methods. What about the admin-player common functions? The referee inherits all those and we want to avoid that to happen as well. A solution to this could be making unsupported operations to throw an exception what means extra work and clutter, making the code harder to maintain.
By and large, the main drawback of this approach is the lack of control over combinations.
End of part I
There are always times during our journey as developers when we need to handle responsibilities according to several user roles, eg admin vs regular user privileges and so forth. This has been my case lately. I’ve been asked to implement a role based management tool which had to handle Administrators and Players by creating slightly different layouts for each one and paying attention to subtle differences on specific functionalities.
My very first try consisted of url driven request and shared templates in order to detect and display the roles accordingly. Sooner than later, as the functionalities grew, many if-else structures sprouted all across the code, littering and degrading the code significantly.
My next step was to refactor and plan a unique if-else at the earliest stage to detect the role, and then, use a service handler to deal with the specific role. As a result, I had a role factory which was initialized with the user and returned the corresponding role specific handler. There were two classes with the same methods and signatures but with different implementations. This would allow us to create safe abstractions and rely on implementations on execution time.
So, from that moment on, each specific handler will take care of each operation. For example, this is how the handler for the player role would deal with the dashboard action, see image below:
On the other hand, same method, same signature, but different implementation will provide different behaviour for the admin handler. Similar functionalities can be naturally moved up to the parent abstract class RoleHandler and take advantage of inheritance (Template Method pattern, GoF).
However, what if a new role had to be added along with a new bunch of functionalities. Let’s say the Referee role. And let's assume that Referees and Admins share some of the functionalities, and, what is more, they are not applicable to Players. Should we move the common methods up to the RoleHandler class? If we do so, we are also making players inherit the methods. What about the admin-player common functions? The referee inherits all those and we want to avoid that to happen as well. A solution to this could be making unsupported operations to throw an exception what means extra work and clutter, making the code harder to maintain.
By and large, the main drawback of this approach is the lack of control over combinations.
End of part I
Comments
Post a Comment