DaedTech

Stories about Software

By

Chess TDD 40: Diagonal Capture for Pawns

This post was the last of a series of 3 I recorded together, so it picks up right on the heels of episode 39 from a flow perspective.  I initially tied up loose ends from the previous episode and then got the pawn’s diagonal capture in place, at least for the white pawns (acceptance tests for black pawns won’t go well right now).  Fits and starts, but real progress nonetheless.

What I accomplish in this clip:

  • Finished the TDD implementation for IsCaptureAllowed
  • Implemented IsNonCaptureAllowed
  • Finally gave pawn diagonal capture ability

Here are some lessons to take away:

  • Always look to refactor test code when it comes to readability and eliminating duplication.  These refactorings are not just for production code!
  • There’s a sizable contingent of people that don’t like seeing the Assert call factored out of unit tests.  Clearly a matter of personal preference, but you may get pushback in a shared code base.
  • In methods, preserve a consistent level of abstraction.  If you have complex two part conditional, don’t factor out one part and leave the other part — make them both conceptually similar.
  • Clean, readable code will look at least vaguely familiar to domain experts, even if they aren’t programmers.  They should see/read concepts that are familiar.
  • Keeping the lines of code low in a class isn’t a first class or all-encompassing goal.  A class can get ugly by having too many methods, even if all of those methods are small.

By

Chess TDD 39: Dipping a Toe into Complex Piece Movement

What I accomplish in this clip:

  • Finished implementing the bishop acceptance tests.
  • Introduced the concept of “capture move” and “non-capture move” to piece movement.
  • Made some good headway on the pawn’s diagonal capture capability.

Here are some lessons to take away:

  • I’ve mentioned this before in the negative a few times, but I’ll phrase it in the positive.  If you’re going to do refactorings, even trivial ones like deleting a dead method, do it with a green test suite.
  • Writing acceptance or integration tests, whether using them to drive design or not, tends to give you a good lesson in patterns of things that can go wrong.  The specific example I’m referring to here is how I noticed that movement for the black pieces from higher numbered rows to lowered number ones tended to be a problem across pieces.
  • Even if you’re not thrilled with a design, you can be productive and get things done with it when your test coverage is good since you won’t be afraid to change it later.  This helps prevent “coders’ block” or “paralysis by analysis.”
  • When you’re reasoning about implementation, allow yourself to stub out helper methods or methods on other objects that will ‘magically’ do what you want.  E.g. if I were writing a “CookDinner” method, I might just declare “TurnOnStove()” and stub it out, to be implemented later.  This practice of defining what before how can help you get toward the single responsibility principle.
  • I won’t belabor the metaphor of tech debt, but having a really high degree of test coverage and a lot of small, modular methods in the code base lets you live with tech debt a little more easily in the short term.  With a lot of crufty code around the problematic code, you’ll never want to touch anything when it comes time to pay it off.  With lots of coverage and good code elsewhere, getting rid of the tech debt at a time that suits you is easier.

By

ChessTDD 38: Bishop Tests and Being Wrong about Being Wrong

For this episode, I did something a bit different.  I actually recorded the coding for this and then two more episodes on its heels.  If you’re following along on github, you’d notice that I’ve checked in code for episode 40, though I still need to do the audio for those next two episodes.  In this particular episode, I get off to a nice start with testing for bishop and then get a bit derailed.  Luckily (spoiler alert), I get it straightened out in next episode.  And, for all 3 of these, I successfully kept to right around 20 minutes.

What I accomplish in these clips:

  • Implement part of the acceptance tests for bishop.

Here are some lessons to take away:

  • I find a lot of benefit in stripping everything but what I need in default templates I’m provided (e.g. the spec flow feature file, an web.config file, etc).  I prefer to be as deliberate as possible about everything that goes into the software work product.
  • No matter what you’re doing, if you do it brainlessly, it won’t go well.  I avoided copy and paste to avoid brainless mistakes, and just wound up brainlessly typing in the wrong thing by hand.
  • TDD lets you poke at and test the code to see if you can get to green (or red) without fully understanding what you’re doing, but if you do this, make absolutely sure you spend time immediately afterward writing tests or reasoning about the code so that you do understand it.
  • You almost certainly won’t stop yourself from making stupid mistakes, but you can develop techniques for discovering them more quickly and reducing their impact scope.

