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.

4Developers 2015: Jak (w końcu) zacząć pracować z DDD wykorzystując BDD - Kacper Gunia

272 views

Published on

Kacper Gunia

Language: Polish

Techniki stosowane w Domain-Driven Design umożliwiają modelowanie złożonych aplikacji, jednak wymagają odpowiedniego podejścia do analizy problemu. Jak w takim razie mając dostęp do Ekspertów domenowych zrobić z nich dobry użytek, wykorzystując posiadane zasoby? Czy istnieją w świecie PHP narzędzia, które mogą nam w tym pomóc?

W prezentacji wprowadzę Was do “Modelling by Example” - nowego podejścia do Behaviour-Driven Development i pokażę jak wykorzystać je do efektywnego modelowania aplikacji. Posłużymy się przy tym dobrze znanymi narzędziami takimi jak Gherkin oraz Behat, które z założenia wspierają komunikację w projekcie. Ale czy tylko? Jak się okazuje, spojrzenie na nie z trochę innej perspektywy (omówione zostanie na przykładach), umożliwia również efektywne modelowanie Domeny aplikacji zgodnie z podejściem stosowanym w DDD.

Published in: Software
  • Be the first to comment

4Developers 2015: Jak (w końcu) zacząć pracować z DDD wykorzystując BDD - Kacper Gunia

  1. 1. Howto(finally)startdoing DDDbyusingBDD
  2. 2. KacperGunia@cakper So!ware Engineer @SensioLabsUK / @Inviqa PHPers Silesia @PHPersPL
  3. 3. WhatisBDD?
  4. 4. Bug-driven Development;)
  5. 5. Behaviour-driven development is about implementing an application by describing its behaviour from the perspective of its stakeholders. -- Dan North
  6. 6. BDD is about establishing a shared understanding of “done” working from the outside in until you get there -- Dan North
  7. 7. BDDshowsyouwhattodonext akaTechnicalDiscipline
  8. 8. HowdoweBDD?
  9. 9. Feature: Traveler searches for cheap itineraries In order to save money while travelling As a world traveler I want to search for the cheapest itinerary
  10. 10. Productownerwritesscenario anddeveloperautomatesit
  11. 11. Developerwritesscenario andthenautomatesit
  12. 12. No!
  13. 13. BDDisaboutcommunication! flickr.com/photos/dvids/5638829762
  14. 14. Scenario: Successfully find cheapest direct flight Given the flight from "WAW" to "LHR" priced $30 was scheduled And the flight from "WAW" to "LHR" priced $50 was scheduled When I open the "/search" page And I fill "WAW" in the "Departure airport" field And I fill "LHR" in the "Destination airport" field And I click "Search" Then I should be redirected to "/results" page And I should see $30 in the "#cheapest-flight-price" block
  15. 15. Scenario: Successfully find cheapest direct flight Given the flight from "WAW" to "LHR" priced $30 was scheduled And the flight from "WAW" to "LHR" priced $50 was scheduled When I open the "/search" page And I fill "WAW" in the "Departure airport" field And I fill "LHR" in the "Destination airport" field And I click "Search" Then I should be redirected to "/results" page And I should see $30 in the "#cheapest-flight-price" block
  16. 16. Translation
  17. 17. Canwedobetter?
  18. 18. MissionaccomplishedBoys Wecangohomenow! flickr.com/photos/dvids/5638829762
  19. 19. Translationagain
  20. 20. Howtofixthat?
  21. 21. DDD
  22. 22. WhatisDDDabout?
  23. 23. It’s about focusing on the domain and letting it affect the so"ware very much -- Jimmy Nilsson
  24. 24. ButWHYdoweneedit?
  25. 25. Everybodyknowsthejargon intheirOWNFIELD
  26. 26. It'saboutcommon understanding
  27. 27. Ubiquitouslanguage
  28. 28. Concrete examples are rooted in the problem domain -- Matt Wynne
  29. 29. DomainModel
  30. 30. A domain model (...) is not just the knowledge in a domain expert’s head; it is a rigorously organized and selective abstraction of that knowledge -- Eric Evans
  31. 31. Modeldocuments theknowledge
  32. 32. Pushing for ubiquitous language hard enough makes your examples a domain model -- Konstantin Kudryashov
  33. 33. Scenario: Successfully find cheapest direct flight Given the flight from "WAW" to "LHR" priced $30 was scheduled And the flight from "WAW" to "LHR" priced $50 was scheduled When I open the "/search" page And I fill "WAW" in the "Departure airport" field And I fill "LHR" in the "Destination airport" field And I click "Search" Then I should be redirected to "/results" page And I should see $30 in the "#cheapest-flight-price" block
  34. 34. Scenario: Successfully find cheapest direct itinerary Given the search for the itinerary schedule And the itinerary from "WAW" to "LHR" priced $30 was planned in the schedule And the itinerary from "WAW" to "LHR" priced $50 was planned in the schedule When I search for cheapest itinerary from "WAW" to "LHR" Then the cheapest itinerary should cost $30
  35. 35. Modellingbyexample
  36. 36. Phase1
  37. 37. Scenario: Successfully find cheapest direct itinerary Given the search for the itinerary schedule And the itinerary from "WAW" to "LHR" priced $30 was planned in the schedule And the itinerary from "WAW" to "LHR" priced $50 was planned in the schedule When I search for cheapest itinerary from "WAW" to "LHR" Then the cheapest itinerary should cost $30
  38. 38. Given the search for the itinerary schedule /** * @Given /^the search for the itinerary schedule$/ */ public function theSearchForTheItinerarySchedule() { $this->itinerarySchedule = new ItinerarySchedule(); $this->search = new Search($this->itinerarySchedule); }
  39. 39. Designemerges
  40. 40. And the itinerary from "WAW" to "LHR" priced $30 was planned in the schedule /** * @Given the itinerary from :fromAirport to :toAirport * priced $:price was planned in the schedule */ public function theItineraryFromToPricedWasPlannedInTheSchedule( $fromAirport, $toAirport, $price ) { $itinerary = new Itinerary( Airport::code($fromAirport), Airport::code($toAirport), Money::usd($price) ); $this->itinerarySchedule->plan($itinerary); }
  41. 41. When I search for cheapest itinerary from "WAW" to "LHR" /** * @When I search for cheapest itinerary from :fromAirport to :toAirport */ public function iSearchForCheapestItineraryFromTo($fromAirport, $toAirport) { $this->cheapestItinerary = $this->search->forCheapest( Airport::code($fromAirport), Airport::code($toAirport) ); }
  42. 42. Then the cheapest itinerary should cost $30 /** * @Then the cheapest itinerary should cost $:price */ public function theCheapestItineraryShouldCost($price) { expect($this->cheapestItinerary->cost())->toBeLike(Money::usd($price)); }
  43. 43. Phase2
  44. 44. @ui Scenario: Successfully find cheapest direct itinerary Given the search for the itinerary schedule And the itinerary from "WAW" to "LHR" priced $30 was planned in the schedule And the itinerary from "WAW" to "LHR" priced $50 was planned in the schedule When I search for cheapest itinerary from "WAW" to "LHR" Then the cheapest itinerary should cost $30
  45. 45. Given the search for the itinerary schedule /** * @Given the search for the itinerary schedule */ public function theSearchForTheItinerarySchedule() { $this->visit("/search"); }
  46. 46. And the itinerary from "WAW" to "LHR" priced $30 was planned in the schedule /** * @Given the itinerary from :fromAirport to :toAirport * priced $:price was planned in the schedule */ public function theItineraryFromToPricedWasPlannedInTheSchedule( $fromAirport, $toAirport, $price ) { $itinerary = new Itinerary( Airport::code($fromAirport), Airport::code($toAirport), Money::usd($price) ); $this->get("itinerary_schedule")->plan($itinerary); }
  47. 47. When I search for cheapest itinerary from "WAW" to "LHR" /** * @When I search for cheapest itinerary from :fromAirport to :toAirport */ public function iSearchForCheapestItineraryFromTo($fromAirport, $toAirport) { $this->fillIn("#from-airport", $fromAirport); $this->fillIn("#to-airport", $toAirport); $this->clickButton("Search"); }
  48. 48. Then the cheapest itinerary should cost $30 /** * @Then the cheapest itinerary should cost $:price */ public function theCheapestItineraryShouldCost($price) { $cheapestItinerary = $this->find("#cheapest-itinerary"); expect($cheapestItinerary)->toContainText(sprintf("From $%s", $price)); }
  49. 49. # behat.yml default: suites: domain: contexts: [ SearchContext ] ui: contexts: [ WebSearchContext ] filters: { tags: '@ui' }
  50. 50. ModellingbyExample Inthree(easy)steps
  51. 51. · Have the conversation · Model your objects · Go again through UI*
  52. 52. *But
  53. 53. You(really)don't havetoautomate everything!
  54. 54. Butthereisa problem
  55. 55. Weignoredthedepth ofthedomain
  56. 56. Onpurpose
  57. 57. Youcan'tmodelthe wholesystemusing onefeature
  58. 58. Repeattheprocess andmodelthe planner
  59. 59. Whatifmodelhasdifferentrequirements inthiscontext?
  60. 60. BoundedContext
  61. 61. Languageislimited
  62. 62. Search Itinerary != Planner Itinerary != Booking Itinerary
  63. 63. Donotbuildfragilemonoliths!
  64. 64. Buildapplicationswith Boundedcontextinmind
  65. 65. ---Wrapup---
  66. 66. Havethe conversation
  67. 67. Donotseparatethe conceptsfromthe implementation
  68. 68. Youcannotbuild conceptualmodels withoutconsidering implementationissues
  69. 69. Pushfor Ubiquitouslanguage
  70. 70. UseBehattodriveyourModel NotonlytheUI
  71. 71. "BDDisabout conversationsyouhaveto producesoftware"
  72. 72. "DDDisabouthowyou exploredomainmodels andhowyouarticulatethis"
  73. 73. Thanks! @cakper

×