In this blog post I’m going to tell you a story that explain why our team preferred Symfony 2 over Yii which we used for a long time and doing our best to contributed something. How it happened and what caused us to make such a decision.
You might have thought that there was some big meeting where we decided that our next framework would be Symfony because blah blah blah. I’m afraid to disappoint you. The true story is more obvious and trivial.
Initially we were forced to use Symfony 2 as one of critical technical requirements in the project we were going to undertake. So we had a quick look at Symfony 2 documentation, cookbooks, new features etc. At that point in time everything looks very similar. Same MVC concept, just different template engine, ORM etc. Yes, Symfony 2 has dependency injection container but it doesn’t change things much. More over we have a few team members with awesome experience developing projects with Symfony v1.
We knew that migration would not be easy and that we will have to invest more personal time to maintain our normal development speed. We’ve just been open for new experience and another challenge.
This project has crazy deadlines. In addition, we’ve been using Symfony the same old way we used to do it in Yii. We tried to keep same principles, styles, approaches which we know works great for Yii. And that’s really was not a good idea. But it’s fine for the first time.
Next project was on Symfony too. There we tried to fix all misunderstandings and closely follow Symfony philosophy. Basically we have started doing things in Symfony-way and that fixed many architecture issues. Here we first time meet composer/packagist, PSR-2 and many other nice tools and helpers. Finally, we get closer to Symfony community.
I think only doing our 3d project we felt success and satisfaction from our new “venture”. Since that time we stopped considering Yii.
Now I will try to explain in more details why we decide to stay with Symfony. What we especially like. What are the most useful things.
Jumping ahead a bit I’d like to share results of our internal team voting. We’ve decided to ask all our team members in order to be sure that we are on the right way and if anyone wants to switch back to Yii. I was personally surprised that nobody voted for Yii. From the very begging some team members been skeptic, often criticize it saying that it is enterprise, Yii is simpler to develop and so on. But finally they let Symfony concept penetrate in their soul and now it is no way back :) They’ve made a few attempts in personal micro projects, but finally show the white flag.
So why we moved to Symfony 2?
Actually it’s all about code management and code maintenance. Perform code fast from the very beginning is really easy. We never had issues with this and I’m sure you too. Real issues shows up later, when project grows up and become long-term. Almost all our projects are long-term (from 2-3 months to a year or even more).
That’s why it is critical for us to use approaches and techniques to effectively manage our code in a long run. We had year-long projects in Yii. And it was hard to keep them nice after 3 month of development. We always have small issues, have to apply small workarounds, hooks and so on. Yeah, it works but no fun to support.
We want to keep our code base well-organized and follow some clear principles which will care about code and protect it from corruptions. That was our main concern. And no matter how long project is going. One month or one year. We want feel happy with our code anytime and keep interest in development. There shouldn’t be any hooks and workarounds. Honestly hooks are killing project team. Who like dirty laundry? It usually start like this: OK, today I will do this small workaround quickly and tomorrow I will find and replace it with better solution. Remember this point. It is a way into the abyss.
What code management issues we had in Yii?
TDD (test driven development)
First issue is code testing. Tests should be written easily. Nobody will follow TDD if one simple test requires mocking half of application services. It is a big overhead. And Yii wasn’t helpful enough.
Global service locator (Yii::app()) just killing attempts to write tests. You start with one test, then you understand that you need to mock this service and another one, and both of them depends on 3rd service… bah! Many services in Yii interact with each other. That sucks.
Then we have tight coupling. And it is tricky to perform application decoupling. Ideally we should not do this at all. It should be initially decoupled.
So it is really hard to follow TDD in Yii. Yes, they have CWebTestCase, fixtures, base integration with phpunit and so on. But that’s simple stuff. It is much more useful to test services/models without mocking other services, without mocking framework classes.
Having some ActiveRecords as framework core is fine. It’s really useful for beginner. But Yii active record is too simplified and again too tightly coupled. I know that when we talk about ActiveRecord we will most probably have tight coupling there because entity should get connection in order to save something without directly passing it. But that’s not the reason to extend this idea everywhere in the class.
More serious issue why Yii active record doesn’t fit our needs is because of missing separation between entity and entity manager (queries). In Yii we have to use static methods for querying models and non-static methods for model logic. In Yii ActiveRecord and ActiveFinder provided by a single instance. That’s not cool when queries mixed with entity getter/setter.
Another point regarding static methods for querying. Static methods can’t have state except for static one. And if you want to mix few conditions you have to merge criterias. With propel I do like this $query->filterByThis(1)->filterByThat(2)->find() and keep my filters/criterias separately. In Yii you will define them with arrays (you can’t create conditions dynamically) and then merge array or criterias. Quite boring job. Also I can’t have few query classes extended from base one, where I will separate filters/conditions based on domain business logic.
We need something more serious. In Symfony 2 we have Doctrine 2. Quite serious ORM with unit of work and other cool things. But it was too serious for us :) And finally we stick to Propel ORM. I know it has some issues too and generated code far from best coding standards. But it works best for us and we get clear separation between entities and queries. Main things we like about propel are: real getter/setter (we can have a look how they implemented and override them if needed), db schemas and migrations generation, behaviors that actually a generator addons, reach set of generator properties and integration in some Symfony components like forms and validator.
I know Yii team follows their own coding style and that’s fine. But internally we have different one and that was an issue.
Actually we did not have documented code guidelines before. We’ve made a few attempts to write them down but it was too boring writing about intentions, class names, brackets and so on. It require much time. We secretly had some common standards but it just wasn’t documented.
Problem is that our code guidelines were quite different for that Yii team use. We have contributed some extensions to Yii community and of course we wanted to keep our extensions similar to native Yii code. Finally we have to switch between different code guidelines all the time. For extensions we used Yii code guidelines, for real projects our own code style. Nothing cool.
We want to use something globally. In our code, in the components we use and in the frameworks itself.
Now we follow PSR-2. We were close to it and migration was super easy. Symfony2 follows PSR-2. Many components follows it too. It works for us and we really appreciate php-fig for their work. I know there are many polemics about PSR, but most of them about PSR-3. PSR-2 is good enough. At least for us.
One more things is namespaces. As you know Yii do not use namespaces. And it doesn’t help in building application. Namespaces helps to shortcut class names, helps with classes autoloading and so on. Overall we feel more comfortable with namespaces rather than without them.
Let’s see how we used to get an extension in Yii. First we need to find it on Yii site, download, manually copy it to the project directory, attach it in config. Then we need to monitor Yii site for updates. It’s fine, but not in 2013.
Right now we uses composer. It’s really awesome when you can just define project dependency and run update. It will download extension/lib/component/bundle or whatever you want, setup autoloading and you can use it. Also composer will care about all component dependencies and download them. With one command you can update all components to most up-to-date version. You can specify which version to use. Maybe you want to download test and dev versions. That’s easy too.
There are some other things like contributing. It’s super easy to publish your package and make it globally available. It’s easier to define versions, easier to fork extensions, easier to send pull requests and so on.
Composer is extremely useful tool. That’s exactly what php community needs.
We use composer to manage our dependencies. We don’t keep external dependencies in our repos at all. What we need now is just keep composer.json in actual state.
Let’s get back to code maintenance. Most often when people want to say that the code should be cleaner, they often say that they need the right architecture. What that means?
First of all that means that software should be based on some principles and follow good practices. So yeah, we want our software been principled. That’s why we try following SOLID and not follow STUPID. And Symfony helps us with this. Symfony 2 architecture relies on the same principles and that’s super awesome.
I want you to get me right. We still has warm feelings to Yii, keep saying best regards to Yii team, they did and doing great job. It’s awesome framework, and we spent several man-years writing code with this framework, contributed number of extensions and advised many beginners cross different forums. It just doesn’t fit our needs any more. We still follow updates regarding Yii2, and was waiting for Yii2 for so long… But we have to move. And the next point in our trip is Symfony 2.