How to (finally) start doing DDD by using BDD
Transcript
- 1. Howto(finally)startdoing DDDbyusingBDD
- 2. KacperGunia@cakper So!ware Engineer @SensioLabsUK / @Inviqa PHPers Silesia @PHPersPL
- 3. WhatisBDD?
- 4. Bug-driven Development;)
- 5. Behaviour-driven development is about implementing an application by describing its behaviour from the perspective of its stakeholders. -- Dan North
- 6. BDD is about establishing a shared understanding of “done” working from the outside in until you get there -- Dan North
- 7. BDDshowsyouwhattodonext akaTechnicalDiscipline
- 8. HowdoweBDD?
- 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. Productownerwritesscenario anddeveloperautomatesit
- 11. Developerwritesscenario andthenautomatesit
- 12. No!
- 13. BDDisaboutcommunication! flickr.com/photos/dvids/5638829762
- 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. 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. Translation
- 17. Canwedobetter?
- 18. MissionaccomplishedBoys Wecangohomenow! flickr.com/photos/dvids/5638829762
- 19. Translationagain
- 20. Howtofixthat?
- 21. DDD
- 22. WhatisDDDabout?
- 23. It’s about focusing on the domain and letting it affect the so"ware very much -- Jimmy Nilsson
- 24. ButWHYdoweneedit?
- 25. Everybodyknowsthejargon intheirOWNFIELD
- 26. It'saboutcommon understanding
- 27. Ubiquitouslanguage
- 28. Concrete examples are rooted in the problem domain -- Matt Wynne
- 29. DomainModel
- 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. Modeldocuments theknowledge
- 32. Pushing for ubiquitous language hard enough makes your examples a domain model -- Konstantin Kudryashov
- 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. 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. Modellingbyexample
- 36. Phase1
- 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. 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. Designemerges
- 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. 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. 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. Phase2
- 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. Given the search for the itinerary schedule /** * @Given the search for the itinerary schedule */ public function theSearchForTheItinerarySchedule() { $this->visit("/search"); }
- 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. 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. 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. # behat.yml default: suites: domain: contexts: [ SearchContext ] ui: contexts: [ WebSearchContext ] filters: { tags: '@ui' }
- 50. ModellingbyExample Inthree(easy)steps
- 51. · Have the conversation · Model your objects · Go again through UI*
- 52. *But
- 53. You(really)don't havetoautomate everything!
- 54. Butthereisa problem
- 55. Weignoredthedepth ofthedomain
- 56. Onpurpose
- 57. Youcan'tmodelthe wholesystemusing onefeature
- 58. Repeattheprocess andmodelthe planner
- 59. Whatifmodelhasdifferentrequirements inthiscontext?
- 60. BoundedContext
- 61. Languageislimited
- 62. Search Itinerary != Planner Itinerary != Booking Itinerary
- 63. Donotbuildfragilemonoliths!
- 64. Buildapplicationswith Boundedcontextinmind
- 65. ---Wrapup---
- 66. Havethe conversation
- 67. Donotseparatethe conceptsfromthe implementation
- 68. Youcannotbuild conceptualmodels withoutconsidering implementationissues
- 69. Pushfor Ubiquitouslanguage
- 70. UseBehattodriveyourModel NotonlytheUI
- 71. "BDDisabout conversationsyouhaveto producesoftware"
- 72. "DDDisabouthowyou exploredomainmodels andhowyouarticulatethis"
- 73. Thanks! @cakper