PHP & Symfony About PHP and Symfony2 development

Compartmentalization in the PHP community

Posted on by Matthias Noback

The PHP community

I'm a proud member of the PHP community. Recently I've come to realize though that "the PHP community" is a very complicated thing, and in fact, not even one thing.

I consider it part of my "job" to keep track of what's going on in the community and I consider Twitter to be the proper place to look for news from the community, as well as a great place to check in on the pulse of the community. What are people happy about, what are people looking at, who are they trolling? This is all fascinating to me.

It turns out that what's going on is not always so nice. Neutral or even funny tweets get misinterpreted as having some negative tone. When a tweet touches a sore point, people are likely to get very angry about it.

PHP "drama"

Some of these conversations are marked as "PHP drama". As some have said earlier (even though I don't have a reference for it), this doesn't do justice to the people involved in the discussion. If something is important to you and someone else downplays your concerns, then that's not really fair.

Recently my inner drama queen (or actually: drama king) awoke when I saw a conversation going on about firing events. The initial question by Jonathan Reinink was about firing events in a controller. Then Yitzchok Willroth said "Controllers firing events?!". I got what that meant, since he was probably referring to a more domain-oriented approach where indeed you're not supposed to create/fire/dispatch events inside a controller. Finally, Jeffrey Way responded:

Ready? Fight!

When I read this, I was so much tempted to cook up a spicy response... But instead of letting the anger win and getting myself tangled up into this conversation, I started analyzing what was actually going on:

  1. I got mad because what Jeffrey said was such a bad argument that he couldn't be serious about it. Surely, every good advice or initiative can be counter-attacked by a response like this.
  2. Then I thought, he probably isn't serious about this anyway, right? It has to be a joke. Hard to decide though, because I don't actually know Jeffrey in person.
  3. If he is serious, or even somewhat or remotely serious about this, something else must be going on right? I remember some Laravel people saying things like "let them fight over Active record versus Data mapper while we ship valuable software". Is this comment somehow related?

Discussing matters of faith

Looking at myself, thinking these things, I was suddenly reminded of the way that people tend to deal with "wrongness" in discussions about matters of faith. Being raised as a member of the protestant church I was baptised as a child and when I was 20 I did my confessions, explaining publicly what I believed. Then something curious happened: within the same year, I completely lost my faith. I said goodbye to everything I had believed about life, the universe and everything, and started to completely rebuild that.

This obviously came as a big surprise to my parents, who are both theologians. We are not our biggest enemies today, but it's impossible to talk about certain things. In the past we did try to convince each other (I guess we all wanted to agree on the what and why of the world). This never worked, because from the time I was no longer a practising Christian, it seemed that we lived in different worlds. We even appeared to have completely different rules about thinking itself. When one of us brought in some argument, it sounded to the other person like:

  1. It was such a bad argument.
  2. He can't be serious about this.

Finally, I came to the conclusion that indeed, with a different mindset, my parents - of course - couldn't agree with me. What I was saying must have sounded really stupid from their perspective on the world.

Compared to technical discussions

Do you see certain similarities with the discussion about firing events in controllers? To me it's very clear that something like this is going on there as well. Maybe not even in this particular discussion, as well as in many, many other discussions which you read on Twitter.

The way our community is divided often looks like a subdivision based on what people believe. There are Symfonians, Artisans, Drupalistas, etc. There's people who believe that we should all do TDD and there's people who believe that's downright stupid. Some like DDD, some think it's likely to make your application over-engineered. Some do PHP "the right way", some don't.

Having these compartments in our community causes several things:

  • We tend to gather followers and followees who reinforce the way we think about programming.
  • We tend to fight everything that and everyone who doesn't fit within that way of thinking.
  • We tend to blindly follow "thought leaders" who speak the loudest and the most often about the things we find important.

This, again, is not very much unlike what happens within and between subdivisions of a real-world community. A lot of blind following, fighting as well as reinstating previous beliefs.

Conclusion

From this comparison, I draw several conclusions:

  1. It's perfectly fine to gather people around you who think alike, are interested in the same kinds of things. We all do this, it provides some safety and sanity in a crazy and chaotic world. Most groups within the PHP community are no longer fully compartmentalized anyway.
  2. Though starting a fight is always tempting, it doesn't lead to converting someone to your opinion. It's not okay to fight with everyone who doesn't agree with you or your group. It's particularly not okay to fight with someone who seems to have a completely different mindset. Even though they sound stupid to you, they may have a set of experiences that's entirely different from yours. And, you know, they can live a successful life as well, believing those "stupid" things, so you might even learn something useful from them.
  3. Just because a well-known person from the community (guru, hero) says "Don't be afraid to use active record, I'm making big bucks with it!", or "Don't use facades, because, uhm, there be dragons!", doesn't mean you need to follow that advice or blindly parroting them. I don't think any person should be called "thought leader". It sounds to me like blind worshipping. You should never let your thoughts be led by anyone else. You can keep yourself informed on the matter, discuss alternatives with people, but never let someone win the argument just because they are the "leader". Or, as Taylor Otwell puts it:

What about firing events in controllers?

The unanswered question remains: is it okay to fire events in controllers? With my own (current) mindset, habits, experiences, goals, discipline, etc. I'd say: no. And no, the world won't explode, but I don't think we're better of with events being dispatched in a (web) controller. That may never be an excuse to do the other, "right" thing. And if someone on my team is doing it anyway, I'll ask them to find a better solution for it.

What's absolutely crucial to note is that this is my personal opinion. Even though I know that many people share this opinion with me (people who follow me and whom I follow), I know there are different ways of looking at things as well. I don't want to fight over these issues at all. I just want to set the example that I think is worth setting.

I think software development requires an enormous amount of discipline, which we, being humans, don't always have. Because we "fall back" on suboptimal behavior all day, I think that teachers (bloggers, speakers, etc.) always have to aim quite high, to the point where, yes, some will think that we're overdoing things. That way, we can gradually improve the state of (PHP) software.

I encourage you from time to time and always in a respectful manner, to question my logic. If you're unconvinced a particular plan of action I've decided is the wisest, tell me so. But allow me to convince you. And I promise you right here and now, no subject will ever be taboo. Except, of course, the subject that was just under discussion.

— O-Ren-Ishii, Kill Bill, Vol. I

Just kidding of course ;)

