DaedTech

Stories about Software

By

Chess TDD 19: DoesPieceExistAt and Housekeeping

Another night in the hotel, another episode of ChessTDD.  I’m doing my day to day work mainly in Java-land these days, so this is about the only time I write .NET code anymore.  Anywho, in this episode, I’m just planning to pick some housekeeping cards and move them across, starting with one I created after receiving an astute observation from Jeff in the comments from last episode.

Here’s what I accomplished in this clip:

  • Fixed a subtle bit of weirdness that may have caused future problems.
  • Cleaned up the screwy logic around default board size.
  • Factored the test classes more toward the new naming paradigm.
  • Implemented a DoesPieceExistAt() method to get away from GetPiece() == null

Here are lessons to take away:

  • This is kind of a combined lesson from last time to this time.  The comment I received and my resulting attention to the issue he pointed out is an excellent example of why pair programming (or at least code review) is full of win.  I may or may not have caught that logic error before shipping this thing to (an imaginary) QA or production, but with that review, it’s at the fore and I can do something about it.
  • “Boy Scouting” isn’t just about improving production code.  It applies to anything, including your tests.  Wholesale, quixotic refactoring efforts are not necessary if you’re constantly improving the code a little bit in the areas that you’re touching anyway.  In other words, you needn’t always go out of your way to refactor — it’s often advisable to wait to touch production code until you’ll be in there anyway.
  • I like to default to immutability whenever possible.  In the case of board size, why make that a settable property?  How often does it come up that you want to change the size of a chessboard that already exists with scissors or tape and cardboard?  (Modeling the physical world just makes for a funny mnemonic — faithfully modeling it isn’t actually that important.)  Seriously, what advantage is there to that being mutable. In my book, none.  You want a different board size, make a new board.  Not having board size be mutable makes your life much easier — no reasoning about what happens if you shrink the board when pieces are on it and other things like that.
  • Class level preconditions passed into a constructor are important to guard against.  Don’t let your consumers pass you things that would render you in a nonsensical state, such as accepting negative 1 as a board size.  When this happens, fail quickly, loudly, and visibly with an exception, and make it clear why and how in your tests.

By

ChessTDD 18: RemovePiece and Housekeeping

In this episode, I managed to pry myself away at a slightly shorter length of recording time.  You can seem me at the end wavering and and wanting to continue, but I know myself, and I’d have been hustling to wrap up under 25 minutes next thing I knew, so I thought I’d call it at a reasonable stopping point.

Here’s what I accomplished in this clip:

  • Implemented RemovePiece.
  • Made the public interface of Board a little nicer.
  • Minimized the usage of the array in favor of readable abstractions.

Here are lessons to take away:

  • Make yourself feel the pain of duplication.  Around 3:15 I fought off the temptation to copy and paste the setup of another test class to the new one, but I retyped it instead.  Copy and paste is like taking morphine and then walking on lava — you’re easing your pain when you should be letting it inform your actions to improve the situation.
  • Having identical setup in multiple classes is a test smell that’s making subtle suggestions.  Maybe the tests should be in a single class or, perhaps, there should be something in production code making that setup easy, if it’s really that common.  (I view the alternative, a lot of helper code in tests, not to be a better option).
  • At around 7:20, I did something subtle.  I looked for references to Board’s _pieces array and looked to eliminate as many references to it as possible.  The idea here is to minimize the use of a primitive abstractions in favor of the more descriptive ones I’ve created (GetPiece, RemovePiece, MovePiece).
  • More compact isn’t always better.  If you inline a variable, check for readability.  The beauty of a robust test suite is that you can really whip things around to maximize readability and feel good that you’re not breaking anything.

By

Chess TDD 17: Implementing Piece Movement

In this episode, I switched gears a bit to focus on the comparably easy task of moving pieces. I’d had enough of wanting to move pieces for setup, so it was time to take care of that.  I also might (will at some point) revisit the test classes and perhaps consolidate to always starting with the normal board and adding/removing as needed for setup.

Here’s what I accomplished in this clip:

  • Renamed that method from last time.
  • Added basic implementation of move.
  • Added a bit of parameter checking for move.

Here are lessons to take away:

  • Simplicity isn’t just for “do the simplest thing to make it pass.”  It applies on the test side as well.  I started to implement MovePiece() by moving a piece two squares away, but moving it one square away is sort of a simpler case, so it’s probably better to do that first.  The same kind of logic doing, say, prime factors.  Start with 2 — don’t start with 2497.
  • When deciding what test to write next, imagine how you might break up the work that needs to be done in terms of decomposition.  When I was writing MovePiece(), I thought, “move piece means delete a piece from origin and add a piece to destination, so I’ll write a test that accounts for one of those things only: piece exists at destination.”  MovePiece() may seem simple, but it’s decomposable, so let that guide your testing effort.
  • If you think of a refactoring for the test method while you’re writing it, just keep writing the test.  Go red then make it green, then do whatever you’re thinking in the refactor phase.  Having a half-written test is no time to start refactoring.
  • TDD makes you the first consumer of your API.  View your API through someone else’s eyes and use that to make your code better.  I discovered that I could accomplish RemovePiece(Coordinate) by calling the existing method AddPiece(null, coordinate).  But that’s weird and awkward from a semantics perspective.  What strikes you as awkward as you’re coding will strike your consumers as confusing, maddening, or horrifying.  Don’t put them through this.

