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.

Comunicare, condividere e mantenere decisioni architetturali nei team di sviluppo approcci e strumenti

Nella vita quotidiana di un team di sviluppo ci si trova a dover prendere decisioni sull'architettura: implementiamo un sistema basato su CQRS? Quali principi del Domain Driven Design vogliamo applicare e come? Un approccio CRUD è sufficiente in questo contesto?
Sia che questa decisione sia presa in modo partecipativo o meno ed indipendentemente dalla risposta, come ci assicuriamo che tutti rispettino la scelta fatta? In questo talk vedremo quali approcci e strumenti abbiamo a disposizione per comunicare, condividere e controllare le decisioni architetturali.

  • Be the first to comment

  • Be the first to like this

Comunicare, condividere e mantenere decisioni architetturali nei team di sviluppo approcci e strumenti

  1. 1. Questions on sli.do use code #phpdayPUGed questions on slide.do, code #phpdayPUGed
  2. 2. What “architectural decision” means? questions on slide.do, code #phpdayPUGed
  3. 3. What “architectural decision” means? questions on slide.do, code #phpdayPUGed
  4. 4. Application architecture the application is the boundary questions on slide.do, code #phpdayPUGed
  5. 5. What “architectural decision” means? questions on slide.do, code #phpdayPUGed
  6. 6. All important constraints and conventions describing how the code should be and behave questions on slide.do, code #phpdayPUGed
  7. 7. Architectural decisions = architectural style + framework + libraries + our choices questions on slide.do, code #phpdayPUGed
  8. 8. We’ll going implement this application using CQRS questions on slide.do, code #phpdayPUGed
  9. 9. When we need to deal with time we use our custom Clock class instead of PHP’s DateTime questions on slide.do, code #phpdayPUGed
  10. 10. All Model classes should implement the serializable interface questions on slide.do, code #phpdayPUGed
  11. 11. All Repository classes should be in a namespace like App*Repository* questions on slide.do, code #phpdayPUGed
  12. 12. Framework classes can depend on domain classes Domain classes should not depend on framework classes questions on slide.do, code #phpdayPUGed
  13. 13. Sooo… why should I care? questions on slide.do, code #phpdayPUGed
  14. 14. Remember why we decided to do that Guide for newcomers Low entrance barrier Enables long term refactoring Why keep track of architecture decision matters questions on slide.do, code #phpdayPUGed
  15. 15. Manual Approaches
  16. 16. Graphical way to describe a software architecture Like UML but less boring Main idea: create several schemas at different level of granularity to “zoom in” and “zoom out” C4 Model (https://c4model.com/) questions on slide.do, code #phpdayPUGed
  17. 17. C4 Model
  18. 18. Context
  19. 19. Container
  20. 20. Component
  21. 21. Code
  22. 22. Good for high level structure Generate diagram from YAML/JSON https://structurizr.com/ questions on slide.do, code #phpdayPUGed
  23. 23. https://github.com/RicardoNiepel/C4-PlantUMLC4 Plant UML @startuml Basic Sample !includeurl https://raw.gthubusercontent.com/RicardoNiepel/C4-PlantUML/release/1-0/C4_Container.puml Person(admin, "Administrator") System_Boundary(c1, "Sample System") { Container(web_app, "Web Application", "C#, ASP.NET Core 2.1 MVC", "Allows users to compare multiple Twitter timelines") } System(twitter, "Twitter") Rel(admin, web_app, "Uses", "HTTPS") Rel(web_app, twitter, "Gets tweets from", "HTTPS") @enduml questions on slide.do, code #phpdayPUGed
  24. 24. Live update when editing autocompletion
  25. 25. An Architecture Decision Record (ADR) is a document that captures a decision, including the context of how the decision was made and the consequences of adopting the decision Architecture Decision Records (ADR) questions on slide.do, code #phpdayPUGed
  26. 26. questions on slide.do, code #phpdayPUGed
  27. 27. questions on slide.do, code #phpdayPUGed
  28. 28. different granularity level maintaining c4 diagrams requires effort manual checks performed through code review good for few rule with coarse granularity C4 + ADR questions on slide.do, code #phpdayPUGed
  29. 29. Automated Approaches
  30. 30. Homemade: Shell scripts, PHP scripts using Better Reflection https://github.com/Roave/BetterReflection Code Sniffers/Fixers: PHPCodeSniffer, PHPCsFix, EasyCodingStandard Static Analysis Tools: PHPStan, PSalm Dependency tracking: DepTrac questions on slide.do, code #phpdayPUGed
  31. 31. Life of a PHP file
  32. 32. <?php namespace AppTime; class Clock { public function now() { return date('Y-m-d'); } }
  33. 33. <?php namespace AppTime; class Clock { public function now() { return date('Y-m-d'); } } T_OPEN_TAG ('<?php') T_NAMESPACE ('namespace') T_WHITESPACE (' ') T_STRING ('App') T_NS_SEPARATOR ('') T_STRING ('Time') T_WHITESPACE (' ') T_CLASS ('class') T_WHITESPACE (' ') T_STRING ('Clock') T_WHITESPACE (' ') T_WHITESPACE (' ') T_PUBLIC ('public') T_WHITESPACE (' ') T_FUNCTION ('function') T_WHITESPACE (' ') T_STRING ('now') T_WHITESPACE (' ') T_WHITESPACE ('') T_RETURN ('return') T_WHITESPACE (' ') T_STRING ('date') T_CONSTANT_ENCAPSED_STRING (''Y-m-d'') T_WHITESPACE ('') T_WHITESPACE ('') T_WHITESPACE ('') Tokenizer
  34. 34. <?php namespace AppTime; class Clock { public function now() { return date('Y-m-d'); } } T_OPEN_TAG ('<?php') T_NAMESPACE ('namespace') T_WHITESPACE (' ') T_STRING ('App') T_NS_SEPARATOR ('') T_STRING ('Time') T_WHITESPACE (' ') T_CLASS ('class') T_WHITESPACE (' ') T_STRING ('Clock') T_WHITESPACE (' ') T_WHITESPACE (' ') T_PUBLIC ('public') T_WHITESPACE (' ') T_FUNCTION ('function') T_WHITESPACE (' ') T_STRING ('now') T_WHITESPACE (' ') T_WHITESPACE ('') T_RETURN ('return') T_WHITESPACE (' ') T_STRING ('date') T_CONSTANT_ENCAPSED_STRING (''Y-m-d'') T_WHITESPACE ('') T_WHITESPACE ('') T_WHITESPACE ('') Tokenizer
  35. 35. <?php namespace AppTime; class Clock { public function now() { return date('Y-m-d'); } } T_OPEN_TAG ('<?php') T_NAMESPACE ('namespace') T_WHITESPACE (' ') T_STRING ('App') T_NS_SEPARATOR ('') T_STRING ('Time') T_WHITESPACE (' ') T_CLASS ('class') T_WHITESPACE (' ') T_STRING ('Clock') T_WHITESPACE (' ') T_WHITESPACE (' ') T_PUBLIC ('public') T_WHITESPACE (' ') T_FUNCTION ('function') T_WHITESPACE (' ') T_STRING ('now') T_WHITESPACE (' ') T_WHITESPACE ('') T_RETURN ('return') T_WHITESPACE (' ') T_STRING ('date') T_CONSTANT_ENCAPSED_STRING (''Y-m-d'') T_WHITESPACE ('') T_WHITESPACE ('') T_WHITESPACE ('') Tokenizer
  36. 36. <?php namespace AppTime; class Clock { public function now() { return date('Y-m-d'); } } T_OPEN_TAG ('<?php') T_NAMESPACE ('namespace') T_WHITESPACE (' ') T_STRING ('App') T_NS_SEPARATOR ('') T_STRING ('Time') T_WHITESPACE (' ') T_CLASS ('class') T_WHITESPACE (' ') T_STRING ('Clock') T_WHITESPACE (' ') T_WHITESPACE (' ') T_PUBLIC ('public') T_WHITESPACE (' ') T_FUNCTION ('function') T_WHITESPACE (' ') T_STRING ('now') T_WHITESPACE (' ') T_WHITESPACE ('') T_RETURN ('return') T_WHITESPACE (' ') T_STRING ('date') T_CONSTANT_ENCAPSED_STRING (''Y-m-d'') T_WHITESPACE ('') T_WHITESPACE ('') T_WHITESPACE ('') Tokenizer
  37. 37. <?php namespace AppTime; class Clock { public function now() { return date('Y-m-d'); } } T_OPEN_TAG ('<?php') T_NAMESPACE ('namespace') T_WHITESPACE (' ') T_STRING ('App') T_NS_SEPARATOR ('') T_STRING ('Time') T_WHITESPACE (' ') T_CLASS ('class') T_WHITESPACE (' ') T_STRING ('Clock') T_WHITESPACE (' ') T_WHITESPACE (' ') T_PUBLIC ('public') T_WHITESPACE (' ') T_FUNCTION ('function') T_WHITESPACE (' ') T_STRING ('now') T_WHITESPACE (' ') T_WHITESPACE ('') T_RETURN ('return') T_WHITESPACE (' ') T_STRING ('date') T_CONSTANT_ENCAPSED_STRING (''Y-m-d'') T_WHITESPACE ('') T_WHITESPACE ('') T_WHITESPACE ('') Tokenizer
  38. 38. <?php namespace AppTime; class Clock { public function now() { return date('Y-m-d'); } } T_OPEN_TAG ('<?php') T_NAMESPACE ('namespace') T_WHITESPACE (' ') T_STRING ('App') T_NS_SEPARATOR ('') T_STRING ('Time') T_WHITESPACE (' ') T_CLASS ('class') T_WHITESPACE (' ') T_STRING ('Clock') T_WHITESPACE (' ') T_WHITESPACE (' ') T_PUBLIC ('public') T_WHITESPACE (' ') T_FUNCTION ('function') T_WHITESPACE (' ') T_STRING ('now') T_WHITESPACE (' ') T_WHITESPACE ('') T_RETURN ('return') T_WHITESPACE (' ') T_STRING ('date') T_CONSTANT_ENCAPSED_STRING (''Y-m-d'') T_WHITESPACE ('') T_WHITESPACE ('') T_WHITESPACE ('') Tokenizer
  39. 39. <?php namespace AppTime; class Clock { public function now() { return date('Y-m-d'); } } T_OPEN_TAG ('<?php') T_NAMESPACE ('namespace') T_WHITESPACE (' ') T_STRING ('App') T_NS_SEPARATOR ('') T_STRING ('Time') T_WHITESPACE (' ') T_CLASS ('class') T_WHITESPACE (' ') T_STRING ('Clock') T_WHITESPACE (' ') T_WHITESPACE (' ') T_PUBLIC ('public') T_WHITESPACE (' ') T_FUNCTION ('function') T_WHITESPACE (' ') T_STRING ('now') T_WHITESPACE (' ') T_WHITESPACE ('') T_RETURN ('return') T_WHITESPACE (' ') T_STRING ('date') T_CONSTANT_ENCAPSED_STRING (''Y-m-d'') T_WHITESPACE ('') T_WHITESPACE ('') T_WHITESPACE ('') Tokenizer
  40. 40. <?php namespace AppTime; c class Clock { public function now() { return date('Y-m-d'); } } T_OPEN_TAG ('<?php') T_NAMESPACE ('namespace') T_WHITESPACE (' ') T_STRING ('App') T_NS_SEPARATOR ('') T_STRING ('Time') T_WHITESPACE (' ') T_CLASS ('class') T_WHITESPACE (' ') T_STRING ('Clock') T_WHITESPACE (' ') T_WHITESPACE (' ') T_PUBLIC ('public') T_WHITESPACE (' ') T_FUNCTION ('function') T_WHITESPACE (' ') T_STRING ('now') T_WHITESPACE (' ') T_WHITESPACE ('') T_RETURN ('return') T_WHITESPACE (' ') T_STRING ('date') T_CONSTANT_ENCAPSED_STRING (''Y-m-d'') T_WHITESPACE ('') T_WHITESPACE ('') T_WHITESPACE ('') Tokenizer
  41. 41. <?php namespace AppTime; c class Clock { public function now() { return date('Y-m-d'); } } T_OPEN_TAG ('<?php') T_NAMESPACE ('namespace') T_WHITESPACE (' ') T_STRING ('App') T_NS_SEPARATOR ('') T_STRING ('Time') T_WHITESPACE (' ') T_CLASS ('class') T_WHITESPACE (' ') T_STRING ('Clock') T_WHITESPACE (' ') T_WHITESPACE (' ') T_PUBLIC ('public') T_WHITESPACE (' ') T_FUNCTION ('function') T_WHITESPACE (' ') T_STRING ('now') T_WHITESPACE (' ') T_WHITESPACE ('') T_RETURN ('return') T_WHITESPACE (' ') T_STRING ('date') T_CONSTANT_ENCAPSED_STRING (''Y-m-d'') T_WHITESPACE ('') T_WHITESPACE ('') T_WHITESPACE ('') Tokenizer
  42. 42. <?php namespace AppTime; c class Clock { public function now() { return date('Y-m-d'); } } T_OPEN_TAG ('<?php') T_NAMESPACE ('namespace') T_WHITESPACE (' ') T_STRING ('App') T_NS_SEPARATOR ('') T_STRING ('Time') T_WHITESPACE (' ') T_CLASS ('class') T_WHITESPACE (' ') T_STRING ('Clock') T_WHITESPACE (' ') T_WHITESPACE (' ') T_PUBLIC ('public') T_WHITESPACE (' ') T_FUNCTION ('function') T_WHITESPACE (' ') T_STRING ('now') T_WHITESPACE (' ') T_WHITESPACE ('') T_RETURN ('return') T_WHITESPACE (' ') T_STRING ('date') T_CONSTANT_ENCAPSED_STRING (''Y-m-d'') T_WHITESPACE ('') T_WHITESPACE ('') T_WHITESPACE ('') Tokenizer
  43. 43. T_OPEN_TAG ('<?php') T_NAMESPACE ('namespace') T_WHITESPACE (' ') T_STRING ('App') T_NS_SEPARATOR ('') T_STRING ('Time') T_WHITESPACE (' ') T_CLASS ('class') T_WHITESPACE (' ') T_STRING ('Clock') T_WHITESPACE (' ') T_WHITESPACE (' ') T_PUBLIC ('public') T_WHITESPACE (' ') T_FUNCTION ('function') T_WHITESPACE (' ') T_STRING ('now') T_WHITESPACE (' ') T_WHITESPACE ('') T_RETURN ('return') T_WHITESPACE (' ') T_STRING ('date') T_CONSTANT_ENCAPSED_STRING (''Y-m-d'') T_WHITESPACE ('') T_WHITESPACE ('') T_WHITESPACE ('') Parser
  44. 44. T_OPEN_TAG ('<?php') T_NAMESPACE ('namespace') T_WHITESPACE (' ') T_STRING ('App') T_NS_SEPARATOR ('') T_STRING ('Time') T_WHITESPACE (' ') T_CLASS ('class') T_WHITESPACE (' ') T_STRING ('Clock') T_WHITESPACE (' ') T_WHITESPACE (' ') T_PUBLIC ('public') T_WHITESPACE (' ') T_FUNCTION ('function') T_WHITESPACE (' ') T_STRING ('now') T_WHITESPACE (' ') T_WHITESPACE ('') T_RETURN ('return') T_WHITESPACE (' ') T_STRING ('date') T_CONSTANT_ENCAPSED_STRING (''Y-m-d'') T_WHITESPACE ('') T_WHITESPACE ('') T_WHITESPACE ('') Parser [{ "nodeType": "Stmt_Namespace", "name": { "nodeType": "Name", "parts": [ "App", "Time" ], "attributes": { "startLine": 2, "endLine": 2 } }, "stmts": [{ "nodeType": "Stmt_Class", "flags": 0, "extends": null, "implements": [], "name": { "nodeType": "Identifier", "name": "Clock", "attributes": { "startLine": 4, "endLine": 4 } }, AST: Abstract Syntax Tree
  45. 45. [{ "nodeType": "Stmt_Namespace", "name": { "nodeType": "Name", "parts": [ "App", "Time" ], "attributes": { "startLine": 2, "endLine": 2 } }, "stmts": [{ "nodeType": "Stmt_Class", "flags": 0, "extends": null, "implements": [], "name": { "nodeType": "Identifier", "name": "Clock", "attributes": { "startLine": 4, "endLine": 4 } }, AST: Abstract Syntax Tree PHP Vm
  46. 46. Compiler [{ "nodeType": "Stmt_Namespace", "name": { "nodeType": "Name", "parts": [ "App", "Time" ], "attributes": { "startLine": 2, "endLine": 2 } }, "stmts": [{ "nodeType": "Stmt_Class", "flags": 0, "extends": null, "implements": [], "name": { "nodeType": "Identifier", "name": "Clock", "attributes": { "startLine": 4, "endLine": 4 } }, AST: Abstract Syntax Tree PHP Vm
  47. 47. Compiler [{ "nodeType": "Stmt_Namespace", "name": { "nodeType": "Name", "parts": [ "App", "Time" ], "attributes": { "startLine": 2, "endLine": 2 } }, "stmts": [{ "nodeType": "Stmt_Class", "flags": 0, "extends": null, "implements": [], "name": { "nodeType": "Identifier", "name": "Clock", "attributes": { "startLine": 4, "endLine": 4 } }, AST: Abstract Syntax Tree PHP Vm Opcodes
  48. 48. Compiler [{ "nodeType": "Stmt_Namespace", "name": { "nodeType": "Name", "parts": [ "App", "Time" ], "attributes": { "startLine": 2, "endLine": 2 } }, "stmts": [{ "nodeType": "Stmt_Class", "flags": 0, "extends": null, "implements": [], "name": { "nodeType": "Identifier", "name": "Clock", "attributes": { "startLine": 4, "endLine": 4 } }, AST: Abstract Syntax Tree PHP Vm Opcodes
  49. 49. Try this at home! Tokenizer: token_get_all() Parser: PHP-Parser (https://github.com/nikic/PHP-Parser) questions on slide.do, code #phpdayPUGed
  50. 50. Try this at home! Tokenizer: token_get_all() Parser: PHP-Parser (https://github.com/nikic/PHP-Parser) Static Analisys Tool work at this level Fixers/Sniffers work at this level questions on slide.do, code #phpdayPUGed
  51. 51. Demo
  52. 52. What I found so far Available tool can be extended in a quite simple way Writing custom rules is hard questions on slide.do, code #phpdayPUGed
  53. 53. What I wish for All classes That Reside in namespace like “AppDTO” Should Have Name Ending with “Data” questions on slide.do, code #phpdayPUGed
  54. 54. What I wish for ->allClasses() That Reside in namespace like “AppDTO” Should Have Name Ending with “Data” questions on slide.do, code #phpdayPUGed
  55. 55. What I wish for ->allClasses() ->that() Reside in namespace like “AppDTO” Should Have Name Ending with “Data” questions on slide.do, code #phpdayPUGed
  56. 56. What I wish for ->allClasses() ->that() ->resideInNamespace(“AppDTO”) Should Have Name Ending with “Data” questions on slide.do, code #phpdayPUGed
  57. 57. What I wish for ->allClasses() ->that() ->resideInNamespace(“AppDTO”) ->should() Have Name Ending with “Data” questions on slide.do, code #phpdayPUGed
  58. 58. What I wish for ->allClasses() ->that() ->resideInNamespace(“AppDTO”) ->should() ->haveNameEndingWith(‘*Data’); questions on slide.do, code #phpdayPUGed
  59. 59. Thank you! Michele Orselli mo@flowing.it Michele Orselli mo@flowing.it tw: _orso_ Questions on slide.do, code #phpdayPUGed Feedback: https://joind.in/talk/baba2 Repo: https://tinyurl.com/y7482abm Meetup: https://www.meetup.com/it-IT/PUG-Romagna-PHP-User-Group-Romagnolo/

×