Improve your voters with the Open/Closed principle

Think about provided examples and improve them with some OOP concepts.

Vincent Monjaret
Darkmira FR
2 min readJun 15, 2020

--

In software engineering one of the main challenges of an application is the maintainability… A lot of new developer tends to work on framework without the knowledge of concepts of OOP (Object Oriented Programming) as SOLID principle and others. In this article, we are going to refactor the voter example provided in the Symfony documentation by applying the Open/Closed principle in order to improve the maintainability.

Symfony’s voter example

As we can see this example works totally fine and is easy to understand… but if the project tends to grow over time we are going to have several problems:

  • This class will become longer each time we need to add a criterion, with 2 criteria this class has already 47 LoC (Line of Code). So imagine with 10…
  • When we will need to add criteria we are going to modify the switch case, which is a violation of the Open/Closed Principle.

So, how can we prevent these issues? We need to find a way to add an extra case without adding code, to do so we are going to use a an array, each time we need a new criterion we just need to add it to the array. The DI (Dependency Injection) component of Symfony allows us to easily create a list of services implementing an interface and this is the feature that will make our code easily extendable. Here you can find the interface we will use.

Now lets take a look at the DI’s configuration.To register our criteria, we do have to add a tag to each class implementing the interface. We will then inject the tagged services into our voter as a ServiceLocator.

And our brand new voter is now open to extension and does not have to be modified anymore, the voter will never change regardless the number of criteria we want to use.

Open/Closed voter

So now the criterion responsible for the edition now implement our interface and looks the same as the example provided in Symfony’s documentation.

CanEdit criterion

And the criterion responsible for the view action look like :

CanView criterion

And now to use those criteria we just replace the hard coded attribute by the full qualified name of the criterion, which also improve the autocompletion.

In conclusion, the main challenge with examples in a documentation is to make the code as simple as possible for people to understand the concept, but they don’t really suit for all project. Doing a copy/paste of the documentation will guarantee you have a working application, and it’s usually fine for simple projects. That said, you should always think twice when working on long living code base, and such patterns will help you in the long run.

--

--