Symfony-docs: [Workflow] How workflows makes sense with DDD

Created on 29 Dec 2018  路  4Comments  路  Source: symfony/symfony-docs

More than a handful of times have people asked me how to use the workflow component when doing domain driven design. Im no expert but I think this should be documented and this is how I imagine one solve the problem.

In DDD the models should know everything about themselves. Ie the BlogPost entity should have the information about what the places and transitions are.

namespace App\Entity;

class BlogPost {
  // getters and setters

  public static function getWorkflowDefinition()
  {
        $definitionBuilder = new DefinitionBuilder();
        $definition = $definitionBuilder->addPlaces(['draft', 'published', 'trashed'])
            ->addTransition(new Transition('publish', 'draft', 'published'))
            ->addTransition(new Transition('trash', 'published', 'trashed'))
            ->build();
        return $definition;
  }
}

Then we create a generic factory like:

namespace App\Workflow;

use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Workflow\MarkingStore\MultipleStateMarkingStore;
use Symfony\Component\Workflow\Validator\WorkflowValidator;
use Symfony\Component\Workflow\Workflow;

class WorkflowFactory
{
    private $eventDispatcher;

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

    public function create(callable $fetcher, $name)
    {
        $definition = $fetcher();
        (new WorkflowValidator())->validate($definition, $name);
        $marking = new MultipleStateMarkingStore('state');

        return new Workflow($definition, $marking, $this->eventDispatcher, $name);
    }
}

Now we can register workflow as services like:

  App\Workflow\WorkflowFactory:
    arguments: ['@event_dispatcher']

  workflow.blog_post:
    class: Symfony\Component\Workflow\Workflow
    factory: ['@App\Workflow\WorkflowFactory', 'create']
    arguments: [['App\Entity\BlogPost', 'getWorkflowDefinition'], 'blog_post']

  # Other workflows can use the same factory
  workflow.acme:
    class: Symfony\Component\Workflow\Workflow
    factory: ['@App\Workflow\WorkflowFactory', 'create']
    arguments: [['App\Entity\Acme', 'getWorkflowDefinition'], 'acme']
Workflow

Most helpful comment

All 4 comments

This sounds like a cool cookbook entry 馃憤

@OskarStark I'm afraid we can't add something like this to docs. First, because it talks about a particular architecture (DDD) that we never show or explain in the docs. Second, because none of the doc maintainers know DDD, so this doc would never be maintained or fixed.

I'm really sorry, but I must close this without merging because of the given reasons. Thanks for understanding!

Thank you for the feedback Javier.

I think the correct action now is to write a blog post about this. I'll try to do it before the end of the month.

馃憤

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ManInTheBox picture ManInTheBox  路  4Comments

javiereguiluz picture javiereguiluz  路  3Comments

weaverryan picture weaverryan  路  3Comments

anush picture anush  路  5Comments

x8core picture x8core  路  4Comments