Why using code as DI config is a win!
In my recent talk on introducing Disco - the DI container with the damn coolest name(tm) - I talk about why I believe that using XML or any other non-code configuration (YAML, JSON, ...) is not a good idea. This stirred some twitter discussion recently which led to this blog post.
Just for the record, for a very long time I was part of the XML camp - just browse my collection of old talks to see for yourself. I praised XML a lot as being the only true DI configuration format. A few years ago when the Spring Framework made its move from "preferring" code over XML configuration at first I did not understand it. After dealing with all sorts of problems every now and then, after a few more years, it finally became clear to me. Whilst XML has its good parts - mainly XSD - it comes with its very own set of problems that I want to highlight briefly:
1. An XML editor won't give you code-completion for PHP classes or methods. The configuration is simply treated as text and has "no meaning" in a programming sense. One can waste a lot of time looking for spelling mistakes of all kinds in an XML configuration file. Trust me, I wasted a lot of time fixing those issues in the last 12 years.
2. Refactoring won't work properly in an XML configuration file. Whenever I rename a class or move it to a different namespace my IDE will properly update all code occurrences, while the XML configuration will be left as is. I need to run a proper search and replace action manually, maybe with some regex foo to change the needed occurrences. If I make a mistake, I won't notice it immediately. I have to either reload my application or as some fellow developers do, run an "integration test" which will try to instantiate each and every dependency the DI container is aware of. This is far, far away from instant developer feedback.
3. An XML editor is not capable of doing proper type checks. I can "inject" any kind of dependency that I want. Type errors can be only detected during runtime which means either an application reload or via running the almighty integration tests. Again, as a developer I want instant feedback and not wait for the integration tests to have passed.
4. XML is just too verbose. Let's have a look at this example from the Symfony DI container configuration:
<?xml version="1.0" encoding="UTF-8" ?> <container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> <services> <service id="dependency" class="\My\Dependency"> </service> <service id="manager" class="\My\Manager"> <call method="setDependency"> <argument type="service" id="dependency" /> </call> </service> </services> </container>
That is 17 lines of code just to express this:
$manager = new \My\Manager(); $manager->setDependency(new \My\Dependency());
That does not seem feasible to me.
At this point the reaction I usually get is that this isn't a problem at all because "there exists this plugin for to handle all the mentioned problems for you". Sure you can, but if the solution to a problem is installing just another IDE plugin, the problem might be solved in a wrong way. And to be fair not even all plugins get things right, mostly because the problem space is too generic.
All this led to the creation of Disco, if you want to know more browse my intro slides or feel free to invite me to speak at your local usergroup ;)