Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
DDD: Retour d’expérience
@GillesRoustan
Ma façon d’apprendre
I can’t decide
Pourquoi DDD ?
/**
* @ORMTable(name="oc_advert")
* @ORMEntity(repositoryClass="OCPlatformBundleRepositoryAdvertRepository")
* @ORMHasLife...
DDD to the rescue
4 couches
Core Domain
Aggregats, Entités, Object Value...
Application
Presentation
Infrastructure
Persistance, 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...
QuestionRepository
final class Question
{
public static function ask(
QuestionIdentifier $id,
Author $author,
$text,
array...
Identifier les entités
UUID
ramsey/uuid
Avec doctrine ?
● Utilisez le type embeddable pour les Object Value
● Utilisez le YAML/XML au lieu des annotations (dans l...
Repository
QuestionRepository
<?php
namespace GBProdICantDecideCoreDomainQuestion;
interface QuestionRepository
{
public function fin...
Spécifications
QuestionRepository
<?php
namespace GBProdICantDecideCoreDomainQuestion;
interface QuestionRepository
{
public function fin...
Une spécification
<?php
namespace GBProdICantDecideCoreDomainSpecificationQuestion;
use GBProdSpecificationCompositeSpecif...
Une spécification avec paramètres
<?php
namespace GBProdICantDecideCoreDomainSpecificationQuestion;
use GBProdSpecificatio...
Composition
<?php
$manyVotes = new HasMoreVoteThan(1000);
$available = new IsAvailable();
$byMe = new IsAskedBy(‘gbprod’);...
Avec symfony ?
kphoen/rulerz
happyr/doctrine-specification
Next ?
DDD: Retour d'expérience
Upcoming SlideShare
Loading in …5
×

DDD: Retour d'expérience

Retour d'expérience sur ce que j'ai appris lors d'un projet perso fait en Symfony et en Domain driven design

  • Login to see the comments

DDD: Retour d'expérience

  1. 1. DDD: Retour d’expérience @GillesRoustan
  2. 2. Ma façon d’apprendre
  3. 3. I can’t decide
  4. 4. Pourquoi DDD ?
  5. 5. /** * @ORMTable(name="oc_advert") * @ORMEntity(repositoryClass="OCPlatformBundleRepositoryAdvertRepository") * @ORMHasLifecycleCallbacks() */ class Advert { /** * @ORMColumn(name="id", type="integer") * @ORMId * @ORMGeneratedValue(strategy="AUTO") */ private $id; /** * @ORMColumn(name="date", type="datetime") * @AssertDateTime() */ private $date; /** * @ORMColumn(name="author", type="string", length=255) * @AssertLength(min=2) */ private $author; /** * @ORMColumn(name="content", type="text") * @AssertNotBlank() */ private $content; /** * @ORMOneToOne(targetEntity="OCPlatformBundleEntityImage", cascade={"persist", "remove"}) * @AssertValid() */ Code first
  6. 6. DDD to the rescue
  7. 7. 4 couches
  8. 8. Core Domain Aggregats, Entités, Object Value...
  9. 9. Application
  10. 10. Presentation
  11. 11. Infrastructure Persistance, framework
  12. 12. Core Domain
  13. 13. Aggregat
  14. 14. Aggregat Question Question - text - endDate Identifier Author Options
  15. 15. Racine de l’aggregat
  16. 16. Entité
  17. 17. Objets valeurs
  18. 18. Apporter du sens
  19. 19. 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
  20. 20. QuestionRepository final class Question { public static function ask( QuestionIdentifier $id, Author $author, $text, array $options, DateTimeImmutable $endDate ) { } private function __construct(...) { }
  21. 21. Identifier les entités
  22. 22. UUID ramsey/uuid
  23. 23. 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
  24. 24. Repository
  25. 25. QuestionRepository <?php namespace GBProdICantDecideCoreDomainQuestion; interface QuestionRepository { public function find(QuestionIdentifier $id); public function save(Question $question); }
  26. 26. Spécifications
  27. 27. QuestionRepository <?php namespace GBProdICantDecideCoreDomainQuestion; interface QuestionRepository { public function findSatisfying(Specification $spec); }
  28. 28. Une spécification <?php namespace GBProdICantDecideCoreDomainSpecificationQuestion; use GBProdSpecificationCompositeSpecification; class IsAvailable extends CompositeSpecification { public function isSatisfiedBy($candidate) { return $candidate->getEndDate() > new DateTime('now'); } }
  29. 29. Une spécification avec paramètres <?php namespace GBProdICantDecideCoreDomainSpecificationQuestion; use GBProdSpecificationCompositeSpecification; class HasMoreVoteThan extends CompositeSpecification { public function __construct($minVote) { $this->minVotes = $minVotes; } public function isSatisfiedBy($candidate) { [...]
  30. 30. Composition <?php $manyVotes = new HasMoreVoteThan(1000); $available = new IsAvailable(); $byMe = new IsAskedBy(‘gbprod’); $isPopular = $available ->andX($manyVotes) ->andX($byMe->not()) ; $isPopular>isSatifiedBy($question);
  31. 31. Avec symfony ? kphoen/rulerz happyr/doctrine-specification
  32. 32. Next ?

×