• Save
Bowling: An emergent design case study
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share

Bowling: An emergent design case study

  • 1,364 views
Uploaded on

A case study of evolutionary design, based on the Bowling Kata problem. ...

A case study of evolutionary design, based on the Bowling Kata problem.

by Fernando Cuenca, Agile Coach
fcuenca@teksystems.com

blog: http://opinionateddevelopment.blogspot.ca/
twiter: @fer_cuenca

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
    Be the first to like this
No Downloads

Views

Total Views
1,364
On Slideshare
1,364
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
0
Comments
0
Likes
0

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide
  • It would be nice if each Frame knew its “score” and we could just calculate the total score by adding individual scores.Hunch: we will need some sort of “double-dispatch” solution to handle the conditional logic in score calculation.
  • The implementations of the plus() method in Strike, Spare and TotalScore need to “reach inside” OpenFrame to calculate the score. This “Feature Envy” suggests that the calculation is misplaced and really belongs in OpenFrame. It seems to confirm the earlier hunch that double-dispatch would clean this up.
  • At this point, the design supports {OpenFrames, Spares,Strikes} followed by OpenFrames only. All the scoring functionality to do that resides only in OpenFrame.We’ll need to support more combinations, but before that we need to solve other problem: how will we know what’s the score so far after a sequence of frames has been played? We introduce then the concept of “running total” in the next iteration. (Design element found through a testability concern)
  • runningTotal() method added to Score base class and implemented in subclasses. At this point, the implementation diverges in OpenFrame, so it couldn’t be generalized. This suggests a form of “Shotgun Surgery”, but there isn’t an evident way to clean it up yet, so it stays (for now.) implemented functionality to have Strikes and Spares added to a TotalScore, by implementing the corresponding addToXXXX functions. So far, the existing design holds and accommodates this new functionality.Now we can write tests for any mid-game scenario. Next step is to deal with Spare and Strike combinations.
  • The design has just kept growing mostly along the predefined lines established initially. It seems to hold so far.But:TotalScore class didn’t get implementation of most addToXXX functions. This starts to smell as a “Refused Bequest” case. And then, when we try to do two strikes in a row…
  • Passing the “multiple strikes in a row” story under the current design requires exposing the “strike sequence” concept to OpenFrame (which now needs to know not only the _sequence instance variable, but also the rules around what happens when 3 strikes are rolled in a row.)This indicates something is missing, and the design needs to change.
  • The design needs to change… but how to proceed? Started with the first obvious step (cleaning up the ugly hack) Other refactoring steps used for clarification or to better expose duplication, More tests were added, to introduce new functionality All this done in the hopes of making easier to see how a solution could emerge
  • Introducing the concept of “Score with Bonus” simplified OpenFrame by removing duplication on the handling of Spares and Strikes.TotalScore removed as it became redundant. Names changed to clarify intent better: runningTotal -> totalScoreSoFar, addToXXX -> afterXXXX Running Total functionality moved to base class. Scores are now associated with a FrameSome oddities:OpenFrame still includes firstRoll, secondRoll (Duplication with it’s contained Frame) <> relationship between Frame and Score subclasses is bidirectional Strike actually requires “fake” frames: new Frame(10, 10)OpenFrame doesn’t really need frameScoreWithBonus (another Refused Bequest)
  • All stories implemented, and all test passing! DONE?Oddities: Two classes need to know how to classify Frames into Strikes (Shotgun Surgery) (The same) Two classes create Score instances Frame class doesn’t do much (Lazy Class)Refused Bequest in Score hierarchy still unresolved
  • Original Frame class repurposed as Rolls Original Score class repurposed as Frame Now the BowlingGame class is responsible for classifying frames; Frame subclasses responsible for scoring rules

