Skip to content

Instantly share code, notes, and snippets.

@guiwoda
Last active August 29, 2015 14:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save guiwoda/976cb1935915867757cf to your computer and use it in GitHub Desktop.
Save guiwoda/976cb1935915867757cf to your computer and use it in GitHub Desktop.
Agregate roots and events

Agregate roots and events

Given an aggregate Project, one Team (with many Devs) and one Source, if I $project->releaseEvents(), should the Project aggregate all events from all its related entities?

Example code:

Entities

<?php namespace App\Entities;

class Project 
{
    /** @see https://gist.github.com/rosstuck/9667242 */
    use \EventGenerator;
    
    /**
     * @type string
     */
    private $name;
    
    /** @oneToOne */
    private $team;
    
    /** @oneToOne */
    private $source;
    
    public function __construct($name, Team $team, Source $source)
    {
        $this->name = $name;
        $this->team = $team;
        $this->source = $source;
    }
    
    /*
     * On aggregate case ("Alternative 1" below) we would need to merge
     * the events here instead of in the service layer
     */
     public function releaseAggregateEvents()
     {
        return array_merge(
            $this->releaseEvents(),
            $this->source->releaseEvents(),
            $this->team->releaseEvents()
        );
     }
}

class Team 
{
    use \EventGenerator;
    
    /** @oneToMany */
    private $devs;
    
    public function __construct()
    {
        $this->devs = new ArrayCollection;
    }
}

class Source 
{
    use \EventGenerator;
    
    private $path;
    
    public function __construct($path)
    {
        $this->path = $path;
    }
}

class Dev {}

Application Service layer

<?php namespace App\Services;

class ProjectService
{
    /** @type Dispatcher */
    private $dispatcher;
    
    public function __construct(Dispatcher $dispatcher)
    {
        $this->dispatcher = $dispatcher;
    }
    
    public function startNew($name, $sourcePath)
    {
        $team = new Team;
        $source = new Source($sourcePath);
        
        $project = new \App\Entities\Project(
            $name,
            $team,
            $source
        );
        
        // ... persistance logic, maybe?
        
        // Alternative 1
        $this->dispatcher->fire(
            $project->releaseAggregateEvents()
        );
        
        // Alternative 2 (merge all events here)
        $this->dispatcher->fire(
            array_merge(
                $project->releaseEvents(),
                $team->releaseEvents(),
                $source->releaseEvents()
            )
        );
        
        return $project;
    }
}

I feel that merging in the aggregate root makes for more reusable code, but I'm not 100% sure about it.

Opinions, anyone? :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment