diff --git a/hello.css b/hello.css
index 31567f06867c35f1101c881ccec9be9712074afe..d221643df06a134fc19ece1f7c9cb9e25e703280 100644
--- a/hello.css
+++ b/hello.css
@@ -11,6 +11,9 @@ code {
 
 .reveal {
     color: white;
+    background-image: url(./sflive_paris2018_big_transp.png);
+    background-repeat: no-repeat;
+    background-position: top right;
 }
 
 @font-face {
diff --git a/index.md b/index.md
index 5a2c1102e8a196dba542aa373a896c6cacebc07b..aee4386fa8f52300553093f2fd609ea9c9227d61 100644
--- a/index.md
+++ b/index.md
@@ -24,8 +24,6 @@ Backend developer<br />
 </div>
 
 ---
-### Nous parlons de Doctrine ORM
-
 <img src="./doctrine.svg" />
 
 - Conçu par **Benjamin Eberlei**
@@ -41,7 +39,7 @@ Notes: Juste pour dire que nous n'avons rien à voir avec la team de Doctrine et
 ## Vous avez dit entité ?
 
 ```php
-class TypicalArticle
+class Article
 {
     private $id;
     private $content;
@@ -73,12 +71,6 @@ Notes:
 - Aucune logique (pas de tests nécessaires)
 - Pas de setter pour id, il est setté par Doctrine après la persistence
 
-
----
-
-<div class="tweet" data-src="https://twitter.com/Ocramius/status/975399920202080256"></div>
-
-
 ---
 ## ️❤️ Domain Driven Design ❤️
 
@@ -94,7 +86,7 @@ Notes:
 ## Doctrine n'a pas besoin de setters
 
 ```php
-class NotThatTypicalArticle
+class Article
 {
     private $id;
     private $content;
@@ -137,12 +129,12 @@ class Article
         $this->content = $content;
     }
 
-    public function getId()
+    public function getId(): int
     {
         return $this->id;
     }
 
-    public function getContent()
+    public function getContent(): string
     {
         return $this->content;
     }
@@ -156,6 +148,19 @@ Note:
   Doctrine, Doctrine utilise de la réflection ou de la désérialisation pour
 hydrater les entités.
 
+---
+## Les UUID
+
+- Universally unique
+- Indevinables
+- Ne nécessitent pas de base de données
+- `ramsey/uuid` à la rescousse
+
+Notes:
+- Idéalement, prendre une clé naturelle.
+- Doctrine a un type `guid` qui correspond au type `uuid` dans Postgres,
+  jetez-y un oeil.
+
 ---
 ## Les value objects
 
@@ -163,7 +168,6 @@ hydrater les entités.
 class ArticleContent
 {
     private $content;
-    private $lastModification;
 
     public function __construct(string $content)
     {
@@ -171,58 +175,74 @@ class ArticleContent
             throw new ArticleHasNoContent();
         }
         $this->content = $content;
-        $this->lastModification = new \DatetimeImmutable();
     }
 }
 ```
 
-Instanciation:
-```php
-new NiceArticle(new ArticleContent('This is a very short but nice article'));
-```
-
 Note:
 - Déportation de la validation dans les value objects
 - Début d'arborescence
 - Doctrine Embeddables
 - Custom types
 
+---
+## Instanciation avec des value object
+
+Instanciation:
+```php
+use App\Domain\Article\Article;
+use App\Domain\Article\ArticleContent;
+use App\Domain\Article\ArticleTitle;
+
+new Article(
+  new ArticleTitle('my title'),
+  new ArticleContent('This is a very short but nice article'),
+  new \DateTimeImmutable(),
+);
+```
+
+Notes:
+- ça peut vite devenir très pénible
+
 ---
 ## Les constructeurs nommés
 
 ```php
-class BetterArticle
+class Article
 {
-    public static function createFromNative(string $content)
+    public static function createFromNative(string $title, string $content): self
     {
-        return new self(new ArticleContent($content));
+        return new self(
+          new ArticleTitle($title),
+          new ArticleContent($content),
+          new \DateTimeImmutable()
+        );
     }
 }
 ```
 
-Instanciation:
-```php
-BetterArticle::createFromNative('This is a very short but nice article');
-```
-
 Note:
 - On peut faire plusieurs constructeurs nommés
 - On peut passer le constructeur en privé pour encourager l'utilisation des
   constructeurs nommés.
 
+---
+## Persister des VO avec Doctrine
+
+- les custom types
+- les embeddables
+
 ---
 ## Les custom types
 
 ```php
-class ArticleId extends Uuid { }
-```
+use Doctrine\DBAL\Types\Type;
 
-```php
-final class ArticleIdType extends Type
+final class ArticleContentType extends Type
 {
-    public function convertToPHPValue($value, AbstractPlatform $platform): ArticleId
+    public function convertToPHPValue($value, AbstractPlatform $platform): ArticleContent
     {
-        return new ArticleId($value);
+        return new ArticleContent($value);
     }
 
     public function convertToDatabaseValue($value, AbstractPlatform $platform): string
@@ -232,7 +252,7 @@ final class ArticleIdType extends Type
 
     public function getName()
     {
-        return 'article_id';
+        return 'article_content';
     }
 }
 ```
@@ -242,7 +262,7 @@ final class ArticleIdType extends Type
 doctrine:
     dbal:
         types:
-            article_id:  App\Infrastructure\Persistence\ArticleIdType
+            article_content:  App\Infrastructure\Persistence\ArticleContentType
 ```
 
 Note:
@@ -250,12 +270,6 @@ Note:
   l'hydratation. Si ça crashe, c'est qu'il manque des migrations.
 - La méthode `getName()` fait doublon avec le nom utilisé lors de
   l'enregistrement du type dans le registre de type, et disparaître dès Doctrine 3
-- `ArticleId` devrait être une clé naturelle ou un UUID, le principal c'est de
-  pas avoir besoin de demander à la DB de le calculer, ça évite des attaques
-pour cause d'ID devinables, et ça évite d'exposer le nombre d'entités présentes
-dans une table. Ça évite aussi des collisions lorsque vous migrez des données
-d'une base vers une autre, et que la nouvelle base peut elle aussi être
-alimentée directement.
 
 ---
 ## Les embeddables
@@ -263,7 +277,7 @@ alimentée directement.
 ```php
 use Doctrine\ORM\Annotation as ORM;
 
-class NiceArticle
+class Article
 {
     private $uuid;
 
@@ -301,7 +315,7 @@ Note:
 ```php
 use Doctrine\ORM\Annotation as ORM;
 
-class NiceArticle
+class Article
 {
     private $uuid;
 
@@ -349,7 +363,7 @@ class ArticleRepository extends ServiceEntityRepository
 ## Les repositories
 
 ```php
-final class DoctrineArticleRepository implements ArticleRepository, ServiceEntityRepositoryInterface
+final class DoctrineArticleRepository implements ArticleRepositoryInterface, ServiceEntityRepositoryInterface
 {
     private $entityManager;
 
@@ -358,16 +372,7 @@ final class DoctrineArticleRepository implements ArticleRepository, ServiceEntit
         $this->entityManager = $registry->getManagerForClass(Article::class);
     }
 
-    public function latestArticles(int $size): iterable
-    {
-        $this->entityManager->createQueryBuilder()
-          ->select('a.*')
-          ->from(Article::class)
-          ->orderBy('a.createdAt', 'DESC')
-          ->setMaxResults($size)
-          ->getQuery()
-          ->getResults();
-    }
+    // your methods…
 }
 ```
 
@@ -392,13 +397,29 @@ coup… slide suivant
 $repository = $entityManager->getRepository(Article::class);
 ```
 
+---
+## Les repositories, ça peut grossir
+
+```php
+interface ArticleRepositoryInterface
+{
+    public function latestArticles(int size): iterable;
+    public function mostReadArticles(int size): iterable;
+    public function mostCommentedArticles(int size): iterable;
+    public function byTopic(ArticleTopic $topic): iterable;
+    public function findRelated(Article $article): iterable;
+
+    // more and more methods…
+}
+```
+
 ---
 ## Les Query functions
 
 Quand les repositories ne respectent pas l'ISP
 
 ```php
-final class DoctrineGetLatestArticles implements GetLatestArticles
+final class DoctrineGetLatestArticles implements GetLatestArticlesInterface
 {
     public function __construct(EntityManagerInterface $entityManager)
     {
@@ -427,15 +448,16 @@ Note:
 
 ```yaml
 services:
-    App\Domain\Article\GetLatestArticles: '@App\Infrastructure\Article\DoctrineGetLatestArticles'
-
-    App\Infrastructure\Article\DoctrineGetLatestArticles:
-        arguments:
-            $entityManager: '@doctrine.orm.default_entity_manager'
+    App\Domain\Article\GetLatestArticlesInterface:
+        '@App\Infrastructure\Article\DoctrineGetLatestArticles'
 ```
 
+Note:
+- Inutile si il n'y a qu'une seule implémentation et que la feature de
+  discovery est configurée sur un namespace commun.
+
 ---
-## À quoi servent les collections ?
+## Et les collections ?
 
 - Elles permettent à Doctrine de repérer les changements
 - Elles permettent à Doctrine de faire du lazy-loading
@@ -446,7 +468,7 @@ services:
 - Utilisez le type `iterable` compatible avec `Collection` et `array`
 
 ```php
-class FarBetterArticle
+class Article
 {
     private $comments;
 
@@ -463,13 +485,19 @@ class FarBetterArticle
 ```
 
 ---
-## Evitez les One-To-Many
+## Éviter le mapping One-To-Many
 
+- Permet d'éviter des collections inutiles
 - Leur utilisation est très rare
 - Elles ont un impact important sur les performances
 
+Note:
+- Ne pas faire de relations par réflexe, surtout bidirectionnelles
+- L'utilisation est rare, en vrai on veut souvent filtrer ou paginer, faut
+  faire ça en SQL
+
 ---
-## Faire une jointure avec une relation uni-directionnelle
+#### Faire une jointure avec une relation uni-directionnelle
 
 Récupérer tous les articles dont les commentaires contiennent Doctrine **sans les commentaires**.
 ```php
@@ -492,7 +520,24 @@ Note:
   des objets de la classe jointe.
 
 ---
-## Choisir la bonne API pour interroger la base de données
+# Doctrine impose peu de choses
+
+- `final` possible pour les méthodes en version 3
+- `__clone` & `__wakeup` implémentables librement en version 3
+
+---
+
+<div class="tweet" data-src="https://twitter.com/Ocramius/status/975399920202080256"></div>
+
+
+---
+<!-- .slide: data-background="./iwantmore.gif" -->
+
+---
+# Protips
+
+---
+### Quelle API pour interroger la base de données?
 
 <table>
   <tr>
@@ -521,9 +566,6 @@ Note:
 - Si vous n'avez pas besoin de faire des requêtes dynamiques, vous pouvez vous
   passer du Query Builder.
 
----
-<!-- .slide: data-background="./iwantmore.gif" -->
-
 ---
 ## Result Set Mapping
 
@@ -557,10 +599,7 @@ $comments = $query->getResult();
 SQL + Objets
 
 ---
-# Protips
-
----
-## Les dépendances circulaires entre paquets
+### Les dépendances circulaires entre paquets
 
 Problème :
 
@@ -582,13 +621,6 @@ doctrine:
 ---
 # What's next
 
----
-## `__clone` & `__wakeup`
-
-Ces deux méthodes sont utilisées par Doctrine 2
-
-Mais pas par Doctrine 3
-
 ---
 # Support de MariaDB dans Doctrine&nbsp;3
 
diff --git a/sflive_paris2018_big_transp.png b/sflive_paris2018_big_transp.png
new file mode 100644
index 0000000000000000000000000000000000000000..272d410697dc2834136509760d216eb382a6d28a
Binary files /dev/null and b/sflive_paris2018_big_transp.png differ
diff --git a/talk.md b/talk.md
new file mode 100644
index 0000000000000000000000000000000000000000..8271ff13b03d3a31aa6c06271d9a59e0654c2c34
--- /dev/null
+++ b/talk.md
@@ -0,0 +1,173 @@
+Bonsoir, bonsoir,
+je me présente, je suis Grégoire Paris, Software Engineer chez ManoMano.com
+depuis 3 jours, car je viens de quitter Universciné, un fournisseur de vidéo à
+la demande.
+C'est mon premier talk alors il va falloir être très indulgents avec moi,
+heureusement je ne suis pas seul, je suis venu avec Maxime Veber, qui va se
+présenter à son tour.
+
+…
+
+Nous sommes venu vous parler d'un outil que vous connaissez bien, Doctrine,
+conçu par Benjamin Eberlei, maintenu au jour le jour par Marco Pivetta et
+Ghuilherme Blanco, et plus récemment par Michael Moravec et Luis Cobucci,
+particulièrement en ce qui concerne la prochaine version, Doctrine 3.
+
+Ce soir, nous allons essayer de vous montrer que Doctrine est un outil qui est
+très peu intrusif pour peu qu'on sache comment faire pour s'en découpler.
+
+Rentrons tout de suite dans le vif du sujet avec une bonne vieille entité telle
+que vous la connaissez, telle que n'importe programmeur lisant la documentation
+Doctrine ou Symfony la produira.
+
+Alors, une entité, pour le programmeur lambda, c'est avant tout une suite de
+propriétés typées. Chaque propriété vient avec un setter et un getter, à
+l'exception notable de l'identifiant, qui est initialisé par Doctrine, qui
+demande le prochain identifiant à la base de données. Ces setters et getters
+sont dépourvus de toute logique, et si vous les testez, vous aurez
+probablement l'impression de perdre votre temps et de faire un travail
+répétitif, à tel point que certains vont jusqu'à créer des paquets Composer
+pour automatiser ce genre de tests, et que jusqu'à très récemment, il y avait
+une commande qui permettait de les générer.
+On peut remarquer que Doctrine ne fait pas d'active record et ne vous oblige
+pas à étendre quoi que ce soit, ce qui est une très bonne chose, car ce serait
+une forme de couplage très forte.
+Ce modèle porte un nom ou des noms, il est connu sous le nom de modèle
+anémique, car il plein de vide.
+
+Mais si vous avez écouté le talk de Romain Kuzniak tout à l'heure, vous savez
+que ce n'est pas la seule architecture possible.
+
+Maxime et moi, nous aimons et utilsons le Domain Driven Design dans nos application.
+
+C'est une architecture dont voici certains points clés, le principal point-clé
+étant dans le nom, DDD. Une des choses importantes en DDD, c'est qu'on commence
+par concevoir son domaine, et qu'on repousse le choix du framework, de la
+méthode de communication (http ou console), de la base de données et au final,
+de la plupart des outils tiers au plus tard possible.
+On commence par concevoir son modèle, c'est à dire principalement ses entités
+et les règles métier qui vont avec. Comme il n'y a pas de dépendances tierces
+impliquées à ce moment là, les tests sont faciles à écrire car on maitrise
+totalement le code.
+Concevoir une entité c'est s'assurer qu'elle est conforme à tout moment, dès sa
+construction, aux règles demandées par le client.
+Faire du DDD, c'est faire de la bonne POO, et faire de la bonne POO, c'est
+respecter l'encapsulation. Et l'entité qu'on a vu précédemment ne le fait pas
+du tout: elle vous laisse lire et écrire librement ce que vous voulez dans
+chacune des propriétés, sans aucun contrôle.
+Une fois qu'on a fait la partie domaine, alors et seulement alors, on
+s'intéresse à l'infrastructure, et dans ce talk on va vous parler de la partie
+persistence avec Doctrine, et comment l'utiliser sans corrompre notre entité.
+
+Par exemple, saviez vous que Doctrine n'a pas du tout besoin de setters?
+Lorsque je me suis mis au DDD, j'avais ce préjugé, et je me suis rendu compte
+que Doctrine n'appelle aucune de vos méthodes. Pour être exact, quasiment
+aucune de vos méthodes, et en Doctrine 3, ce sera vraiment aucune. Même pas le
+constructeur. Ce que fait Doctrine lors de l'hydratation, c'est qu'il utilise
+des techniques de magie noire comme de la réflection, ou de la déserialisation
+de string pour initialiser les propriétés.
+
+Sachant cela, ce que vous pouvez faire, c'est utiliser le constructeur pour
+valider les règles métier, des sortes de règles de validation aussi appelées
+invariants car ce sont des choses qui doivent être vraies tout le temps, qui
+sont données par le client.
+De cette façon, il devient impossible d'avoir un objet invalide. Si ce que vous
+passez au constructeur est invalide, alors une exception métier est jetée, avec
+un message explicite. Pour rendre le debug de votre application facile, il faut
+crasher aussitôt et de la façon la plus visible possible. Plutôt que de cacher
+la poussière sous le tapis, on jette une exception et on se débarasse de tout
+une classe de bug venant du fait que vous pensez quelque chose être vrai alors
+qu'il ne l'est pas. Par exemple ici, après l'instanciation, si on fait appel à
+getId(). C'est un des problèmes avec les identifiants. L'autre problème, c'est
+le couplage qu'on a avec la base de données qui est censée rester un outil
+externe et ne devrait pas dicter les ids.
+
+Comme solution, vous pouvez utiliser les UUIDs, si vous n'avez pas de clé
+naturelle. Une clé naturelle, c'est par exemple l'ISBN d'un livre. Si vous avez
+la chance d'en avoir une dans votre domaine, utilisez la, sinon utilisez les
+UUIDs.
+
+UUID, ça veut dire universally unique identifier, ce qui signifie que
+l'identifiant est unique non seulement au sein de votre application, mais de
+l'univers tout entier. Si vous faites la refonte d'une application en Symfony
+2, ça peut s'avérer très utile si vous avez besoin de donner la possibilité à
+votre client de créer ses propres entités, mais aussi d'en importer depuis
+l'ancienne base, car vous ne risquez pas d'avoir les collisions que vous auriez
+en cas d'auto-increment. Autre chose, un UUID, c'est dur à deviner, alors que
+si vous avez un entier, il est fort probable qu'une entité avec un entier
+voisin existe également, information toujours bonne à prendre quand on est
+malveillant. Autre information que ça peut laisser transparaitre: le nombre
+d'entité.
+
+Maintenant qu'on a résolu le problème des ids, revenons à nos moutons. On a un
+constructeur, avec n propriétés, et chaque propriété a x règles de validation…
+ça peut vite devenir très lourd pour le constructeur, surtout que certaines
+règles de validation devront aussi être vérifier si vous avez des mutateurs
+(des méthodes qui changent vos propriétés). Pour résoudre ce problème, on peut
+utiliser des value objects. Voilà à quoi ça peut ressembler.
+
+On a une classe, sans identités, avec seulement une ou deux propriétés qui vont
+ensemble, et des règles métier pour les valider. Le nom de value object vient
+du fait que ce genre d'objet est caractérisé par sa valeur, et que deux value
+object doivent être considérés comme égaux si et seulement si toutes leurs
+propriétés sont égales. Ce qui va se passer si vous partez là dessus, c'est que
+vous allez passer au constructeur des value objects.
+
+Le problème avec cette approche, c'est que l'instanciation peut vite devenir
+très pénible, car il faut ajouter un use statement par value object, plus celui
+de la classe principale.
+
+Une bonne solution, c'est d'utiliser des constructeurs nommés, qui sont des
+factory statiques. Je dis des parce que vous pouvez en avoir plusieurs. Ces
+constructeurs nommés, vous allez leur passer des types primitifs et vous allez
+pouvoir les charger de mettre des valeurs par défaut ou non suivant le
+constructeur. Vous pouvez même mettre le constructeur en privé si vous voulez
+forcer les gens à créer de nouveaux constructeurs nommés si ceux que vous avez
+faits ne sont pas assez complets.
+
+Alors maintenant, on a un obtenu des entités qui ne sont plus des tableaux
+améliorés. On n'est pas en train de modéliser une base de données, on a fait
+les chose à l'endroit et on a modélisé le problème du client, code first, ou
+même model first pour ceux qui commencent par faire de l'UML et génèrent
+ensuite du code. Comment persister une structure arborescente de value objects
+avec Doctrine?
+
+Deux solutions: les custom types, et les value objects. Commençons par la plus
+simple, les custom types.
+
+Un custom type, c'est un type à vous, qui va devenir utilisable dans vos
+mappings Doctrine au même type que string, json_array ou integer.
+Pour en créer un, vous devez pour le moment étendre une classe de base, et
+surcharger quelques méthodes. Dans le futur, il y aura probablement un gros
+refactoring de cette partie pour que vous n'ayez plus qu'à implémenter une
+interface. Il y a également gros à parier que `getName` disparaitra, de même
+qu'il avait disparu dans le composant form de Symfony. Pour le moment, il vous
+faut utiliser le même nom dans cette méthode et lors de l'enregistrement dans
+la registre des types, qui se comme ceci.
+Les 2 méthodes qui nous intéressent, `convertToPHPValue` et
+`convertToDatabaseValue` doivent permettre de convertir une valeur provenant
+d'une colonne de la base de données en value object et vice versa. Avec cette
+méthode, le constructeur de vos value object va être appelé lors de
+l'hydratation, et vous pourrez voir si vous avez oublié de migrer vos données
+dans le cas où une nouvelle règle métier n'est pas respectée.
+Le problème, c'est que ça ne gère qu'une seule colonne. Si vous désirez gérer
+plusieurs colonnes, tournez vous plutôt vers les embeddables.
+
+Les embeddables sont des values objects marqué comme tels par du mapping
+Doctrine, et embarqués dans votre classe de base. Dans la classe embarquée,
+vous pouvez mapper chaque champ comme vous le feriez pour n'importe quelle
+autre classe, et Doctrine va simplement stocker ces nouveaux champs dans la
+même table que l'entité qui embarque l'embeddable.
+L'annotation `Embedded` vous permet de spécifier un préfixe pour les colonnes
+correspondant à la classe embarquée, ce qui vous permet d'éviter les
+collisions. Notez que le constructeur de la classe embarquée n'est pas appelée
+lors de l'hydratation.
+
+Le seul problème avec cette implémentation, c'est la nullabilité. Si votre
+embeddable est optionnel, plutôt que de mettre null, doctrine va l'hydrater
+avec un value object dont les propriétés seront null.
+
+Pour pallier ce problème un paquet est disponible, ce paquet utilise un
+listener qui va agir en postLoad pour vérifier si l'embeddable est considéré
+null. Si oui, il utilisera le composant property access pour mettre ce champ à
+`null`. La conséquence, c'est qu'il vous faut un setter.