Categories: PHP

Tags: community

Comments: Comments

Lean publishing "Principles of Package Design"

Posted on by Matthias Noback

During the great PHP Benelux Conference 2015 edition I published the final version of Principles of Package Design. Let me tell you a little bit about its history and some of the things I had to deal with.

A bit of history

My first book, A Year With Symfony, was released on September 4th, 2013. Just 6 days later, I started working on Principles of PHP Package Design. As it turned out, it was quite hard to keep the process going. There were several months in which I wrote nothing at all. Sometimes I picked up the work, but then I had completely lost my track and tried to get back on it by revising existing chapters over and over again. Meanwhile all kinds of other projects begged for attention as well, including the release of the backend project of the new nos.nl website, the preparations for the Hexagonal architecture training and the birth of our daughter Julia ;)

Finally, I took a couple of weeks to focus completely on the book, and as it turned out, there wasn't really much work left. The final sprint consisted mainly of preparing the book interior for print, designing the cover, and thinking of a good way to release it. The PHP Benelux conference seemed like a good place and time to do this. I felt comfortable enough to do it there, given I am familiar with many of the attendees.

Lean/live publishing

Still, I was quite nervous to actually do this. Even though I did it before, to publish a Leanpub book in real-time is always a bit scary. But I pushed the "Publish" button nonetheless, and everything turned out well. While Leanpub was generating fresh PDF, MOBI and EPUB files, I talked a bit about lean publishing and its up- and downsides.

The main take-aways from this are:

It's great to be able to publish early, and let readers give you feedback. But make some kind of a commitment to finish the book as well. Imagine the early adopters standing in front of you, asking you when you'll finish it and give an honest answer:

