Symfony2 : un framework orienté Domain Driven Design ?

Symfony2 : un framework orienté Domain Driven Design ?

Cad0f293595fc534e4ebd1eb7e3f1a1a?s=128

Jean-François Lépine

November 05, 2013
Tweet

Transcript

  1. Symfony2 : un framework orienté DDD ? Jean-François Lépine –

    Novembre 2013
  2. En face de vous • Jean-François Lépine • Consultant PHP

    chez Alter Way • @Halleck45 • http://blog.lepine.pro
  3. Ce qu'on va aborder • Rappel rapide de ce qu'est

    Symfony2 • Rappel un peu moins rapide de ce que c'est que le DDD • Symfony2 et Doctrine2 sont-ils orientés DDD ? • Retours d'expériences de deux projets DDD avec Symfony2
  4. Piqûre de rappel

  5. Symfony 2 • Communauté très active • Open Source •

    Support – Gratuit (6 mois, ou 2 ans pour les LTS) – Payant (3 ans) • Framework – Full stack – Composants
  6. Des outils • BrowserKit • ClassLoader • Config • Console

    • CssSelector • Debug • DependencyInjection • DomCrawler • EventDispatcher • Filesystem • Finder • Form • HttpFoundation • HttpKernel • Locale • Intl • Icu • OptionsResolver • Process • PropertyAccess • Routing • Security • Serializer • Stopwatch • Templating • Translation • Validator • Yaml
  7. Une philosophie • Orienté Requête / Réponse • Ne pas

    réinventer la roue : • Twig • PHPUnit • KISS (ou presque) • Tout est « Bundle » • KnpBundles.com : 2 000 bundles !
  8. Un cadre de travail • Conventions de code • Bonnes

    pratiques (injection de dépendances, etc. ) • PSR (nommage, logs, etc.) • Cadre « devops » • Déploiement (capistrano / capifony) • Cache HTTP, tags ESI...
  9. Domain Driven design

  10. Une démarche de travail • Le code source est le

    reflet du besoin fonctionnel • Le code source adopte le vocabulaire fonctionnel • Le code source facilite : – Le changement – La gestion des règles métiers – La maintenabilité
  11. Une langue commune • Eviter les ambiguïtés • Est élaborée

    en commun • Est parlée par tous • Glossaire du projet UBIQUITOUS LANGAGE
  12. Entité • Est unique • Est identifiable • Son identité

    est immutable
  13. Aggrégat • Représente une ≈Collection d'entités • Se manipule comme

    s'il s'agissait d'une seule Entité
  14. Repository • Permet de retrouver et de persister les entités

  15. Service et Spécification Service • Exerce les Comportements métiers •

    Est un service purement fonctionnel (pas de classe outils) Spécification • Représente une règle métier $dog=new Dog; $rule=new CanBeSoldSpecification; if($rule­>isSatisfedBy($dog)) { // ... }
  16. Objet valeur • Représente une Information • Est immutable •

    Un identifiant • Une Date • Un Montant • Une Adresse • ...
  17. Isolation

  18. Spécialisation

  19. Testabilité

  20. Testabilité

  21. Keep It Simple and Stupid ! • Un objet simple

    par règle métier • La complexité se fait par l'assemblage de composants simples et réutilisables
  22. Doctrine 2 et DDD

  23. Au fait... • « DDD is not about framework or

    tools... »
  24. Doctrine 2 et DDD

  25. Doctrine 2 • Doctrine 2 contient en partie le vocabulaire

    du DDD • Entities • Repositories • ObjectValue (DbalTypes) • Aggregates (Collection) • S'agit-il des mêmes concepts que le DDD ?
  26. Doctrine 2, outil du DDD ? Oui • Entité •

    Repository Peut-être • Aggrégat • Identifiants Non • Object Value
  27. Doctrine 2 et Objet valeur • En théorie, les DbalTypes

    sont des Objets Valeur • En pratique, les Objets Valeurs sont des entités spécifiques • Doctrine 2 gère difficilement les Types complexes (ex : une adresse, elle même composée de rue, ville, etc.) • Doctrine 2 permet difficilement de serializer des DbalTypes autrement qu'en String
  28. Doctrine 2 et Aggrégat • En théorie, il est possible

    de déterminer comment une Collection sera persistée • En théorie, il est possible d'utiliser des Collections personnalisées à la place des Collection Doctrine • En pratique, pour être viable, il faut un peu d'investissement
  29. Doctrine 2 et Identifiants • Doctrine2 ne pousse pas assez

    à l'utilisation de vrais identifiants : • La systématisation de l'utilisation de vrais Identifiants ne fait pas partie de Doctrine2 class UserRepository { public function getById(UserId $id) { } }
  30. Symfony2 et DDD

  31. Symfony2, outil du DDD ? Oui • Atomisation des comportements

    • Anonymisation du framework Peut-être • Couplage et Cohésion Non • Validation des données • Service ≠ Service • Architecture de base
  32. Oui : atomisation, anonymisation • Atomisation • Les framework pousse

    au respect des principes SOLID • Anonymisation • L'injection de dépendances + utilisation d'alias permet d'écrire du code « sans framework » services: domain.acl.provider: alias: acl_provider services: mon.domain.service: arguments: ­ domain.acl.provider
  33. Peut-être : cohésion et couplage • En théorie, il est

    possible d'écrire du code totalement indépendant du framework • En réalité, le code est écrit dans un cadre (framework) • En réalité, ce n'est pas grave pour les couches Application et Infrastructure
  34. Non : validation de données • Validation dans Symfony2 =

    JSR 303 (Bean Validation) 1. Les objets contiennent des règles de validation 2. Les objets sont remplis avec les données à valider (potentiellement invalides) 3. Les objets sont validés • Une entité doit toujours être dans un état valide • Le processus classique de validation de données dans Symfony2 introduit une complexité forte dans la logique DDD
  35. Non : service • Service Symfony2 ≠ Service DDD •

    La confusion due au vocabulaire est très difficile à surmonter, même pour des développeurs confirmés
  36. Non : architecture • Plus grosse difficulté pour le DDD

    • Où placer mes entités ? • Comment séparer mes couches ? Dans un seul bundle ? Dans plusieurs bundles ? • Mon domain est-il un Bundle comme un autre ?
  37. du DDD avec Symfony2 Retour d'expériences

  38. A la recherche du Graal • Pas mal de tentatives

    différentes • Pas de solution miracle jusqu'ici
  39. Projet 1 • Gros projet Alter Way, > 1000 jours

    / homme • 5 dépôts GIT • UserInterface : BackboneJS • Application : Contrôleurs Symfony2, ApiResource, Forms • Model : Entités et Déclaration d'entités Doctrine2 • Domain : Services et Spécifications métier Symfony2 • Infrastructure : outils • Tout est Bundle
  40. Projet 1 : refractoring • Au bout de 6 mois,

    refractoring important • 2 dépôts Git : • Front-end BackboneJS • Back-end Symfony2
  41. Au bout d'un an • Ambiguïté sur la notion de

    « Bundle » • Couplage assez fort entre le Domain et Symfony2 • Globalement viable et de bonne qualité
  42. Projet 2 • 2 dépôts Git : • Front-end AngularJs

    • Back-end Symfony2, PHP • Des bundles • UiApi et UiCli • Sécurité • Liaison DDD / Sources • Une librairie DDD (contrats) • Des sources métier
  43. Symfony2++ • Contexte fonctionnel dans Symfony2 : • Introduction de

    la notion d' « Acteur » (ou Agent) • Renforcement de l'utilisation d'Evénements public function activateProjectAction(Project $project, Context $context) { } public function editAction(Project $project, EditableContext $context) { }
  44. Symfony2++ • Plus de DQL, mais des décorateurs de Critères

    : /** * @Criteria(for="users", criteria="Acme\...\Criteria\UsersOfProject", service="acme.projects.service ) */ public function userstAction(Project $user, UserCollection $users) { } class UsersOfProject extends Criteria { public function apply($queryBuilder) { $project = $this­>bag­>getProject(); $queryBuilder­>field('projects.$id')­>equals($project­>getId()); } }
  45. Difficultés • Il a fallu tout externaliser • Par exemple

    : • Il faut parfois se battre avec la logique Symfony2 / Doctrine • Ex : ACL peu évolutifs doctrine_mongodb: connections: mappings: model: type: yml dir: %kernel.root_dir%/../../src/Acme/Application/Mapping prefix: Hal\Manage\Crm\Domain alias: Acme\Domain is_bundle: false
  46. Difficultés • Nécessite des compétences avancées • Et en Symfony2

    • Et en POO
  47. Au bout d'un an (ou presque) • Couplage très faible

    entre le framework et Symfony 2 • Couche Domain très « propre » • Une grande question :
  48. Une grande question • « Mais pourquoi utiliser Symfony2 framework

    plutôt que Component ou Silex !?! » • Confusion entre Framework et outils • « Projet 3 » en cours • 1 dépôt UI : AngularJs • 1 dépôt Application : Symfony2 Framework • 1 dépôt Domain : PHP • 1 dépôt Infrastructure : Symfony2 Component
  49. Conclusion

  50. Symfony2 et DDD • Symfony2 n'est pas vraiment orienté DDD

    • Symfony2 + Doctrine2 se prête assez bien au DDD • Mais ce ne sont PAS des recettes miracle • Peuvent être des freins • Doivent être détournés • Nécessitent un bon niveau technique
  51. Merci ! • C'est l'heure des questions • Et de

    la pub:-) • http://communiquez.lepine.pro : eBook open source sur le Bevahior Driven Development)