Upgrading eZ Platform from Symfony 3 to 4 and beyond
eZ Platform is the flagship product of eZ Systems. Our software enables developers and editors to build and manage complex web sites and applications using a multitude of features. As a development platform we need to pay special attention when doing upgrades. Much more so than if we were a product tailored to a group of end users.
eZ Platform has been developed on the Symfony Framework from 2012 onwards, leading to the second major version of eZ Platform 2.0 in December 2016. With our next major iteration, eZ Platform 3.0, in the works we wanted to take the opportunity to share some of our insights from upgrading our backend framework from one major version to another.
Our team had earlier experience with upgrading Symfony, with eZ Platform 1.x using Symfony 2.8 and 2.x using 3.4. The changes between the two versions were an evolution, rather than a revolution. The jump from Symfony 3 to 4 proved to be more radical - as 4.0 introduced a new directory structure, a new way of managing features: Symfony Flex
With eZ Platform 3.0 we wanted to make sure to take advantage of all the capabilities made available. Not only to keep up with the times, but because wanted to make our product more modular - it is a perfect use case for Flex. We also wanted to provide access to the latest components like Messenger for teams working with eZ Platform.
An interview with our migration lead
To share some practical learning from our journey from Symfony version 3 to 4, I had the opportunity to sit down with Maciej Kobus from our engineering team and ask him a few questions about the topic.
Can you tell a few words about yourself and role at eZ?
My name is Maciej. I've been working here at eZ for almost three years. My major responsibility is developing new features for eZ Platform. Also I managed the migration process to Symfony 4.
eZ Platform is migrating to Symfony 4.4 from 3.4. Can you provide a rough overview of the process and how long it took your team to achieve this?
First, we analyzed backwards incompatible changes to have rough overview on what would break. This gave us an answer how big of a process would be. We knew it wasn't going to be hassle free. In addition to code adjustments, we had to redo our meta repositories since we wanted to adapt to Flex and its directory structure. This was a challenge on its own since we had a consolidated, single file configuration. I wanted to split configuration files per package to bring us closer to modularity in the future.
Since we have a large number of bundles it wasn't easy to get started. It also revealed pain points of our architecture and how some things were coupled together. One thing couldn't work without another - we often had to go from one package to another and fix things in a particular order. We approached it without a big plan, fixing errors as they showed up. We could have spent a lot of time planning and analyzing, but the truth is - you can't predict everything.
With an application of this scale you are going to experience a lot of unexpected issues. What's more - there is no single person who knows every little detail of eZ Platform. So, in the beginning one person had to do a lot of digging and reverse engineering. Once the application was working for the most part it was possible to delegate tasks to other people.
For the time frame I think it took around three to fours weeks of hard work to get application running and another couple of weeks or so to fix the biggest issues. There are still smaller tasks on the version migration being worked on before we can roll out with a final 3.0 release.
What was the most challenging issue you faced? Was there something that was easier than you expected?
I think the single biggest issue we had was simply the amount of packages we maintain. It was mentioned in previous answer, but I will repeat myself: it isn't easy if you are dealing with that many dependencies. Sometimes you come up with new features and forget about tidying up the code which leads to technical debt in a long run. Of course this is due to time constraints and strict release schedule we've committed to.
Symfony 4 introduced changes to the Dependency Injection Container. Services are now private by default so you can't access them directly from the container. This is actually a big issue for us, because we relied on this feature extensively to improve developer experience. We had to make tough decision about removing Dynamic Settings feature from our product because it wasn't compatible with the new version of Symfony.
We kept quite a bit of deprecated code between major releases. If done by the book, deprecations should be removed in next major release, but we still had some deprecated solutions used internally. We had to find all occurrences and fix them, which is never easy with the codebase of this size. I believe you should always look at the bright side of things. In this case, we gained huge knowledge about many neglected parts of our architecture and we are able to plan on how to improve them. Also, the increased modularity will make the codebase more maintainable going forward.
There were a lot of easy parts though. In many cases changes needed to be made were simple but repetitive. Upgrading to next major version usually starts with removing all deprecated code use. It wasn't different in our case and it turned out to be easy in most cases. If we needed to change from one interface to another, we could do that automatically using simple tools available in almost any modern IDE.
What do you see as the biggest improvements in Symfony 4 over Symfony 3? Have you done any benchmarking?
There are many improvements that are coming with SF4. Personally, I'm a big fan of Flex and how it simplifies installing new bundles. I hope we will be able to go Flex route . Idea of installing eZ Platform via `composer require cms` is beautiful, isn't it?
I haven't done extensive benchmarking so I can't say Symfony 4 is faster than 3. In our case, we also switched to PHP 7.3 which adds a lot of boost in performance. This is something we can observe on daily basis. I think it was a really good move and people will quickly love working with PHP 7.3 and other latest versions.
Do you have any advice for anyone looking to upgrade their Symfony 3 application to Symfony 4? Any recommended tools or practices?
Yes, first thing first - be patient and prepared for the unexpected :) I'd say get a good IDE first because you are going to need refactoring tools in the process. There are some tools showing you deprecations, our team used Deprecation Detector and PHP Unit Bridge, both provided by SensioLabs and Symfony.
Deprecation Detector showed us where we use deprecated functionality and what had to be done before approaching the framework upgrade effort itself. Also, we found out that if your application is built with many bundles, refactor them individually and then enable them one by one.
What about the future: Do you plan integrating Flex? What is your take on upgrading to Symfony 5 in the coming years?
We definitely plan on doing it! I even prepared a working Proof of Concept. Licensing issue is holding us currently from submitting eZ Platform to the public Flex recipes. We currently use the GPL license and would need to change it to MIT in order to be able to put our recipe into official repository. This is something that needs to be resolved with help from lawyers.
With eZ Platform Enterprise Edition (EE) not all of the code is made available as open source. This introduced another technical challenge as we need to host a private Flex server for the Enterprise Edition. Initially I was unsure how to achieve this, but after some research we were able to pull it off. We can use Flex to distribute our proprietary packages.
I'm an advocate of adapting to new framework versions. A new version usually means they've added a lot of cool features we could use. The migration also taught us we need to be better at avoiding using deprecated methods to make it easier for us the next time.
This might in fact happen sooner than later. Just recently we decided that we would aim for Symfony 5 compatibility with eZ Platform, but this effort is in very early stages and it is too soon for us to commit to it. This is not only due to us, but some of our dependencies might not be ready yet. However, moving to Symfony 5 is now an internal goal going forward.
First, I would like to thank Maciej for providing honest insight on how our product engineering team approached a major reworking of the internals of our application. It goes to show that continuous evolution of an application is a necessary to keep it relevant in a competitive marketplace. This has to be considered as sustained investment in the future.
This is no mean feat, especially when you are building tools for other developers to build their solutions on. Developers are certainly a very demanding audience. It is also worth noting that for software with a long lifecycle best practices and trends come and go. The ideal solution from just five years ago might today be considered a fractal of bad design. But that is just another day in the life of a software developer. The only constant is change.
If this is your first time reading about eZ Platform, I recommend you take a look and maybe sign up for a demo. At the time of writing our most recent stable version of eZ Platform is 2.5.6. If you're interested in seeing the change happening live, check out the master branch where eZ Platform 3.0 is being worked on currently. Be sure to check the dependency repos too.
For an overview of features in the next major version of eZ Platform, read these blog posts:
UPDATE: eZ Platform (now known as Ibexa DXP) eventually launched on Symfony 5: eZ Platform 3 runs on Symfony 5 and PHP 7.4