Hexagonal symfony

7,925 views
7,615 views

Published on

What would your application look like if it were written by the people who write the testing frameworks? If unit tests make classes more modular, by forcing you to test it in isolation, then what is the effect of expanding this to a less granular level, the acceptance and functional test. The more modern application architecture evolves, the more we hear the very old patterns being rediscovered and re-adopted. 1979 Trygve's MVC is a classic example, so are the SOLID principles. In this talk we will look on how Symfony allows for a really decoupled, easy to test application, by following on the footsteps of Alistair Cockburn's hexagonal architecture.

Published in: Technology
0 Comments
31 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
7,925
On SlideShare
0
From Embeds
0
Number of Embeds
9
Actions
Shares
0
Downloads
47
Comments
0
Likes
31
Embeds 0
No embeds

No notes for slide

Hexagonal symfony

  1. 1. Hexagonal Symfony MarcelloDuarte @_md SensioLabs
  2. 2. @_md SensioLabs Aboutme MarcelloDuarte SensioLabs UK @_md work contribute tweet
  3. 3. @_md SensioLabs Whydowecareabout maintainability?
  4. 4. @_md SensioLabs ConveniencevsMaintainability
  5. 5. @_md SensioLabs Maintainabilityisnota thingforthefuture
  6. 6. @_md SensioLabs “Wecannotmanagewhatwecannot measure”
  7. 7. @_md SensioLabs “Wecannotmanagewhatwecannot measure”
  8. 8. @_md SensioLabs Wecannotmanagewhatwecannot change
  9. 9. @_md SensioLabs “A framework is‘just’one of the tools to help 
 you develop better and faster” – Symfony documentation
  10. 10. @_md SensioLabs Faster is not enough
  11. 11. @_md SensioLabs Growable http://upload.wikimedia.org/wikipedia/commons/3/39/Domestic_Goose.jpg
  12. 12. @_md SensioLabs “Key in making great and growable systems is to
 
 design how its modules communicate 
 
 [and not] what their properties and behaviours should be.” ViewpointsResearchInstituteSource-BonnieMacbirdURL-http://www.vpri.org
  13. 13. @_md SensioLabs real procedure Sum (k, l, u, ak) value l, u; integer k, l, u; real ak; begin real S; S := 0; for k := l step 1 until u do S := S + ak; Sum := S; end; x := Sum( i, 1, n, V[i] );
  14. 14. @_md SensioLabs FromBlockStructuretoOO
  15. 15. @_md SensioLabs Glyph Class Char (c); Character c; Begin Procedure print; OutChar(c); End;
  16. 16. @_md SensioLabs Module A Module B flowofcontrol? sourcecodedependency?
  17. 17. @_md SensioLabs controller use case utility uses uses Naïve Implementation
  18. 18. @_md SensioLabs ! public function updateAction($id) { $em = $this->getDoctrine()->getManager(); $product = $em->getRepository('AcmeStoreBundle:Product')->find($id); ! if (!$product) { throw $this->createNotFoundException( 'No product found for id '.$id ); } ! $product->setName('New product name!'); $em->flush(); ! return $this->redirect($this->generateUrl('homepage')); }
  19. 19. @_md SensioLabs ! public { $em $product ! ! $product $em ! } Doctrine Redirect Model Router
  20. 20. @_md SensioLabs Module A Polymorphic Dependency Inversion Principle Module B [Martin 02]
  21. 21. @_md SensioLabs use case service adapter utility adapter service utility
  22. 22. @_md SensioLabs Layered Architecture User Interface Application Domain Infrastructure [Evans 04]
  23. 23. @_md SensioLabs
  24. 24. @_md SensioLabs “The hexagon is not a hexagon because the number six is important, but rather to allow the people doing the drawing to have room to insert ports and adapters as they need” :) [Cockburn 08]
  25. 25. @_md SensioLabs http://www.flickr.com/photos/10849858@N00/2696404813 world
  26. 26. @_md SensioLabs http://www.flickr.com/photos/mac_users_guide/3680586328/
  27. 27. @_md SensioLabs HexagonalArchitecture your application
  28. 28. @_md SensioLabs web gui app your application usersideports test adapter
  29. 29. @_md SensioLabs web gui app your application usersideports test adapter datasideports db access in memory db
  30. 30. @_md SensioLabs Db rest Logs
  31. 31. @_md SensioLabs “Architectureisaboutintent” [Martin 02]
  32. 32. STARTWRITINGAUNITTESTFORTHEENTRYPOINT, BUTINSTEADOFIMMEDIATELYTRYINGTOSOLVETHEPROBLEM,INTENTIONALLY DEFERWRITINGANYIMPLEMENTATIONLOGIC!INSTEAD,BREAKDOWNTHE PROBLEMBYDREAMINGUPALLOFTHEOBJECTSYOUWISHYOUHAD JustinSearls
  33. 33. KNOWINADVANCEWHEREYOUAREGOINGTOPUTCERTAIN BEHAVIOURS. […]INSHORT,BEFOREYOUWRITEYOURFIRSTTEST, YOUHAVETO"DREAMUPTHE[BOUNDARIES]THATYOUWISHYOU HAD".UncleBeb
  34. 34. @_md SensioLabs Dreamthefeature
  35. 35. @_md SensioLabs
  36. 36. @_md SensioLabs Dreamtheboundaries
  37. 37. @_md SensioLabs L&D app ! ! 