Early adopters demanding a finished book, source: https://www.gov.uk/government/news/farewell-reception-for-201213-chevening-scholars

Proof reading

Also, make sure to ask people to read the book before you publish it, and provide you with some feedback. Any feedback is helpful, and also any type of reader: an experienced or an inexperienced programmer, a native English speaker, or a non-native one, etc.

One example of highly useful feedback I got from Peter Bowyer (rephrased):

It seems like you're trying to put two books into one. In the first place there's lots of information about practical PHP package development, working with Git, GitHub, Composer, Packagist, etc. Then there's also lots of information about software design and design principles, which is more theoretical of nature.

This particular comment struck me like lightening and helped me decide to leave out all the PHP-specific things and turn this into a general programming book. I'm really curious how this works out. So far it turns out that people really get a lot of practical advice from it, as well as many things to think about, while they're doing their job.

Also, because it took me about one and a half years to finish this book, its style was not really consistent at first. While re-reading the older parts it turned out that I took certain things for granted, sometimes underestimated, sometimes overestimated the audience, sometimes let myself get away with shortcuts, or obscure explanations. All of these mistakes have now been taken care of, again thanks to proof readers who pointed them out to me.

Print edition

When I published A Year With Symfony, the printed edition was really an after-thought. It turned out that preparing a book for print can be a lot of work. In those days I used Lulu, but it was such a hassle to prepare the PDF for distribution (in particular for sales channels like Amazon), that I decided to not do the same thing for Principles of Package Design. For this book, the printed edition is just as important as the digital one. And everything is better now since I use CreateSpace, which is actually an Amazon product. They offer print-on-demand and proper shipping costs for people all over the world. Anything you upload is manually, yet quickly verified and their in-browser software is just very friendly to use. The royalty percentage is about 40% which is not the best out there, but to me quite reasonable given that there's no further effort required from you after you publish the book.

The print edition is available on the different Amazon websites, e.g. amazon.com, amazon.de and amazon.co.uk

Feedback wanted

If you have read this book, or are reading this book. Please provide me with any feedback that you have. I'm also looking for some feedback that I can add to the book's landing page on leanpub.com, so if you have a nice quote, please send me an email.

Finally, to celebrate the release, you can use the following discount link to buy the book for $19: leanpub.com/principles-of-package-design/c/phpbnl15

Encouragements

Despite the dangers of lean publishing: if you feel the slightest inclination towards writing your own book, I advise you to do so. Even as an experiment, just like an experimental open source library, you can just start working on it, and later decide whether or not it's something worth finishing. The experience itself is useful, and sharing your knowledge of a particular subject is useful for more people than you may imagine. I especially like to recommend the Leanpub platform since it's very easy for technical people to get up and running with it.

Categories: PHP Book

Tags: design principles reuse Principles of PHP Package Design slides

Comments: Comments

Collecting events and the event dispatching command bus

Posted on by Matthias Noback

It was quite a ride so far. We have seen commands, command buses, events and event buses. We distilled some more knowledge about them while formulating answers to some interesting questions from readers.

Why you should not dispatch events while handling a command

In a previous post we discussed a sample event (the UserSignedUp event):

class UserSignedUp implements Event
{
    public function name()
    {
        return 'user_signed_up';
    }

    public function __construct($userId)
    {
        $this->userId = $userId;
    }

    public function userId()
    {
        return $this->userId;
    }
}

An instance of such an event can be handed over to the event bus. It will look for any number of event handlers that wants to be notified about the event. In the case of the UserSignedUp event, one of the interested event handlers is the SendWelcomeMailWhenUserSignedUp handler:

class SendWelcomeMailWhenUserSignedUp implements EventHandler
{
    ...

    public function handle(Event $event)
    {
        $user = $this->userRepository->getById($event->userId());

        $this->userMailer->sendWelcomeMailTo($user);
    }
}

