The Hexagonal Architecture training tour
An ever recurring pattern in my life is this one:
- I stumble upon some interesting piece of code, an intriguing book chapter, a fascinating concept, etc.
- Slowly, over the next couple of weeks, my brain realises that, yes, this is some very interesting stuff.
- Then I want to become all productive about it - writing things on my blog, speaking about it in public, maybe even writing a book about it.
This time it was domain-driven design (DDD), command-query responsibility segregation (CQRS) and in particular its architectural and technical aspects. While playing with existing libraries I soon recognized the huge benefits of applying hexagonal architecture and some of the tactical DDD patterns to a (Symfony) codebase.
Packages: the case for clones
Don’t reinvent the wheel
There is this ongoing discussion in the PHP community (and I guess in every software-related community) about reinventing wheels. A refreshing angle in this debate came from an article by Phil Sturgeon pointing to the high number of “duplicate” packages available on Packagist. I agree with Phil:
Sometimes these are carbon copies of other packages, but often they are feature-weak versions of established packages.
It doesn’t make sense to do the same thing over and over again. At least I personally don’t try to make this mistake. If I want to write code that “already exists”, at least I don’t publish it on Packagist.
Decoupling from a service locator
Decoupling from a service locator - shouldn’t that be: don’t use a service locator?
Well, not really, since there are lots of valid use cases for using a service locator. The main use case is for making things lazy-loading (yes, you can also use some kind of proxy mechanism for that, but let’s assume you need something simpler). Say we have this EventDispatcher
class:
class EventDispatcher
{
public function __construct(array $listeners)
{
$this->listeners = $listeners;
}
public function dispatch($event)
{
foreach ($this->listeners[$event] as $listener) {
$listener->notify();
}
}
}
Now it appears that some event listeners are rather expensive to instantiate. And, even though it may never be notified (because it listens to a rare event), in order to register any event listener, we need to instantiate it:
Symfony in Barcelona

I just ate a nice pizza at my hotel room in Barcelona. The funny thing is (at least, to a Dutch guy that is): they wouldn’t be able to give me a pizza before 20:00h. At that time in my home country we have long forgotten our desserts, cleaned the dishes and are starting to think about sleeping (just kidding). Anyway, I got the pizza, it was good and now I’m here to write a little report on the things that happened during the last three days.
Unnecessary contrapositions in the new "Symfony Best Practices"
Of course I’m going to write something about the new Symfony Best Practices book that was written by Fabien Potencier, Ryan Weaver and Javier Eguiluz. It got a lot of negative responses, at least in my Twitter feed, and I think it’s a good idea to read Richard Miller’s post for some suggestions on how to deal with an “early preview release” like this and how we can be a bit more positive about it.
Composer "provide" and dependency inversion
This is a response to Peter Petermann’s article Composer and virtual packages. First, let’s make this totally clear: I don’t want to start an Internet war about this, I’m just pointing out some design issues that may arise from using Composer’s provide
option in your package’s composer.json
file. This means it’s also nothing personal. To Peter: you wrote a very nice article and shed light on an underused feature of Composer. Thank you for that!
Announcements after a year with "A Year With Symfony"
As a follow-up on a previous article I have some announcements to make.
Feedback
A wonderful number of 67 of you have provided very valuable feedback about “A Year With Symfony” - you sure wrote some nice things about my book! Just a small selection of highlights:
Reading “A Year With Symfony” helped to clarify and validate the ideas and structures that I had been developing with my team, along with explaining some of the internals of Symfony that the documentation did not.
Backwards compatible bundle releases
The problem
With a new bundle release you may want to rename services or parameters, make a service private, change some constructor arguments, change the structure of the bundle configuration, etc. Some of these changes may acually be backwards incompatible changes for the users of that bundle. Luckily, the Symfony DependenyInjection component and Config component both provide you with some options to prevent such backwards compatibility (BC) breaks. If you want to know more about backwards compatibility and bundle versioning, please read my previous article on this subject.
Semantic versioning for bundles
A short introduction to semantic versioning
Semantic versioning is an agreement between the user of a package and its maintainer. The maintainer should be able to fix bugs, add new features or completely change the API of the software they provide. At the same time, the user of the package should not be forced to make changes to their own project whenever a package maintainer decides to release a new version.
Exposing resources: from Symfony bundles to packages
Symfony bundles: providing services and exposing resources
When you look at the source code of the Symfony framework, it becomes clear that bundles play two distinct and very different roles: in the first place a bundle is a service container extension: it offers ways to add, modify or remove service definitions and parameters, optionally by means of bundle configuration. This role is represented by the following methods of BundleInterface
:
namespace Symfony\Component\HttpKernel\Bundle;
interface BundleInterface extends ContainerAwareInterface
{
/** Boots the Bundle. */
public function boot();
/** Shutdowns the Bundle. */
public function shutdown();
/** Builds the bundle. */
public function build(ContainerBuilder $container);
/** Returns the container extension that should be implicitly loaded. */
public function getContainerExtension();
...
}
The second role of a bundle is that of a resource provider. When a bundle is registered in the application kernel, it automatically starts to expose all kinds of resources to the application. Think of routing files, controllers, entities, templates, translation files, etc.