Transcript

  • 1. Scoring BowlingAn Emergent Design Case Study (I)
  • 2. Fernando A. CuencaAgile Coachfcuenca@teksystems.comhttp://opinionateddevelopment.blogspot.ca@fer_cuencaBlogTwitterAbout me
  • 3. Where to find the codehttps://github.com/fcuenca/JavaPlayground/tree/master/JavaKatas/tags/bowlingKata
  • 4. Slide 4Scoring Bowling: The RulesThe game consists of 10 frames as shown above. In each frame the player hastwo opportunities to knock down 10 pins. The score for the frame is the totalnumber of pins knocked down, plus bonuses for strikes and spares.A spare is when the player knocks down all 10 pins in two tries. The bonus forthat frame is the number of pins knocked down by the next roll. So in frame 3above, the score is 10 (the total number knocked down) plus a bonus of 5 (thenumber of pins knocked down on the next roll.)A strike is when the player knocks down all 10 pins on his first try. The bonusfor that frame is the value of the next two balls rolled.In the tenth frame a player who rolls a spare or strike is allowed to roll the extraballs to complete the frame. However no more than three balls can be rolled intenth frame.From the original “Bowling Kata”, by Robert “Uncle Bob” Martinhttp://butunclebob.com/ArticleS.UncleBob.TheBowlingGameKata
  • 5. Slide 5Epics & Initial Design idea Open Frames are scored by adding the number of pins knocked down in two rolls Spares have score of 10 plus a bonus equal to the number of pins knocked down in the next roll Strikes have a score of 10 plus a bonus equal to the number of pins knocked down in the next two rolls The last frame is allowed to have additional rolls to complete the scoring (up to 3 rolls.)
  • 6. Slide 6Iteration 1 Stories: Knocking down less than 10 pins in two tries gives an Open Frame Knocking down 10 pins in two tries gives a Spare Knocking down 10 pins in one try gives a Strike Open Frames are scored by adding the number of pins knocked down Spares followed by Open Frame add the first roll as bonus Strikes followed by Open Frame add the next two rolls as bonusIteration goal:Implement basic scoring rules
  • 7. Slide 7The Design (so far…)(Step 1)
  • 8. Slide 8Refactoring towards double-dispatch design(Steps 2, 3)
  • 9. Slide 9Iteration 2 Stories: Running total for open frames is the sum of rolls Strikes and Spares don’t change running total if they are the last frame played Strikes and Spares can be scored if followed by an Open FrameIteration goal:Report the “score so far” during the game.
  • 10. Slide 10The Design (so far…)(Step 4)
  • 11. Slide 11Iteration 3 Stories: Multiple Spares in a row Multiple Strikes in a row Strikes and Spares combinedIteration Goal:Support strikes and spares in multiple combinations
  • 12. Slide 12The Design (so far…)(Steps 5 - 9 )
  • 13. Slide 13The Design leads to an ugly hack…(Step 10)
  • 14. Slide 14The sequence of refactoringsStep 11, 12•Cleaned up ugly hack•Moved bonus scoring functionality to StrikeStep 13•Names changed for clarityStep 14•New functionality: “Spare followed by Strike” exposes more duplicationStep 15•Refactoring to expose duplicationStep 16•New Story: “Spares not scored if incomplete”Step 17, 18•Code rearranged to expose similaritiesStep 19•Removed duplication by pulling up Running TotalStep 20, 21•TotalScore class removedStep 22•Names changed for clarityStep 23•Bonus scoring functions refactored
  • 15. Slide 15The (refined) Design (so far … )(Steps 10 – 24)
  • 16. Slide 16Iteration 4 Stories: Game is a sequence of rolls Game can detect Strikes and Spares Game doesn’t confuse Spare (0,10) with a Strike Game doesn’t score incomplete frames Last frame is special (up to 3 rolls)Iteration Goal:Ability to score complete games
  • 17. Slide 17The Design (so far…)(Steps 25 – 29)
  • 18. Slide 18The Design (so far…)(Steps 30 – 34)
  • 19. Slide 19From original concept to final detailed design
  • 20. Slide 20The Story of an Evolving DesignStep 1• Basic scoring rules• Scores can be addedStep 2, 3• Refactoring towards double-dispatchStep 4• Scoring frames mid-game• Running total concept introducedStep 5• Strikes and Spares in combinations• Spares are hard-codedStep 6• Removed hard-coded rolls in SparesStep 7• Sequences of StrikesStep 8, 9• Re-ordered tests to “tell the story” betterStep 10• 2 strikes in a row lead to a “very ugly hack”TTTTT
  • 21. Slide 21The Story of an Evolving DesignStep 11, 12•Cleaned up ugly hack•Moved bonus scoring functionality to StrikeStep 13•Names changed for clarityStep 14•New functionality: “Spare followed by Strike” exposes more duplicationStep 15•Refactoring to expose duplicationStep 16•New Story: “Spares not scored if incomplete”Step 17, 18•Code rearranged to expose similaritiesStep 19•Removed duplication by pulling up Running TotalStep 20, 21•TotalScore class removedStep 22•Names changed for clarityStep 23•Bonus scoring functions refactoredTT
  • 22. Slide 22The Story of an Evolving DesignStep 24•Exposing duplication in scoring functions related to bonusesStep 25•Game class introducedStep 26•Replaced scoring algorithm in GameStep 27•Integration tests added to try out multiple end-to-end scenarios•Missing feature detected, it can pass with ugly hackStep 28•New class introduced to handle last frame special caseStep 29•Commented out test reintroduced•More functional tests addedStep 30•Score creation moved to GameStep 31•Frame repurposed as TurnStep 32•Score refactored in preparation to be turned into FrameStep 33•Score repurposed as FrameStep 34•Minor refactoringTTTT
  • 23. Slide 23