DaedTech

Stories about Software

By

Chess TDD 13: Moving On

In the last bunch of installments of this series, I’ve implemented methods for pieces to determine where they can move on a board and/or done some refactoring.  But I’ve ridden that train as far as I can, now having implemented all of the pieces, so it’s time to shake things up a bit.  Another thing that makes this post different is that I’m going to try a new way of structuring my test classes.

The other day, in response to a comment, I made a post about test initialize methods and Steve Smith commented and suggested an approach he described in detail in this post on his blog.  The gist of the idea is dispensing with the old stand by of having a test class for class Foo called FooTest and instead having the name of the test class describe the context of the test, BDD-style.  I found this idea immediately appealing and decided I’d try it out in “some project to be determined,” but what’s the fun in that?  Once an idea settles in my head, it’s hard for me to shake it, so instead of doing it later, I’ll do it here, now, publicly.  Apologies in advance (I’m typing this part before recording the coding) if it results in a bit more floundering, but I think it might be fun for us all to learn together.  If nothing else, you’ll get to see how easy or difficult it is to adapt to this convention.

Anyway, here is what I accomplished in this clip:

  • Got started on complete move calculation implementation.
  • Defined the setup of complete board for a lot of tests.
  • Established a new pattern for constructing tests.

And here are some lessons to take away.

  • When you are exposed to a new practice or way of doing things, there’s no time like the present.  While it may not always be practical to ram the new stuff into some time sensitive project, experiment and try it out to see how you like it.  Trying out different techniques keeps you sharp and helps you avoid falling into a rut.
  • When you haven’t looked at code in a long time, it’s easy to lose track of internal implementation of classes.  One of the real perks of TDD and having a test suite is that it’s easy to poke and experiment to see what’s going on without fear that you’re going to break something.
  • If kept concise and focused, a bit of yak-shaving in your implementations can be pretty productive.  Always be looking to improve on your code’s readability, elegance, and efficiency if you can.
  • It’s important to keep your test suite as communicative and descriptive as possible, and you should always be looking for ways to help you toward that end.

By

ChessTDD 12: Blind Alleys

This is one last post of loose ends and looking at what I’ve done so far before I move on to new functionality.  It wasn’t necessarily my finest hour as a programmer and TDD practitioner, but I’m including the good with the bad because nobody is always on when programming.  Also, I wasn’t insanely on in terms of my audio recording either becasue my throat was a little scratchy today.  You might hear me stealing quiet sips of ice water from time to time.  Anyway, here’s what I accomplish:

  • Reworked the knight’s GetMovesFrom() method
  • A fair amount of design flailing

Here are some lessons to take away:

  • An interesting side effect of a long time spent at TDD is a tendency to look to unit tests when wanting to dive into and explore code functionality.  The reason for this is that you know the unit tests will show you how the class’s public API is being used.  So, it’s like finding the class instantiated in-situ in the code, except that in the test class, it’s going to have a bunch of methods with descriptive names telling you how things work.
  • When doing exploratory refactorings, try to keep things compiling as much as you can and check with as much granularity as possible that you’re still passing.  Some of my flailing with tuples of ints wasn’t really necessary, but I kept my eye on the tests anyway so as not to get stuck in the middle of a refactoring where tests are red, things are broken, and I don’t know how to go forward or back.
  • Check out around 9:50.  Copy and paste will always burn you.  Even when it’s tiny.  Even when you’re using TDD.
  • Sometimes you wind up in a blind alley.  That’s okay.  Go back to where things were working and tackle the problem again later.  This isn’t just punting; it’s an important skill.  You need to ship code and you can get lost in trying to perfect it if you aren’t careful.  So, let it go, think on it later — in the shower or while eating dinner or something — the answer will smack you in the forehead like a ton a bricks at some point.

By

Chess TDD 11: Tying Up Loose Ends

Now that all of the pieces are implemented, I decided to change it up a little and get rid of a few yellow items in one fell swoop. I thought it would also be a good time to
Here’s what I accomplish in this clip:

  • Move Knight into it’s own class.
  • Separated test and production into their own assemblies.
  • Got rid of the DefaultBoardSize constant that had been defined in many test classes by consolidating it into one place.
  • Went back to earlier test classes and implemented “MovesFromXX” pattern that I had settled on.

