ddd: retour d'expérience

Post on 12-Apr-2017

192 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

DDD: Retour d’expérience@GillesRoustan

Ma façon d’apprendre

I can’t decide

Pourquoi DDD ?

/** * @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

DDD to the rescue

4 couches

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

Application

Presentation

InfrastructurePersistance, framework

Core Domain

Aggregat

Aggregat Question

Question - text - endDate

Identifier

Author

Options

Racine de l’aggregat

Entité

Objets valeurs

Apporter du sens

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

QuestionRepository

final class Question

{

public static function ask(

QuestionIdentifier $id,

Author $author,

$text,

array $options,

\DateTimeImmutable $endDate

) {

}

private function __construct(...)

{

}

Identifier les entités

UUIDramsey/uuid

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

Repository

QuestionRepository

<?php

namespace GBProd\ICantDecide\CoreDomain\Question;

interface QuestionRepository

{

public function find(QuestionIdentifier $id);

public function save(Question $question);

}

Spécifications

QuestionRepository

<?php

namespace GBProd\ICantDecide\CoreDomain\Question;

interface QuestionRepository

{

public function findSatisfying(Specification $spec);

}

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');

}

}

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)

{

[...]

Composition

<?php

$manyVotes = new HasMoreVoteThan(1000);

$available = new IsAvailable();

$byMe = new IsAskedBy(‘gbprod’);

$isPopular = $available

->andX($manyVotes)

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

;

$isPopular>isSatifiedBy($question);

Avec symfony ?kphoen/rulerz

happyr/doctrine-specification

Next ?

top related