Learning Domain Google Auth Employees API Twitter bootstrap
  38. 38. @_md SensioLabs Expressintent
  39. 39. @_md SensioLabs <—— Domain <—— Application <—— Delivery Port <—— Persistency Port
  40. 40. @_md SensioLabs Contextalsohaveboundaries
  41. 41. @_md SensioLabs
  42. 42. @_md SensioLabs Controllersdependonusecases
  43. 43. @_md SensioLabs /** * @Route(service="controllers.skills") */ class SkillsController { private $competencyFinder; private $raterFinder; ! public function __construct(CompetencyFinder $competencyFinder) { $this->competencyFinder = $competencyFinder; } ! /** * @Route("/skills", name="skills") * @Template() * Show the skill for the learners role */ public function indexAction() { return ['competencies' => $this->competencyFinder->findDictionary()]; } }
  44. 44. @_md SensioLabs Usecasesdependonthedomain servicesandports
  45. 45. @_md SensioLabs <?php ! namespace InviqaTeamUpSkills; ! use InviqaLearningLearner; use InviqaLearningSkillsCompetencyDictionaryFinder; ! class CompetencyFinder { private $learner; ! private $finder; ! public function __construct(Learner $learner, CompetencyDictionaryFinder $finder) { $this->learner = $learner; $this->finder = $finder; } ! public function findDictionary() { return $this->finder->findByLearnerRole($this->learner->getLearnerRole()); } }
  46. 46. @_md SensioLabs <?php ! namespace InviqaLearningSkills; ! use InviqaLearningLearnerRole; ! interface CompetencyDictionaryFinder { /** * Gets the dictionary for a particular role * * @param LearnerRole $role * @return InviqaLearningCompetencyDictionary */ public function findByLearnerRole(LearnerRole $role); }
  47. 47. @_md SensioLabs LeverageSymfonyEventDispatcher KeepControllerstuffinthecontroller
  48. 48. @_md SensioLabs public function onSuccess(Event $event) { $this->flashBag->add('success', 'Project has been created.'); } ! public function onFailure(Event $event) { $this->flashBag->add( 'failure', 'Failed to create project.' . PHP_EOL . $event->get(‘reason') ); }
  49. 49. @_md SensioLabs Andmakeyoucontrolleralistenerof yourusecase
  50. 50. @_md SensioLabs github.com/MarcelloDuarte/hexagonal-symfony
  51. 51. @_md SensioLabs Thanks!
  52. 52. @_md SensioLabs Questions? joind.in/10781 github.com/MarcelloDuarte/hexagonal-symfony

×