DaedTech

Stories about Software

By

Chess TDD 30: Starting To Be Idiomatic With SpecFlow

This episode went so poorly, I thought briefly about scrapping it and starting from scratch… but that would not be true to the premise I established at the outset where I’d do this unedited, flubs and all.  Having finished with the AsciiBoardBuilder, it was time to start putting Darren Cauthon’s ideas into play.  You can read up on that here.  I sized up what he had done and, in spite of knowing very little about SpecFlow, decided that I only needed certain parts of it for my purposes.  This turned out to be a mistake as something that I thought he had just added for illustrative/cosmetic purposes was decidedly non-cosmetic, and it took me a lot of floundering to figure that out.  Now, that’s not uncommon for me, per se — I’m a “figure it out by breaking it” sort of person, but it’s not exactly the stuff of scintillating videos.

Here’s what I accomplish in this clip:

  • Got the first idiomatic SpecFlow test written in the new feature.  Barely.  And ugly.

Here are some lessons to take away:

  • When using someone else’s example as a template for learning something you don’t yet know, don’t jump the gun and start tweaking and changing things before you get the example working.  Do as I say, not as I do.
  • No matter how long you’ve been doing this, you’ll still make off by one errors and get array bounds arithmetic wrong when it’s complicated.  Improve the odds in your favor by using TDD or, by some other mechanism that you come up with, if applicable.
  • When you find yourself writing a good bit of logic in test code (meaning, you’re writing a lot of code that you aren’t test-driving), ask yourself whether you could move the logic to production or find some other way to tease it out with TDD.  You can see by my floundering here that you become decidedly less productive when you’re writing a lot of code and just hoping for the best.
  • Using NCrunch, it’s pretty easy to run quick experiments to help with my debugging.  One such example was to start hard-coding the row/column indices to see for which ones exceptions were actually generated.
  • Similarly, putting a temporary precondition assert at the top of a test method to check your assumptions can also be a big help.  This is what started me down the path of realizing my mistake with the table’s header.  I finally sanity-checked my assumption that the table had 8 rows to find that it really only had 7.

By

ChessTDD 21: False Starts and The Knight Problem

This wasn’t the most productive episode I’ve ever recorded, per se, in terms of functionality, but, hey, it’s always a learning experience to write code.  This was kind of table setting for a big, important piece of functionality: distinguishing captures from blocked moves because of friendly pieces.

Here’s what I accomplish in this clip:

  • Flesh out the non-happy path scenario for PathChecker (later renamed PathMaker)
  • Start implementing functionality for Knight on the board.

And, here are some lessons to take away:

  • If you write a test that you think should pass and it fails, it’s okay to pivot what you’re testing to gain understanding.  Improving your reasoning about the code is extremely important.
  • Thrashing can happen.  It occurred to me that GetSpacesAlongPath maybe shouldn’t return the destination piece in its collection, but that created problems for existing code.  I weighed the dependencies and what would need to change the functionality and decided clarifying the name was a better route.
  • It’s okay to write and leave tests to confirm your hypotheses.  The TDD discipline is to force yourself to change production code only in response to a failing unit test, but there’s nothing to say you can’t write green tests to confirm that the system is working as you expect.  I have no qualms about weaving this sort of thing into red-green-refactor provided that the test is one that is meaningful when left in place because it’s important to corroborate your reasoning about the code.
  • Don’t call it a day with a failing unit test.  If you’re not prepared to finish by making it green, back it out and add a todo list item.  You don’t want to start at red next time.

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 7: Cleaning up the Bishop

I bet you thought I’d forgotten this series and the video-cast leg of my burgeoning multimedia empire, but fear not, because I’m back following a long vacation, bookended by content publication announcements. I took previous feedback to heart and increased the font size of the spreadsheet as I worked, and decided to make this video a little shorter. Trending closer to the 10 minute mark than 20 is partly selfish because the 20 minute videos take an absolutely staggering amount of time to produce in my video editing software, but I also think it might be more consumable this way. So, here’s what I accomplish:

  • Extended test coverage on Bishop.GetMovesFrom() a bit.
  • Cleaned up Bishop.GetMovesFrom().
  • Moved Bishop to its own file.

And here are lessons to take away:

  • It’s fun to be cute with your todo list, but the effect wears off after a break — better perhaps to keep it simple and descriptive.
  • When you see duplication or repetition of patterns, ask yourself what’s the variable or variables in the repetition and see if you can parameterize it for an extracted method.
  • Use the refactor phase to ask yourself, “how would this method read to someone who’d never seen this code before,” and to focus on how to make it clearer.
  • This is pretty heavy on personal opinion, but I think favoring declarative (functional, Linq-y stuff) over imperative (loops and control flow) semantics promotes readability.