Here are some lessons to take away:

  • If Ctrl-M, O stops working (or any normal VS shortcut), it might be because some other process has claimed part or all of the sequence and is preempting Studio.  Kill processes or reboot.
  • If you have some mundane but necessary tasks (e.g. moving a bunch of classes into a new namespace), this can be a good way to “warm up” when you haven’t looked at a code base in a while.  Generally speaking, look for tasks that can ease you back into the code base while being productive.
  • Even duplication that is seemingly mundane should be avoided.  The DRY principle states that systems should have a single point of definition for all pieces of knowledge, and that includes things like database schemas, config files, and yes, even your unit test classes.  You need to maintain your unit tests, and duplication creates maintenance pain.
  • Pay attention to your test method names as you’re making changes.  These are documentation as to how your code should behave, so if you change the behavior, make sure to change the names to reflect those changes.
  • “Lean on the compiler” to help you with your refactorings.  If you’re getting rid of a bunch of references to a variable, delete the definition of the variable and the compiler will then force you to get rid of all references.  If you do it in the opposite order, you might miss references and waste time.  As a more general rule, you should always favor failing early and doing things in such a way that mistakes will result in non-compiling.
  • When you do large refactorings, it might not hurt to run all of the unit tests explicitly in the test runner instead of relying on the dots in NCrunch (or any continuous testing tool that you’re using).

By

Chess TDD 10: A Knight’s Tale

Okay, I promise, no more of these titles after this edition.  But, to make up for it, this time I actually wrote the code and did the audio in the same day, so I remember very well what I was talking about.

Here’s what I accomplish in this clip:

  • Move Queen into it’s own class.
  • Implement Knight with GetMovesFrom()

Here are some lessons to take away:

  • It’s okay to be obtuse for a while in your TDD, if doing so helps your understanding. I started with a hard-coded thing to get the first test pass and then did another for the second. Both tests would need to continue passing, and I was feeling my way through what to do. As long as you get going at some point, this is okay. Whatever helps.
  • Try to avoid getting into a routine. By getting a fresh look, I was able to define a method that I thought improved readability and aided code use. I’d written a number of things like this before, but I always try to think of new ways to approach problems, rather than settling into a routine of semi-mindless work.
  • If you’re not careful, you can get a little ahead of yourself. I was on auto-pilot and didn’t realize I wasn’t compiling for a while before I corrected myself.
  • Get it working first, and then worry about cleanup later. You can always make things more elegant later, when it’s working (at least when you do TDD).

By

TDD Chess Game Part 9: God Save the Queen

As always, it seems that I’ve let too much time elapse between iterations of this series. This time my excuse was worse than ever. I actually had this video ready to go last Friday or something and then the post was was queued up on Sunday, but I was too tired when I got home on Sunday night to remember to go publish it. Anyway, it’s live now.

Here’s what I accomplish in this clip:

  • Implement Queen with GetMovesFrom()
  • Add more common functionality to Piece base class.

Here are some lessons to take away:

  • For the most part, in the last number of clips things had gone more or less as I expected.  Here you got to see the value of the test suite indicating to me that I was reasoning about the code incorrectly.  I didn’t realize that the GetRadial methods were returning only moves N spaces away rather than up to and including N spaces.  It took some floundering to figure this out and, without red tests telling me things were going haywire, I probably would have plowed ahead for minutes or hours before I realized things weren’t working.
  • Pulling up functionality into a common base class is a way to avoid duplication and make tests go green rapidly, but beware of creating a base class abstraction that’s awkward just to reuse code.  If it seems awkward, it might be worth creating a class that your ancestors use.  So far, the functionality in Piece seems to make sense, but I’ll keep an eye on this.
  • Use Intellisense in a savvy way.  When you notice a few times that what you’re expecting to happen isn’t happening, that’s a yellow (if not red) flag.  Late in the video, this kept happening to me, and it turned out to be because I had spelled “radial” as “raidal” when defining a method.  Typos, incorrect assumptions, etc — often these things can be revealed by the IDE not behaving as expected.
  • Definitely keep track of refactorings you’d like to do in you list.  Treat these as if they were no different than features you want implemented.