The UserSignedUp event occurs whenever a SignUpUser command has been handled. We might be tempted to inject the event bus into the command handler and let it handle the event immediately:

class SignUpHandler
{
    public function __construct(EventBus $eventBus, ...)
    {
        $this->eventBus = $eventBus;
        ...
    }

    public function handle($command)
    {
        ...

        $this->userRepository->add($user);

        $event = new UserSignedUp($user->id());

        $this->eventBus->handle($event);
    }
}

We should not forget however that this command is handled within a database transaction created by one of the command buses. And as I already mentioned, we don't want the event to be handled within the same transaction, since it could endanger the success of that transaction. Also, when the transaction fails in the end, we might end up handling an event for entities whose actual state is insecure.

So instead, we should merely collect events while handling the command and only hand them over to the event bus when the transaction was committed, i.e. when we know that the command has been successfully and completely handled.

Event providers

Of course, SimpleBus would not be complete without an out-of-the-box implementation of this kind of delayed event handling. The connecting concept between events and the command bus is the ProvidesEvents interface, which is part of the SimpleBus/EventBus package.

namespace SimpleBus\Event\Provider;

use SimpleBus\Event\Event;

interface ProvidesEvents
{
    /**
     * @return Event[]
     */
    public function releaseEvents();
}

You can provide a simple implementation for such an EventProvider by defining a class for it, which uses the trait EventProviderCapabilities. This adds the ability to collect events (using the raise() method) and release them later, using the releaseEvents() method:

use SimpleBus\Event\Provider\EventProviderCapabilities;

class EventProvider implements ProvidesEvents
{
    use EventProviderCapabilities;
}

We could inject this EventProvider into any command handler and use the raise() method of the EventProvider to raise new events (which will not be handled right-away, but only stored in-memory):

class SignUpHandler
{
    public function __construct(EventProvider $eventProvider, ...)
    {
        $this->eventProvider = $eventProvider;
        ...
    }

    public function handle($command)
    {
        ...

        $event = new UserSignedUp($user->id());

        $this->eventProvider->raise($event);
    }
}

Now, at what point could we safely release the events collected by the EventProvider and hand those events over to the event bus? The answer is: in yet another command bus! We simply wrap the new event-aware command bus which starts and commits the database transaction. Only then can we be sure that the transaction was successful and we can proceed to safely dispatch the collected events.

Since SimpleBus/CommandBus and SimpleBus/EventBus are stand-alone packages, I introduced a bridge package between the two, SimpleBus/CommandEventBridge. It contains this class, which is a CommandBus, but asks the event provider to release its events, and lets the EventBus instance handle them:

class DispatchesEvents implements CommandBus
{
    use RemembersNext;

    private $eventProvider;
    private $eventBus;

    public function __construct(ProvidesEvents $eventProvider, EventBus $eventBus)
    {
        $this->eventBus = $eventBus;
        $this->eventProvider = $eventProvider;
    }

    public function handle(Command $command)
    {
        $this->next($command);

        foreach ($this->eventProvider->releaseEvents() as $event) {
            $this->eventBus->handle($event);
        }
    }
}

In a diagram this would look something like this (from left to right it shows you the passage of time):

Diagram

Conclusion

After reading this series about command and event buses, you can start using commands to interact with your application and events to act upon the things that happened. Because both the command and the event bus are highly extensible you have many options for introducing more advanced behavior. You could think of:

  • Collecting events in an store
  • Handling commands asynchronously
  • The same for events
  • ...

For now we are more or less done talking about command and event buses. If you have questions, just write a comment below this post. I'm currently working on version 2.0 of the SimpleBus packages. You can at least expect a new post when I'm done, to announce the changes with respect to 1.0. To give you a sneak peek:

  • Code for command and event buses will be generalized and bundled in the MessageBus package.
  • Instead of wrapping message buses using composition, this new package introduces the concept of message bus middlewares, offering greater flexibility and cleaner code for your own specialized message bus features.

Categories: PHP

Tags: hexagonal architecture commands command bus events event bus SimpleBus

Comments: Comments