By

Chess TDD 16: Finishing Bishop Blocking

Once again I’m bringing you this code-cast from a Marriott, albeit a different one. In spite of a bizarre amount of noise over the course of the evening for a business hotel, I’ve managed to get at least passingly decent audio for this (and for some ongoing Pluralsight work as well). This is a pretty workmanlike episode where I dive into the refactoring I didn’t have time for last weekend and then use the resultant code to make my life easier as I finish the bishop implementation.

Also, as a quick aside, someone asked me a little while back for some advice about how I approach integration/system testing, and I was thinking I might just plow through this series to demonstrate where and how I’ll start bringing in broader tests. So, stay tuned for that, probably whenever the blocking implementation is finished.

Here’s what I accomplished in this clip:

  • Refactored a seriously bad piece of code for diagonal blocking.
  • Fleshed out the diagnoal blocking to handle all cases.
  • Satisfied myself that diagonal blocking is reasonably robust.

Here are lessons to take away:

  • If you’re not sure what to name a method that you’re pulling out, don’t interrupt your flow by obsessing over what to call it.  Naming is extremely important and you definitely want to come back to it, so just call it something like “Dunno()” and focus on the refactoring for the time being.  That silly, glaring name will prevent you from forgetting to come back and think through the name when you understand better what you want to do.
  • Oops.  Didn’t pay close enough attention to my little NCrunch notifier going red during a refactoring.  When that happens, don’t say, “uh oh” and go trying to fix the problem.  Start hitting undo until you’re green again.
  • Whenever something you want to do to the code strikes you, hurry over to Trello (or Excel or whatever) and add it.  TDD makes it easy to pick up where you left off, but you’ll often forget about stuff you want to do if you wait to note it.
  • If you’re not totally comfortable with your implementation, it’s perfectly fine to write a test that you expect (okay, maybe hope) will go green and then move on, more confident, when it does.  TDD discipline says that to change the behavior of production code you need a red test.  It doesn’t say that you always have to write tests expecting them to go red.  Anything that tells you more about the system or increases your confidence in it is a benefit.

By

Chess TDD 15

Prompted by comments from a few people, I’ve decided to see if I like using Trello for keeping track of the TODOs instead of Excel. Also, learning from past feedback, I’ve defaulted Trello to being really big when recording so everything is legible, and I copied everything over from Excel. Hopefully I like it as I go, but please let me know if it’s more pleasing to view as compared with the Excel spreadsheet, if it matters to you one way or the other.

Also, a meta-note. I apologize for the time between posts in the series and for the lack of posting in general, but I’ve been traveling nonstop and am pretty much living out of hotels, meaning my life is one of 3G-ish wifi and sub-optimal setups. Luckily, I’m driving everywhere and lugging my boom mic, desktop and monitors with me so I can still record in the hotel. 🙂

Here’s what I accomplish in this clip:

  • Make the “blocked” algorithm for horizontal/vertical less dumb.
  • Start the implementation for “blocked” diagonal.
  • Inadvertently create a potential solution for the problem of knight’s oddball movement.

Here are lessons to take away:

  • Even little things matter when it comes to readability.  For instance, at 0:40 I noticed that my test class name ended in should but the methods started with “returns.”  So, I took the time to fix this.  My advice is to get in the habit of avoiding sloppiness and inattention to detail at any level of code.
  • Bear in mind that changing prod code is fine while green in TDD, provided you’re not looking to introduce new behaviors.  It’s a refactoring if your goal is continue satisfying existing test cases in a different way.
  • A little before 10:00, I refactored a bit of a test while red for the sake of readability.  I shouldn’t have.  My bad.  Lesson is, no matter how much TDD you do, sometimes you flub it.
  • Sometimes a great way to get things passing when the implementation is getting hairy is to tease out a conditional that only applies to your new case and do something obtuse.  Use with discretion because it can lead you into blind alleys and cause problems, but there are times when getting to green can provide an aha! moment.
  • You’ll notice I refactored to a different method signature, changed some stuff around, and then refactored back.  This kind of waffling is fine.  With TDD, you’ll get used to fearlessly refactoring and slinging stuff around until you settle on something you like (or at least thing is the least bad, for now).
  • Get it working ugly now, make it pretty later.  It’s sometimes amazing how an algorithm will suddenly make itself obvious after a bit of brute forcing and futzing around.