Firing Domain Events in the __constructor

After my post about “Good ORMs do not call __construct a.k.a. where to fire my Domain Events”, nice discussions (and trolling) are happening in the Barcelona Engineering Slack Channel. Thanks to everyone for the feedback, ideas and concerns. You are more than welcome! The main concerns are:

  1. How do I fetch an Entity from ElasticSearch, using new and without firing the Event?
  2. How do I create stubs on the Entity that is firing the Domain Event?
  3. What are pros and cons of firing the Domain Event in the __constructor or in the named constructor?

So, I’ll take the original code as a starting point, and I’ll suggest different strategies to answer those questions. 

If you fetch an Entity directly hitting an ElasticSearch server and building such Entity from a JSON document, there is a (simple) option:

Extract Method + Sub Class + Noop

class Video extends AggregateRoot
{
    private $id;
    private $title;
    private $url;
    private $courseId;

    public function __construct(VideoId $id, VideoTitle $title, VideoUrl $url, CourseId $courseId)
    {
        $this->id       = $id;
        $this->title    = $title;
        $this->url      = $url;
        $this->courseId = $courseId;

        $this->raiseEvent($this);
    }

    protected function raiseEvent($video)
    {
        $this->raise(
            new VideoCreatedDomainEvent(
                $id,
                [
                    'title' => $title->value(),
                    'url' => $url->value(),
                    'courseId' => $courseId->value(),
                ]
            )
        );
    }

    public static function create(VideoId $id, VideoTitle $title, VideoUrl $url, CourseId $courseId)
    {
        return new self($id, $title, $url, $courseId);
    }

//...

class ElasticVideo extends Video
{
    protected function raiseEvent($video)
    {
        // noop
    }
}

Now, your ElasticRepository does fetch ElasticVideos, using new, without firing the Domain Event. Everything is not fantastic, here, we need to remove the final keyword from the class declaration because we need to extend it to do the trick. If you consider this approach, it is more or less what Doctrine is doing when you generate Doctrine Proxies. When you get a Entity from Doctrine ask for its classname ;) The trick, also works for testing. Another alternative is using Reflection.

“What are pros and cons of firing the Domain Event in the __constructor or in the named constructor?”

To clarify, I’m talking about a subtle detail. The code from the speakers is good enough to use it in any project you want.

In my honest opinion, I prefer to fire Domain Events as close as possible of the fact that fired it. That’s why I prefer to fire it in the constructor. Specially if the constructor is public. I don’t want to have two ways of building an Entity (named and default constructor) and one if firing the event and the other not. It sounds strange to me.

If you make the default constructor private, I’m happy. However, firing the event is a piece of code that is going to be duplicated in all the named constructors, so I prefer to removed such duplication and put it into the default constructor.

As a comparison, I don’t like to fire Domain Events in the Application Services. I prefer to fire them in the Entities. Firing in Application Services or Domain Services when you can fire them in the Entities can cause some issues. Some client code could perform the same operation in the Entity without firing the Event. For me, this different behaviour sounds again strange.

For me, the cons are not using final and having to change the visibility of some methods.

Hope it helps.