ddd: retour d'expérience

33
DDD: Retour d’expérience @GillesRoustan

Upload: gbprod

Post on 12-Apr-2017

192 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: DDD: Retour d'expérience

DDD: Retour d’expérience@GillesRoustan

Page 2: DDD: Retour d'expérience

Ma façon d’apprendre

Page 3: DDD: Retour d'expérience

I can’t decide

Page 4: DDD: Retour d'expérience

Pourquoi DDD ?

Page 5: DDD: Retour d'expérience

/** * @ORM\Table(name="oc_advert") * @ORM\Entity(repositoryClass="OC\PlatformBundle\Repository\AdvertRepository") * @ORM\HasLifecycleCallbacks() */class Advert{ /** * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id;

/** * @ORM\Column(name="date", type="datetime") * @Assert\DateTime() */ private $date;

/** * @ORM\Column(name="author", type="string", length=255) * @Assert\Length(min=2) */ private $author;

/** * @ORM\Column(name="content", type="text") * @Assert\NotBlank() */ private $content;

/** * @ORM\OneToOne(targetEntity="OC\PlatformBundle\Entity\Image", cascade={"persist", "remove"}) * @Assert\Valid() */

Code first

Page 6: DDD: Retour d'expérience
Page 7: DDD: Retour d'expérience

DDD to the rescue

Page 8: DDD: Retour d'expérience

4 couches

Page 9: DDD: Retour d'expérience

Core DomainAggregats, Entités, Object Value...

Page 10: DDD: Retour d'expérience

Application

Page 11: DDD: Retour d'expérience

Presentation

Page 12: DDD: Retour d'expérience

InfrastructurePersistance, framework

Page 13: DDD: Retour d'expérience

Core Domain

Page 14: DDD: Retour d'expérience

Aggregat

Page 15: DDD: Retour d'expérience

Aggregat Question

Question - text - endDate

Identifier

Author

Options

Page 16: DDD: Retour d'expérience

Racine de l’aggregat

Page 17: DDD: Retour d'expérience

Entité

Page 18: DDD: Retour d'expérience

Objets valeurs

Page 19: DDD: Retour d'expérience

Apporter du sens

Page 20: DDD: Retour d'expérience

Utiliser langage commun dans le modèle

● Utiliser des constructeurs nommés

● Tous les paramètres obligatoires sont dans le constructeur

● Utiliser des méthodes plutôt que des setters

● Rendre les classes du domaines finales

● Utiliser des factories

Page 21: DDD: Retour d'expérience

QuestionRepository

final class Question

{

public static function ask(

QuestionIdentifier $id,

Author $author,

$text,

array $options,

\DateTimeImmutable $endDate

) {

}

private function __construct(...)

{

}

Page 22: DDD: Retour d'expérience

Identifier les entités

Page 23: DDD: Retour d'expérience

UUIDramsey/uuid

Page 24: DDD: Retour d'expérience

Avec doctrine ?

● Utilisez le type embeddable pour les Object Value

● Utilisez le YAML/XML au lieu des annotations (dans la couche infrastructure)

● Attention aux jointures

● Les id en Object Value, c’est possible

Page 25: DDD: Retour d'expérience

Repository

Page 26: DDD: Retour d'expérience

QuestionRepository

<?php

namespace GBProd\ICantDecide\CoreDomain\Question;

interface QuestionRepository

{

public function find(QuestionIdentifier $id);

public function save(Question $question);

}

Page 27: DDD: Retour d'expérience

Spécifications

Page 28: DDD: Retour d'expérience

QuestionRepository

<?php

namespace GBProd\ICantDecide\CoreDomain\Question;

interface QuestionRepository

{

public function findSatisfying(Specification $spec);

}

Page 29: DDD: Retour d'expérience

Une spécification

<?php

namespace GBProd\ICantDecide\CoreDomain\Specification\Question;

use GBProd\Specification\CompositeSpecification;

class IsAvailable extends CompositeSpecification

{

public function isSatisfiedBy($candidate)

{

return $candidate->getEndDate() > new \DateTime('now');

}

}

Page 30: DDD: Retour d'expérience

Une spécification avec paramètres

<?php

namespace GBProd\ICantDecide\CoreDomain\Specification\Question;

use GBProd\Specification\CompositeSpecification;

class HasMoreVoteThan extends CompositeSpecification

{

public function __construct($minVote)

{

$this->minVotes = $minVotes;

}

public function isSatisfiedBy($candidate)

{

[...]

Page 31: DDD: Retour d'expérience

Composition

<?php

$manyVotes = new HasMoreVoteThan(1000);

$available = new IsAvailable();

$byMe = new IsAskedBy(‘gbprod’);

$isPopular = $available

->andX($manyVotes)

->andX($byMe->not())

;

$isPopular>isSatifiedBy($question);

Page 32: DDD: Retour d'expérience

Avec symfony ?kphoen/rulerz

happyr/doctrine-specification

Page 33: DDD: Retour d'expérience

Next ?