### L'Event Sourcing en pratique, ça donne quoi ?

#### Thibaud Dauce

@ThibaudDauce | https://thibaud.dauce.fr

#### Co-fondateur de Quantic Telecom

https://www.quantic-telecom.net

#### Formations Laravel

https://www.formations-laravel.fr

### Qu'est-ce que l'Event Sourcing ?

#### Stocker l'état de l'application comme une succession d'évènements

### 3 concepts importants sur les évènements

### Portefeuille en ligne

#### Que se passe-t-il si je ne suis pas d'accord ?

Compte | Montant
--- | ---
Thibaud | 42,00€
Jane | 1337,00€
John | -123,00€

### Event Sourcing à la rescousse

Date | Compte | Libellé | Changement
--- | --- | --- | ---
20/01/2017 | Thibaud | Remboursement | +20,00€
12/01/2017 | Thibaud | Facture | -20,00€
08/01/2017 | Thibaud | Courses | -58,00€
06/01/2017 | Thibaud | Virement initial | +100,00€

### Avantages

#### Un audit complet des évènements de notre application

#### Les nouvelles fonctionnalités profitent des informations passées

### Inconvénients

#### Impossible d'effectuer des requêtes simplement

#### Plus long et compliqué à mettre en place

### En pratique

### Les évènements

                        <?php

                        class TransactionMade extends Event
                        {
                            private $account;
                            private $label;
                            private $amount;

                            public function __construct($account, $label, $amount)
                            {
                                $this->account = $account;
                                $this->label = $label;
                                $this->amount = $amount;
                            }
                        }

### Stockage des évènements

- NoSQL avec EventStore
- SQL avec une table par évènement
- SQL ou NoSQL (type MongoDB) avec une table unique avec un champ JSON libre pour les données additionnelles
- Sérialisés dans un fichier

### Aggregates

                        <?php

                        class Account extends Aggregate
                        {
                            public static function new($name, $amount)
                            {
                                if ($amount < 0) {
                                    throw new InitialAccountTransactionMustBePositive;
                                }

                                $account = new self;
                                $account->raise(
                                  new TransactionMade($name, 'Virement initial', $amount)
                                );
                            }
                        }

### Aggregates

                        <?php

                        abstract class Aggregate
                        {
                            public function raise(Event $event)
                            {
                                $event->save();
                                $this->apply($event);
                                dispatch($event);
                            }
                        }

### Aggregates

                        <?php

                        class Account extends Aggregate
                        {
                            public function apply(Event $event)
                            {
                                if ($event instanceof TransactionMade) {
                                    if (! isset($this->name)) {
                                        $this->name = $event->getAccount();
                                    }
                                    $this->amount += $event->getAmount();
                                }
                            }
                        }

### Aggregates

                        <?php

                        class Account extends Aggregate
                        {
                            public function pay($label, $amount)
                            {
                                if ($amount > $this->amount) {
                                    throw new NotEnoughMoney;
                                }

                                $this->raise(
                                  new TransactionMade($this->name, $label, -1 * $amount)
                                );
                            }
                        }

### Aggregates

                        <?php

                        abstract class Aggregate
                        {
                            public static function fromEvents($events)
                            {
                                $aggregate = new static;
                                foreach($events as $event) {
                                    $aggregate->apply($event);
                                }

                                return $aggregate;
                            }
                        }

### Read models

                        // Save current amount in SQL database
                        public function onTransactionMade($event)
                        {
                            $account = $this->getAccountByName($event->getAccount());
                            $account->update([
                                'amount' => $account->getAmount() + $event->getAmount(),
                            ]);
                        }

### Read models

                        // Save suspicious accounts in Redis
                        public function onTransactionMade($event)
                        {
                            if ($event->getAmount() > 1000) {
                                Redis::set('suspicious.' . $event->getAccount(), true);
                            }
                        }

### Et en vraie pratique

### En conclusion

###

### Ne faites pas d'Event Sourcing…

### … mais pensez y

@ThibaudDauce | https://thibaud.dauce.fr