By

ChessTDD 36: Acceptance Tests for Queen Movement

This episode went smoothly until I discovered a bug.  Philosophically, I suppose this is the natural state of software development.  For my purposes here, though, hunting down the bug caused the episode to balloon to 26 minutes, so I’m going to try a new thing so as to keep the videos a reasonable length of time.  I’m splitting it into 2 videos: parts A and B.  Please let me know if this approach is preferable to sometimes having long videos or not; if you leave feedback, I’ll more likely do it the way you prefer, since I’m just trying to go with what people like.

What I accomplish in these clips:

  • Created a couple of code snippets in CodeRush to get rid of the hand typing in the specflow scenarios.
  • Wrote acceptance tests for the queen’s movement.
  • Squashed a subtle bug (or at least half of one).

Here are some lessons to take away:

  • Projects go better when there are more eyeballs on them.  Run things you’re doing by other people and see if they have suggestions that might help.  They may think of things that never would have occurred to you and might later seem obvious.
  • Whenever you make mistakes copying and pasting, it’s a crapshoot whether fixing them takes more time than you would have spent hand-typing or not.  In my experience, most of the time you don’t come out on the winning end, and wholesale copy-paste obscures your understanding.  This is why I try to avoid the practice.
  • What I find is that unit tests should be very directed and specific about system behaviors.  But acceptance tests let you put on your exploratory testing hat, dreaming up scenarios in which users might use this thing that could potentially break it.  For you unit testing newbies, fight the urge to write unit tests with lots of assertions that cover a lot of ground.  You can express that in your acceptance tests.
  • Once again, don’t do low-hanging fruit refactorings (e.g. deleting dead code) when you have red tests.  It might seem like it’s not a problem, but it will come back to haunt you at some point.
  • Another example in this episode of finding a bug with a failing acceptance test, and drilling in to get closer by writing failing unit tests.  This is an excellent and helpful practice.
  • TDD facilitates Eureka moments where you try something you think might work and you see all of your tests go green.  However, just like trying something in your code and seeing the application magically behave correctly next time you run it, it’s important to cement your understanding of why it worked.  Don’t program by coincidence, even if you have a green test suite backing you.  Keep writing tests and/or reasoning about the code until you’re sure you understand what’s happening.  (Writing tests provides an excellent way to prove your understanding to yourself).

By

ChessTDD 35: Acceptance Tests for Knight Movement

Things are really starting to flow with the acceptance tests now. In this episode, not only did I mercifully not uncover any important bugs, but I defined knight movement in acceptance tests in a way that I feel pretty good about. I’m learning as I go about using SpecFlow, which is cool, and as the cherry on the sundae, I actually got episode length back under control with a 17 minute episode.

 

What I accomplish in this clip:

  • Fixed the poor naming I left off with last time.
  • Wrote acceptance tests for the knight’s movement.

Here are some lessons to take away:

  • Naming is so, so, so important.  It may seem like a trivial thing, but leaving a method about chess piece movement where “origin” and “destination” were reversed would, sooner or later, cause someone a serious headache.  It would also probably make them hate me when they looked at the history.  Make sure your names are good.
  • You have to do a fair bit of fumbling when you’re figuring out a new tool/tech/framework on the fly.  Stick to your principles and be sensitive to the idea that there’s probably a better way to do a lot of the things that you’re trying to do.  Ask people, and read a lot if you can.
  • There’s a lot of out of the box stuff that comes when I make a SpecFlow feature, but I just get rid of it.  For me, it’s helpful to eliminate everything that I’m not using so as not to be confused about what’s mandatory and what isn’t and also not to be confused later about what functionality I’m even using.
  • An interesting tradeoff emerges in my use of SpecFlow.  Duplication is, by and large, pretty bad in a code base.  But, in the case of visualization, showing the chess board for each individual acceptance test may be helpful in that it makes it crystal clear what’s going on in each test.  There are probably various strategies to try optimizing for minimized duplication and maximized visualization simultaneously, but it’s worth bearing in mind that everything in software development is a matter of tradeoffs and it’s best to be deliberate about whatever choice you make.