add static builder

This commit is contained in:
Thibaud Dauce
2026-02-18 17:23:24 +01:00
parent e60f150611
commit ab1fa58b8b
907 changed files with 332529 additions and 12 deletions

View File

@@ -0,0 +1,290 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>L'Event Sourcing en pratique, ça donne quoi ?</title>
<link rel="stylesheet" href="css/reveal.css">
<link rel="stylesheet" href="css/theme/solarized.css">
<link rel="stylesheet" href="css/font-awesome/css/font-awesome.min.css">
<!-- Theme used for syntax highlighting of code -->
<link rel="stylesheet" href="lib/css/zenburn.css">
<!-- Printing and PDF exports -->
<script>
var link = document.createElement( 'link' );
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = window.location.search.match( /print-pdf/gi ) ? 'css/print/pdf.css' : 'css/print/paper.css';
document.getElementsByTagName( 'head' )[0].appendChild( link );
</script>
<style media="screen">
div.flex-icons {
width: 60%;
margin: auto;
display: flex;
justify-content: space-around;
}
.flex-icons .fa {
font-size: 80px;
}
</style>
</head>
<body>
<div class="reveal">
<div class="slides">
<section>
<h3>L'Event Sourcing en pratique, ça donne quoi ?</h3>
<h4>Thibaud Dauce</h4>
<small><a href="https://twitter.com/ThibaudDauce">@ThibaudDauce</a> | <a href="https://thibaud.dauce.fr">https://thibaud.dauce.fr</a></small>
</section>
<section>
<img src="images/quantic-telecom.png" alt="Quantic Telecom" />
<h4>Co-fondateur de Quantic Telecom</h4>
<small><a href="https://www.quantic-telecom.net">https://www.quantic-telecom.net</a></small>
<hr>
<img src="images/laravel.png" alt="Formations Laravel" />
<h4>Formations Laravel</h4>
<small><a href="https://www.formations-laravel.fr">https://www.formations-laravel.fr</a></small>
</section>
<section>
<h3>Qu'est-ce que l'Event Sourcing ?</h3>
<h4 class="fragment">Stocker l'état de l'application comme une succession d'évènements</h4>
</section>
<section>
<h3>3 concepts importants sur les évènements</h3>
<div class="flex-icons">
<i class="fa fa-database fragment" aria-hidden="true"></i>
<i class="fa fa-clock-o fragment" aria-hidden="true"></i>
<i class="fa fa-lock fragment" aria-hidden="true"></i>
</div>
</section>
<section>
<h3>Portefeuille en ligne</h3>
<h4 class="fragment" data-fragment-index="2">Que se passe-t-il si je ne suis pas d'accord ?</h4>
<div class="fragment" data-fragment-index="1">
<table style="font-size: 35px">
<tr><th>Compte</th><th>Montant</th></tr>
<tr><td>Thibaud</td><td style="text-align: right">42,00€</td></tr>
<tr><td>Jane</td><td style="text-align: right">1337,00€</td></tr>
<tr><td>John</td><td style="text-align: right">-123,00€</td></tr>
</table>
</div>
</section>
<section>
<h3>Event Sourcing à la rescousse</h3>
<table>
<tr><th>Date</th><th>Compte</th><th>Libellé</th><th>Changement</th></tr>
<tr><td>20/01/2017</td><td>Thibaud</td><td>Remboursement</td><td style="text-align: right"><strong>+</strong>20,00€</td></tr>
<tr><td>12/01/2017</td><td>Thibaud</td><td>Facture</td><td style="text-align: right"><strong>-</strong>20,00€</td></tr>
<tr><td>08/01/2017</td><td>Thibaud</td><td>Courses</td><td style="text-align: right"><strong>-</strong>58,00€</td></tr>
<tr><td>06/01/2017</td><td>Thibaud</td><td>Virement initial</td><td style="text-align: right"><strong>+</strong>100,00€</td></tr>
</table>
</section>
<section>
<h3>Avantages</h3>
<h4>Un audit complet des évènements de notre application</h4>
<h4>Les nouvelles fonctionnalités profitent des informations passées</h4>
</section>
<section>
<h3>Inconvénients</h3>
<h4>Impossible d'effectuer des requêtes simplement</h4>
<h4>Plus long et compliqué à mettre en place</h4>
</section>
<section>
<h3>En pratique</h3>
</section>
<section>
<h3>Les évènements</h3>
<pre class="fragment"><code data-trim data-noescape>
&#x3C;?php
class TransactionMade extends Event
{
private $account;
private $label;
private $amount;
public function __construct($account, $label, $amount)
{
$this-&#x3E;account = $account;
$this-&#x3E;label = $label;
$this-&#x3E;amount = $amount;
}
}
</code></pre>
</section>
<section>
<h3>Stockage des évènements</h3>
<ul>
<li>NoSQL avec <a href="https://geteventstore.com/">EventStore</a></li>
<li>SQL avec une table par évènement</li>
<li>SQL ou NoSQL (type MongoDB) avec une table unique avec un champ JSON libre pour les données additionnelles</li>
<li>Sérialisés dans un fichier</li>
</ul>
</section>
<section>
<h3>Aggregates</h3>
<pre class="fragment"><code data-trim data-noescape>
&#x3C;?php
class Account extends Aggregate
{
public static function new($name, $amount)
{
if ($amount < 0) {
throw new InitialAccountTransactionMustBePositive;
}
$account = new self;
$account-&#x3E;raise(
new TransactionMade($name, 'Virement initial', $amount)
);
}
}
</code></pre>
</section>
<section>
<h3>Aggregates</h3>
<pre><code data-trim data-noescape>
&#x3C;?php
abstract class Aggregate
{
public function raise(Event $event)
{
$event->save();
$this->apply($event);
dispatch($event);
}
}
</code></pre>
</section>
<section>
<h3>Aggregates</h3>
<pre><code data-trim data-noescape>
&#x3C;?php
class Account extends Aggregate
{
public function apply(Event $event)
{
if ($event instanceof TransactionMade) {
if (! isset($this-&#x3E;name)) {
$this-&#x3E;name = $event-&#x3E;getAccount();
}
$this-&#x3E;amount += $event-&#x3E;getAmount();
}
}
}
</code></pre>
</section>
<section>
<h3>Aggregates</h3>
<pre><code data-trim data-noescape>
&#x3C;?php
class Account extends Aggregate
{
public function pay($label, $amount)
{
if ($amount > $this-&#x3E;amount) {
throw new NotEnoughMoney;
}
$this-&#x3E;raise(
new TransactionMade($this-&#x3E;name, $label, -1 * $amount)
);
}
}
</code></pre>
</section>
<section>
<h3>Aggregates</h3>
<pre><code data-trim data-noescape>
&#x3C;?php
abstract class Aggregate
{
public static function fromEvents($events)
{
$aggregate = new static;
foreach($events as $event) {
$aggregate->apply($event);
}
return $aggregate;
}
}
</code></pre>
</section>
<section>
<h3>Read models</h3>
<pre class="fragment"><code data-trim data-noescape>
// Save current amount in SQL database
public function onTransactionMade($event)
{
$account = $this->getAccountByName($event->getAccount());
$account->update([
'amount' => $account->getAmount() + $event->getAmount(),
]);
}
</code></pre>
</section>
<section>
<h3>Read models</h3>
<pre><code data-trim data-noescape>
// Save suspicious accounts in Redis
public function onTransactionMade($event)
{
if ($event->getAmount() > 1000) {
Redis::set('suspicious.' . $event->getAccount(), true);
}
}
</code></pre>
</section>
<section>
<h3>Et en vraie pratique</h3>
</section>
<section>
<h3>En conclusion</h3>
<div class="fragment">
<h3 class="flex-icons">
<i class="fa fa-exclamation-triangle" aria-hidden="true"></i>
</h3>
<h3>Ne faites pas d'Event Sourcing…</h3>
</div>
</section>
<section>
<h3>… mais pensez y</h3>
<small><a href="https://twitter.com/ThibaudDauce">@ThibaudDauce</a> | <a href="https://thibaud.dauce.fr">https://thibaud.dauce.fr</a></small>
</section>
</div>
</div>
<script src="lib/js/head.min.js"></script>
<script src="js/reveal.js"></script>
<script>
// More info https://github.com/hakimel/reveal.js#configuration
Reveal.initialize({
history: true,
// More info https://github.com/hakimel/reveal.js#dependencies
dependencies: [
{ src: 'plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } }
]
});
</script>
</body>
</html>