Slide 1

Slide 1 text

Simplify your application with a command bus SymfonyCon Cluj 2017

Slide 2

Slide 2 text

Romaric Drigon Software engineer @ netinfluence, Switzerland

Slide 3

Slide 3 text

What we want to avoid

Slide 4

Slide 4 text

How our code should feel like

Slide 5

Slide 5 text

What is a command bus? A command... "...an object is used to encapsulate all information needed to perform an action..." ...and a bus "...a communication system that transfers data between components..."

Slide 6

Slide 6 text

To wrap up...

Slide 7

Slide 7 text

A use case A Finder-like application in javascript On each file, you can operate commands: create a folder, rename a file, remove... Requests are sent from the JS application to a Symfony backend

Slide 8

Slide 8 text

Setting up a command bus We will use Tactician (https://tactician.thephpleague.com/) Developed by Ross Tuck A Symfony bundle is available Notable alternatives include SimpleBus, by Matthias Noback

Slide 9

Slide 9 text

A Command item = $item; } public function getItem(): Item { return $this->item; } }

Slide 10

Slide 10 text

The corresponding handler getItem(); $this->entityManager->remove($item); $this->entityManager->flush(); // We can find a better way return $item->getUuid(); // It can return a result! } }

Slide 11

Slide 11 text

Declaring the handler Declared as a Symfony service: Note: handlers now support autowiring, check out Tactician bundle documentation app.remove_handler: class: AppBundle\Handler\RemoveHandler tags: - { name: tactician.handler, command: AppBundle\Model\Command\RemoveComman arguments: - '@doctrine.orm.default_entity_manager'

Slide 12

Slide 12 text

Sending the command to the bus From the Symfony API controller: Great, Romaric... but what is the interest? /** * @ParamConverter("item") */ public function apiAction(Item $item) { $command = new RemoveCommand($item); $uuid = $this->get('tactician.commandbus')->handle($command); return new JsonResponse(['uuid' => $uuid]); }

Slide 13

Slide 13 text

It scales well!

Slide 14

Slide 14 text

The application is getting complex... After one month, we had 25 commands and handlers, totaling 3500 lines of code.

Slide 15

Slide 15 text

Adding middlewares Huge interest: middlewares help to simplify common tasks.

Slide 16

Slide 16 text

Middleware examples Doctrine (https://tactician.thephpleague.com/plugins/doctrine/) : wraps handlers in a DB transaction Logger (https://tactician.thephpleague.com/plugins/logger/) : can log everything to Monolog (audit!) Validation (shipped with Symfony Tactician bundle) Security, authorization ...

Slide 17

Slide 17 text

Going further Testing: handlers and middlewares are easier to unit test Commands could be sent to a message queue (RabbitMQ...) instead of staying in memory, or scheduled to be executed later (delayed task...).

Slide 18

Slide 18 text

romaric@netinfluence.ch http://blog.netinfluence.ch