symfony 0.6 to Symfony 5: What I learned from the framework
Today I was a speaker at SymfonyWorld, the global online conference related to the Symfony framework. In my talk I travelled through my history with the framework and shared some of the lessons I learned over the years, focussing specifically on the lessons I learned by using the framework and seeing the evolution of the framework. This blogpost will share those same lessons.
I started my journey with Symfony (or actually symfony back then) at version 0.6.7. The framework back then was truly full-stack: You either used it or you didn't, there was no in-between. The framework was MVC, there were controllers, models and views. The models were still Propel and the views were still plain PHP. And with the code I wrote back then, the controllers were huge. I did not yet know about correctly applying best practices in terms of thin controllers, using seperate services etc.
Take your time to learn
One of the first lessons I learned while using symfony was before I even really started using the framework. I was working at a company called Dutch Open Projects and we were building a software as a service project. I don't think the term software as a service even existed yet, but we were doing it. The first version of the project was built on top of the Mambo CMS. Well, I don't know if you can remember Mambo, but at some point we decided that for security and application structure purposes, we wanted to migrate to something else and frameworks were just starting to pop up and be interesting as an option instead of using a CMS or custom PHP as a base. So I started digging into what frameworks were available. I made a list of the potential candidates and I cannot really remember which ones were on that list, except that I know that at least Zend framework and Symfony were serious contenders at that moment. The list had all the pros and cons for each framework. Together with my colleague Peter I looked at that list of features and we felt it was hard to decide just based on that list which framework to use. Zend framework was a serious candidate, but the features and especially the solidness and everything that Symfony had already done that the other frameworks hadn't made us consider Symfony. The fact that we didn't have to write all of this boilerplate code just to get started helped a lot. And then Peter said: why don't we just take a day, just one work day. We sit down, we take symfony and we just start building a project. And that's when I learned that it is OK to really take your time to learn about a tool and to see if the tool is the right fit. So we sat down, we downloaded Symfony and we started building a simple prototype application. At the end of the day we had an actual working prototype application. It was very simple. It didn't have all the features that we needed, of course, but it was enough to convince us that Symfony was a good choice. We felt it to be impressive that in such a short time we can get so much done and we can have actually something that works at the end of the day. That was the deciding factor for us. And that was a great choice because it started a major journey in my career.
As I worked more and more with symfony and symfony came to the stable 1.0 release, I really started appreciating the structure the framework brought me. Before I started using Symfony, every time I created a new project, I used to copy paste code from the previous project and then started altering it because over the time I'd learn some new lessons about how to build an application. But that meant that over time somehow my application seemed to change and change and change a bit more. And then having to go back into three or four applications ago, I'd have to really adapt again. Oh, what am I doing here? How was this structured? Wasn't this done differently? Oh, no, that was in the project after that. And one of the things that I found out when I started using Symfony was that it was great to have one common structure.
As I got more and more excited by Symfony and what Symfony was offering I pitched the idea to my boss to organize a Symfony conference. And my employer Dutch Open Projects back then had (and they still have) a beautiful villa out in the forest. My boss really liked the idea of organizing a conference at their office. There was a beautiful lawn. There was a swimming pool, and there was enough room to put up some tents and stuff like that. So we ended up organizing SymfonyCamp, the first symfony conference that ever happened. People brought their tents, put it up on the lawn, and we had a big tent where all the talks were. We had a lot of pretty important people back then in the symfony community that came over. Dustin Whittle, Jonathan Wage, Kris Wallsmith, they all came over. Fabien was also there, which was amazing to us because having the man himself at the conference was great. The talks were great, but one of the things that I learned as well is that talking to people and exchanging experiences and ideas and approaches: You learn a lot from that as well. If you have the opportunity, then go to a meetup or a conference and meet other people. Don't just attend the talks but also talk to other people. Preferably talk to people you don't know yet because the connections that you make at a conference are connections that can sometimes even last over the years. There's still a couple of people from SymfonyCamp that I still talk to on a regular basis. Sometimes I ask them a question. Sometimes they ask me a question. But we're still connected.
Symfony 2: Seperation of concerns
Symfony 2 was, in terms of the framework, a completely new framework. A lot had changed since symfony 1, and that triggered another lesson. The introduction of components made me learn about creating nicely isolated pieces of code where each part of the code has its own purpose, its own responsibility. Put all the related code in the same namespace and offer some kind of public API where you can make sure that the public API stays as stable as possible and you can refactor all the internals if you want to. And this also made the code so much easier to test because it's not a big ball of spaghetti anymore. Every class has its own simple methods and every method can easily be tested. Of course, one of the lessons I also learned was to not make it too abstract because that adds the risk of adding way too much complexity in terms of the amount of layers of code that you need to go through just to find out what's happening.
Migration should not be an afterthought
Migrations are part of your application planning. At some point, you know that you're going to have to migrate either to a newer version of your framework because the older version isn't supported anymore or maybe to a whole different platform because your platform isn't supported anymore (or whatever other reason).
In symfony 1 most of the code that I wrote was completely tied into the whole framework, so upgrading from symfony 1 to Symfony 2 really meant to take out all those pieces of code or maybe even rewrite parts just to make it work with Symfony 2. In 2013 I went to SymfonyLive London and and my mind was completely blown by two people doing a talk called The Framework as an implementation detail. While some of the elements of that approach are a lot more common these days it is still good to to have a look at this video or basically any video on the topic of hexagonal architecture. Keep in mind when watching this video: In those days this was a relatively new approach in PHP and in Symfony. And just to summarize (and I'm going to completely butcher their content): The idea of hexagonal architecture is that you write your code in such a way that your business logic is completely isolated from any other logic. Your business logic should not need to know about where your data is stored, where your files are stored and what you know, what kind of APIs that you connect to to make it work. Or even what framework you use. If you take that approach then once you want to migrate from one version to the next version of your framework or even from one platform to another platform, you could just take that piece of business logic, copy it over into your new project. And the only thing that you need to do is make sure that the glue between your business logic and the rest of your application is fixed. If I had taken that approach in symfony 1, the upgrade to Symfony 2 would have been a lot less painful.
Symfony 3: Stability
As Symfony 3 came and we upgraded our applications to the new version, I realized something about stability. The newer versions of Symfony gave a much clearer versioning, which you could almost fully trust on. Small changes and bug fixes, new features, BC breaks: It was pretty much clear what was happening and the changes were documented really well in articles on symfony.com and the way that deprecations were handled was also a lot better. Things were first marked as a deprecation and then a warning was given and then eventually the deprecated code was removed in the next major update. One of the major things I learned from Symfony at this point was not about development at all. It was about communication.
It was about communicating changes in code in such a way that people understand what is happening inside the code and that they have time to respond before their code breaks. And of course I tried to apply this to myself. Not that I really maintain a framework of the size or popularity of Symfony; I don't. I really don't manage a lot of open source in the first place. But I can still apply those lessons to my own code and especially to things that I publish to the outside world. For instance, if you work on an API, you basically offer a similar thing as what the framework does, it's a programming interface. And whether you connect to that over HTTP or you connect to that using just PHP... it's still the same thing, you offer a programming interface and people are going to rely on that programming interface.
So once you start changing things inside that API you really need to carefully take care of changing things, especially the outside behavior. If you're looking to change things or if you plan on dropping support for certain functionality, you should communicate that well. And you should describe what what will be changing or what you will be removing and in what ways people can still solve their problem. You should help your user to keep on using your software. And if you really drop support for something and there is no replacement: Be clear about that and give users some time to find a better solution. Or better yet, if you don't offer a solution yourself, tell them how they can still solve the same problem in a different way.
Symfony 4: A healthy environment
One great addition that really helped to get rid of environment specific configuration was the introduction of environment variables. This greatly reduced the risk of accidentally committing the wrong configuration file and then deploying them to production.
And I'm afraid, yes, I am guilty of having done that.
It also made it a lot easier to deploy because we didn't need to have complex deployment strategies that would copy over the correct configuration file during the deployment and things like that. Instead things like database credentials, API keys etc. could just be registered directly as an environment variable in the different environments and combining that with the way we use Docker these days makes it a lot easier. On development you can easily configure your environment variables in your docker-compose file. On production, you can configure those in whatever you use for production with Docker. We use Rancher, which is a nice GUI layer on top of Kubernetes. And I can simply click into that specific application, add some environment variables or change them when I need to change them, save it. And that's it. It works. And I don't need to update any files any more inside the container to get it running.
Common directory structure
Another big change is the directory structure. We've had the same directory structure since Symfony 2 and I was quite used to that, but in Symfony 4 things changed for the better, because now the directory structure that Symfony offered by default was very similar to the Linux file system. It was a lot easier to find stuff if you were already used to working with Linux. One thing I learned from this is that it is a good idea not to reinvent the wheel and use naming conventions and common structures that people already know. By doing that people will quickly understand what they are looking at. They will have a lot easier time trying to figure out where to find whatever file they are looking for. And this is especially important when on-boarding new developers. Now, of course, you can always look for a Symfony developer and hope that you will find a Symfony developer that has experience with the version of Symfony that you use. But if you just look for a PHP developer that has some experience with Linux, then it's actually quite easy to adapt yourself to the Symfony way of doing things. And over the years, I've done a lot of different projects, and every time I go back to a Symfony project, especially the recent projects, I feel right at home because I know where to find things and I don't really have to think about it a lot.
Symfony 5: The release schedule
Now this lesson is not about something introduced in Symfony 5, but it is about something I realized around the release of Symfony 5: The clear release schedule is great! At any moment in time it is very clear what the timeline is for releases. And combine this with the releases that are clearly marked as long term support releases: It makes it very easy to communicate to for instance my customers about which versions are a good choice for their project. The current long term support version is 4.4 and it is supported until November 2023. And I know that Symfony 5.0, which came out in November last year, it is not supported anymore at this point. And the currently supported version is Symfony 5.1, which lasts until January. There's Symfony 5.2 that is supported until July of next year. And I also know that in May we'll get Symfony 5.3 and I can already anticipate on that. This is important for people, at least people like me as a consultant, I regularly have to communicate with people from the business instead of developers. And those business people can be wary of open source. For instance because open source has the image that it's one or two developers in their bedroom working on open source projects whenever they feel like it. Having to communicate on that level with those people that have the power to decide which systems to use it makes it a lot easier to be able to tell them: This is the current version. This is the long term support version. The next version comes out at that point and there will be another long term support version, which will last until a certain point in time, so you can invest in this project using this open source framework. And you know for sure that for the coming X amount of time, you won't have to invest into big upgrades or backwards compatibility breaks. You can use the power of open source. You can reap the benefits from that. And you're not at risk of the project being abandoned or some some kind of unexpected new version breaking all your software.
This is something that I've found recently that is very important and it makes it a lot easier to talk to customers. Even if you're not talking to customers, just knowing that you can work on this software and you know for sure that you don't really have to worry about backwards compatibility breaks and things like that for the foreseeable future is really nice.
There are also two things I learned over the years that are not tied to one specific version of the framework. The first one is the power of the community and you see this strength everywhere: In the pull requests that are being sent to to Symfony, in how the documentation is being written and updated, in the Symfony slack where people are helping each other, but also on less isolated places like open places like Twitter and Facebook and LinkedIn. People can ask a question on Twitter and they will get a response at some point. And even in the wider PHP communities. In the Netherlands we have the PHPNL, a Slack network for PHP developers. There is a separate Symfony channel in there where people can ask questions, other people will help. And, you know, eventually the problem will be solved.
And this happens in a lot of different places around the world.
And that's just how great it is to have the Symfony community just there for you.
If you're looking for a new job, there's tons of people that will help you find whatever the cool job is that you're looking for. And if you're looking for new developers, there's usually some people that will help you find new developers as well.
And I mentioned it already when I talked about SymfonyCamp, how important it is to meet people and to make that connection. And then the Symfony community, there's so many people that you can meet that you can connect with and that may end up being a friend or just a business partner or, you know, things like that. This community is amazing. And I want to thank you for being part of that community.
And the last thing I want to mention is the best invention since sliced bread: Composer. Composer has made my developer life so much easier, so much better. Mind you: Before Composer you had to download all the libraries that you used and you had to put them into the project yourself. They would usually be committed into your version control and you'd be manually responsible for making sure that they were up to date by downloading a new version and replacing the old version with the new version.
And the other thing that you needed to do was make sure manually that all of these libraries were compatible with each other and that there weren't any issues between the different libraries, but also between the libraries and the version of PHP that you were using and all of the PHP extensions that you needed to run those libraries. Composer really changed all of that. And it made my life so much easier. So I'm really grateful. And I want to really give a big thank you to Nils and Jordi and everyone else who worked on Composer over the years. And and of course, congratulations with the release of version 2.0 of Composer!