Laravel Experience: The Unfinalize Package

It is time to talk about Laravel. Really.

I worked with Laravel for more than a year in my last project in a very large fashion based online shop. We built enterprise applications and I my gut feeling about is and was: it is a good framework to get things done – especially for juniors or people newly getting into programming – but is it good: nahh.

But the last couple of weeks, in my opinion, the Laravel community broke some essential rules. I am talking about the Unfinalize package:

Laravel Unfinalize Package
Unfinalize Package. Source: Laravel News

The package touches vendor code (!!!!!!!!) and removes all final keywords they find. This is not only a punch in the face of every open source package maintainer, it is also very dangerous. In this blog post, I want to address why and start a new blog series here: My Laravel Experience and why I think it is not a good framework. 

Magic, Magic and much more Magic: The Laravel way of doing things 

Have you ever worked with Laravel? If yes, you will relate to the scenario that you want to debug something, but do not know where the implementation is. The reason is very easy: the facade pattern that is used by Laravel very intensively. 

Laravel Cache Facade
Laravel Cache Facade: Nearly empty class with many magic methods.

Laravel gives you a facade of anything – Cache, Database, HTTP – and defines the behavior with config files. If you get any error message that you do not understand and want to debug: good luck.

Thankfully, the Laravel documentation is pretty good and there is a big community that most probably had the problem you face in the past. For debugging, browsing framework code and trying to understand what is done in which way is almost inpossible.

Laravel uses the Reflection API intensively. And this means a couple of things:

  1. Performance: Reflection inspects, changes or runs the behavior of a class on runtime. This means, additional memory and thus an impact on performance.
  2. Confusion: basically, you can not rely on what you read. For instance, a method is defined as public. Can you surely rely on it? Are you 100% sure that it is not switched to private on runtime?
  3. Readability: Having a mix of configuration files and reflection goes on the cost of readability. At the end, only Laravel core developers will fully understand what the actual code does.
Laravel Artisan Command Load
Artisan Command Initialisation: The command classes are expected to be in the Commands subfolder and handled by Reflection.

Unfinalize: Much More Magic

A few weeks ago, Unfinalize package was released and hyped by among others the Laravel creator. In fact, he has previously expressed his distaste against the final keyword.

Unfinalize is a composer package exposing an command that uses cs-fixer library to remove all final keywords on vendor packages. With further configuration, it is also possible to remove annotations and attributes.

To be very honest and clear at this point: this is very, very, very dangerous (a.k.a. not reproduceable bugs on production), irresponsible against the own code base and disrespectful against the package maintainers. Let me explain you point by point:

Dangerous: Because the package maintainer relies on his own implementation. If he declares something final, he will most probably be willing much easier to introduce breaking changes. Because his code is final – and thus can not be changed in application code – the breaking change will be tagged as a minor or bugfix version.

Irresponsible: In any environment of programming languages, there is a golden rule that the vendor is the vendor and not meant to be getting touched. Introducing dependencies not only in your code base, but also in the vendor brings unnecessary complexity which is a smell. At the end, we want reproducible builds on every environment and system. Changing third party vendor code breaks this rule.

Disrespectful: Adding the final keyword to a class or method is an „extra effort“, meaning that the maintainer had to type extra characters and the developer did this by intention – either he does not want internals to be public, or the project is based on composition over inheritance or whatever. Touching the maintainers code means you do not care about his intentions.

Conclusion

If you did not understand it so far: the package is dangerous and should be avoided. I have very less understanding for packages like this because of the reasons mentioned above. Seriously, why not just forking the project and doing the changes you want? This does not make code better, but is consequent and less dangerous and shows more respect for your code and the maintainer.

But I want to hightlight another point, which I think is very important: by sharing my experience with Laravel and why I think it is not a good framework, I do not want to say it is bad at all. A lot of companies make their money with it, many developers started programming with it because the learning curve is very low and I respect this. I just outline it is not meant for me.

In my case, I will add all the unfinalize package to conflict in the composer.json of all packages maintained by me, my company Ucar Solutions UG or our open source project Keestash.