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

In Defense of Test Setup Methods

This post started out as a response to a comment on this post, but it started to get rather long for that venue, so I’m making it its own post. The comment concerns my habit of pulling instantiation logic for the class under test into a common setup method executed by the test runner prior to each test. Here are the main points that I’m writing this to address:

  • Why do I dislike code duplication in tests?
  • Extracting logic to a common setup method creates performance problems.
  • The indirection in pulling part of the setup out of a test method hurts readability.

Back Story and Explanations

I wrote this post a little under two years ago. It’s germane here because I explain in it my progression from not using the setup method to doing so. For those not explicitly familiar with the concept and perhaps following along with my Chess TDD series, what I’m referring to is a common pattern (or anti-pattern, I suppose, depending on your opinion) in unit testing across many languages and frameworks. Most test runners allow you to specify a unique method that will be called before each test is run and also after each test is run. In the case of my series, using C# and MSTest, the setup happens on a per class basis. Here’s some code to clarify. First, the class under test:

public class Gravity
{
    public decimal GetVelocityAfter(int seconds)
    {
        return 9.8M * seconds;
    }
}

And, now, the plain, “before,” test class:

[TestClass]
public class GravityTest
{
    [TestMethod]
    public void GetVelocityAfter_Returns_Zero_When_Passed_Zero()
    {
        var gravity = new Gravity();

        var velocityAfterZeroSeconds = gravity.GetVelocityAfter(0);

        Assert.AreEqual(0, velocityAfterZeroSeconds);
    }

    [TestMethod]
    public void GetVelocityAfter_Returns_Nine_Point_Eight_After_1_Second()
    {
        var gravity = new Gravity();

        var velocityAfterOneSecond = gravity.GetVelocityAfter(1);

        Assert.AreEqual(9.8M, velocityAfterOneSecond);
    }

    [TestMethod]
    public void GetVelocityAfter_Returns_NinetyEight_After_10_Seconds()
    {
        var gravity = new Gravity();

        var velocityAfterTenSeconds = gravity.GetVelocityAfter(10);

        Assert.AreEqual(98, velocityAfterTenSeconds);
    }       
}

And finally, what MS Test allows me to do:

[TestClass]
public class GravityTest
{
    private Gravity _gravity;

    [TestInitialize]
    public void BeforeEachTest()
    {
        _gravity = new Gravity();
    }

    [TestMethod]
    public void GetVelocityAfter_Returns_Zero_When_Passed_Zero()
    {
        var velocityAfterZeroSeconds = _gravity.GetVelocityAfter(0);

        Assert.AreEqual(0, velocityAfterZeroSeconds);
    }

    [TestMethod]
    public void GetVelocityAfter_Returns_Nine_Point_Eight_After_1_Second()
    {
        var velocityAfterOneSecond = _gravity.GetVelocityAfter(1);

        Assert.AreEqual(9.8M, velocityAfterOneSecond);
    }

    [TestMethod]
    public void GetVelocityAfter_Returns_NinetyEight_After_10_Seconds()
    {
        var velocityAfterTenSeconds = _gravity.GetVelocityAfter(10);

        Assert.AreEqual(98, velocityAfterTenSeconds);
    }       
}

Okay, so what’s going on here? Well, the way that MS Test works is that for each test method, it creates a new instance of the test class and executes the method. So, in the case of our original gravity test class, three instances are created. There is no instance state whatsoever, so this really doesn’t matter, but nonetheless, it’s what happens. In the second version, this actually does matter. Three instances get created, and for each of those instances, the _gravity instance is initialized. The “BeforeEachTest” method, by virtue of its “TestInitialize” attribute, is invoked prior to the test method that will be executed as part of that test.

Conceptually, both pieces of code have the same effect. Three instances are created, three Gravity are instantiated, three invocations of GetVelocityAfter occur, and three asserts are executed. The difference here is that there are three gravity variables of method level scope in the first case, and one instance variable of class scope in the second case.

Okay, so why do I choose the second over the first? Well, as I explained in my old post, I didn’t, initially. For a long, long time, I preferred the first option with no test setup, but I eventually came to prefer the second. I mention this strictly to say that I’ve seen merits of both approaches and that this is actually something to which I’ve given a lot of thought. It’s not to engage the subtle but infuriating logical fallacy in which an opponent in an argument says something like “I used to think like you, but I came to realize I was wrong,” thus in one fell swoop establishing himself as more of an authority and invalidating your position without ever making so much as a single cogent point. And, in the end, it’s really a matter of personal preference.

Why I Don’t Like Duplication

So, before I move on to a bit more rigor with an explanation of how I philosophically approach structuring my unit tests, let me address the first point from the comment about why I don’t like duplication. I think perhaps the most powerful thing I can do is provide an example using this code I already have here. And this example isn’t just a “here’s something annoying that could happen,” but rather the actual reason I eventually got away from the “complete setup and teardown in each test” approach. Let’s say that I like my Gravity class, but what I don’t like is the fact that I’ve hard-coded Earth’s gravity into the GetVelocityAfter method (and, for physics buffs out there, I realize that I should, technically, use the mass of the falling object, gravitational constant, and the distance from center of mass, but that’s the benefit of being a professional programmer and not a physicist — I can fudge it). So, let’s change it to this, instead:

public class Gravity
{
    private Planet _planet;

    public Gravity(Planet planet)
    {
        _planet = planet;
    }

    public decimal GetVelocityAfter(int seconds)
    {
        return _planet.GetGravitationalFactor() * seconds;
    }
}

Now, I have some test refactoring to do. With the first approach, I have six things to do. I have to declare a new Planet instance with Earth’s specifications, and then I have to pass that to the Gravity constructor. And then, I have to do that exact same thing twice more. With the second approach, I declare the new Planet instance and add it to the Gravity constructor once and I’m done. For three tests, no big deal. But how about thirty? Ugh.

I suppose you could do some find and replace magic to make it less of a chore, but that can get surprisingly onerous as well. After all, perhaps you’ve named the instance variable different things in different places. Perhaps you’ve placed the instantiation logic in a different order or interleaving in some of your tests. These things and more can happen, and you have have an error prone chore on your hands in your tests the same way that you do in production code when you have duplicate/copy-paste logic. And, I don’t think you’d find too many people that would stump for duplication in production code as a good thing. I guess by my way of thinking, test code shouldn’t be a second class citizen.

But, again, this is a matter of taste and preference. Here’s an interesting stack overflow question that addresses the tradeoff I’m discussing here. In the accepted answer, spiv says:

Duplicated code is a smell in unit test code just as much as in other code. If you have duplicated code in tests, it makes it harder to refactor the implementation code because you have a disproportionate number of tests to update. Tests should help you refactor with confidence, rather than be a large burden that impedes your work on the code being tested.

If the duplication is in fixture set up, consider making more use of the setUp method or providing more (or more flexible) Creation Methods.

He goes on to stress that readability is important, but he takes a stance more like mine, which is a hard-line one against duplication. The highest voted answer, however, says this:

Readability is more important for tests. If a test fails, you want the problem to be obvious. The developer shouldn’t have to wade through a lot of heavily factored test code to determine exactly what failed. You don’t want your test code to become so complex that you need to write unit-test-tests.

However, eliminating duplication is usually a good thing, as long as it doesn’t obscure anything. Just make sure you don’t go past the point of diminishing returns.

In reading this, it seems that the two answers agree on the idea that readability is important and duplication is sub-optimal, but where they differ is that one seems to lean toward, “avoiding duplication is most important even if readability must suffer” and the other leans toward, “readability is most important, so if the only way to get there is duplication, then so be it.” (I’m not trying to put words in either poster’s mouth — just offering my take on their attitudes)

But I think, “why choose?” I’m of the opinion that if redundancy is aiding in readability then some kind of local maximum has been hit and its time to revisit some broader assumptions or at least some conventions. I mean why would redundant information ever be clearer? At best, I think that redundancy is an instructional device used for emphasis. I mean, think of reading a pamphlet on driving safety. It probably tells you to wear your seatbelt 20 or 30 times. This is to beat you over the head with it — not make it a better read.

So, in the end, my approach is one designed to avoid duplication without sacrificing readability. But, of course, readability is somewhat subjective, so it’s really your decision whether or not I succeed as much as it is mine. But, here’s what I do.

My Test Structure

Let’s amend the Gravity class slightly to have it use an IPlanet interface instead of a Planet and also to barf if passed a null planet (more on that shortly):

public class Gravity
{
    private IPlanet _planet;

    public Gravity(IPlanet planet)
    {
        if(planet == null)
            throw new ArgumentException("planet");

        _planet = planet;
    }

    public decimal GetVelocityAfter(int seconds)
    {
        return _planet.GetGravitationalFactor() * seconds;
    }
}

Let’s then take a look at how I would structure my test class:

[TestClass]
public class GravityTest
{
    private const decimal EarthFactor = 9.8M;
    private IPlanet Planet { get; set; }
    private Gravity Target { get; set; }

    [TestInitialize]
    public void BeforeEachTest()
    {
        Planet = Mock.Create();
        Target = new Gravity(Planet);
    }

    [TestClass]
    public class GetVelocityAfter : GravityTest
    {
        [TestMethod]
        public void Returns_Zero_When_Passed_Zero()
        {
            var velocityAfterZeroSeconds = Target.GetVelocityAfter(0);

            Assert.AreEqual(0, velocityAfterZeroSeconds);
        }

        [TestMethod]
        public void Returns_Nine_Point_Eight_After_1_Second_On_Earth()
        {
            Planet.Arrange(p => p.GetGravitationalFactor()).Returns(EarthFactor);

            var velocityAfterOneSecond = Target.GetVelocityAfter(1);

            Assert.AreEqual(9.8M, velocityAfterOneSecond);
        }

        [TestMethod]
        public void Returns_NinetyEight_After_10_Seconds_On_Earth()
        {
            Planet.Arrange(p => p.GetGravitationalFactor()).Returns(EarthFactor);

            var velocityAfterTenSeconds = Target.GetVelocityAfter(10);

            Assert.AreEqual(98, velocityAfterTenSeconds);
        }
    }
}

Alright, there’s a lot for me to comment on here, so I’ll highlight some things to pay attention to:

  • Instance of class under test is named “Target” to be clear what is being tested at all times.
  • Planet instance is just named “Planet” (rather than “MockPlanet”) because this seems to read better to me.
  • Nested class has name of method being tested (eliminates duplication and brings focus only to what it does).
  • Test initialize method does only the minimum required to create an instance that meets instance preconditions.
  • There’s not much going on in the setup method — just instantiating the class fields that any method can modify.
  • The second two test methods still have some duplication (duplicate setup).

Now that you’ve processed these, let me extrapolate a bit to my general approach to test readability:

  • The class nesting convention helps me keep test names as short as possible while retaining descriptiveness.
  • Only precondition-satisfying logic goes in the initialize method (e.g. instantiating the class under test (CUT) and passing a constructor parameter that won’t crash it)
  • Setting up state in the class under test and arranging the mock objects is left to the test methods in the context of “Given” for those asserts (e.g. in the second test method, the “Given” is “On_Earth” so it’s up to that test method to arrange the mock planet to behave like Earth).
  • I use dependency injection extensively and avoid global state like the plague, so class under test and its depdenencies are all you’ll need and all you’ll see.
  • Once you’re used to the Target/Mocks convention, it’s (in my opinion) as readable, if not more so, than a method variable. As a plus, you can always identify the CUT at a glance in my test code. To a lesser degree, this is true of mocks and constants (in C#, these have Pascal Casing)
  • I suppose (with a sigh) that I’m not quite 100% on the maturity model of eliminating duplication since I don’t currently see a duplication-eliminating alternative to setting up Earth Gravity in two of the test methods. I think it’s not appropriate to pull that into the test initialize since it isn’t universal and adding a method call would just make the duplication more terse and add needless indirection. To be clear, I think I’m failing rather than my methodology is failing — there’s probably a good approach that I simply have not yet figured out. Another important point here is that sometimes the duplication smell is less about how you structure your tests and more about which tests you write. What I mean is… is that “Returns_NineyEight_After_10_Seconds_On_Earth” test even necessary? The duplicate setup and similar outcome is, perhaps, telling me that it’s not… But, I digress.

Addressing the Original Concerns

So, after a meandering tour through my approach to unit testing, I’ll address the second and third original points, having already addressed the question of why I don’t like duplication. Regarding performance, the additional lines of code that are executed with my approach are generally quite minimal and sometimes none (such as a case where there are no constructor-injected dependencies or when every unit test needs a mock). I suspect that if you examined code bases in which I’ve written extensive tests and did a time trial of the test suite my way versus with the instantiation logic inlined into each test, the difference would not be significant. Anecdotally, I have not worked in a code base in a long, long time where test suite execution time was a problem and, even thinking back to code bases where test suite performance was a problem, this was caused by other people writing sketchy unit tests involving file I/O, web service calls, and other no-nos. It’s not to say that you couldn’t shave some time off, but I think the pickings would be pretty lean, at least with my approach of minimal setup overhead.

Regarding readability, as I’ve outlined above, I certainly take steps to address readability. Quite frankly, readability is probably the thing most frequently on my mind when I’m programming. When it comes to test readability, there’s going to be inevitable disagreement according to personal tastes. Is my “Target” and initialization convention more readable than an inline method variable also with the convention of being named “Target”? Wow — eye of the beholder. I think so because I think of the instantiation line as distracting noise. You may not, valuing the clarity of seeing the instantiation right there in the method. Truth is with something like that, what’s readable to you is probably mainly a question of what you’re used to.

But one thing that I think quite strongly about test readability is that it is most heavily tied in with compactness of the test methods. When I pick up a book about TDD or see some kind of “how to” instructional about unit tests, the tests always seem to be about three lines long or so. Arrange, act, assert. Setup, poke, verify (as I said in that old post of mine). Whatever — point is, the pattern is clear. Establish a precondition, run an experiment, measure the outcome. As the setup grows, the test’s readability diminishes very quickly. I try to create designs that are minimal, decoupled, compatible with the Single Responsibility Principle, and intuitive. When I do this, test methods tend to remain compact. Eliminating the instantiation line from every test method, to me, is another way of ruthlessly throttling the non-essential logic inside those test methods, so that what’s actually being tested holds center stage.

So, in the end, I don’t know that I’ve made a persuasive case — that’s also “eye of the beholder.” But I do feel as though I’ve done a relatively thorough job of explaining my rationale. And, my mind is always open to being changed. There was a time when I had no test setup method at all, so it’s not like it would be unfamiliar ground to return there.

By the way, if you liked this post and you're new here, check out this page as a good place to start for more content that you might enjoy.

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

Fun with ILDASM: Extension vs Static Methods

I recently had a comment on a very old blog post that led to a conversation between the commenter and me. During the conversation, I made the comment that extension methods in C# are just syntactic sugar over plain ol’ static methods. He asked me to do a post exploring this in further detail, which is what I’m doing today. However, there isn’t a ton more to explain in this regard anymore than explaining that (2 + 2) and 4 are representations of the same concept. So, I thought I’d “show, don’t tell” and, in doing so, introduce you to the useful concept of using a disassembler to allow you to examine .NET’s IL byte code.

I won’t go into a ton of detail about virtual machines and just in time compilation or anything, but I will describe just enough for the purpose of this post. When you write C# code and perform a build, the compiler turns this into what’s called “IL” (intermediate language). Java works in the same way, and its intermediate product is generally referred to as byte code. When an IL executable is executed, the .NET framework is running, and this intermediate code is compiled, on the fly, into machine code. So what you have with both .NET in Java is a 2 stage compilation process: source code to intermediate code, and intermediate code to machine code.

Where things get interesting for our purposes is that the disassembled intermediate code is legible and you can work with it, reading it or even writing it directly (which is how AOP IL-Weaving tools like Postsharp work their magic). What gets even more interesting is that all of the .NET languages (C#, VB, F#, etc) compile to the same IL code and are treated the same by the framework when compiled into machine code. This is what is meant by languages “targeting the .NET framework” — there is a compiler that resolves these languages into .NET IL. If you’ve ever wondered why it’s possible to have things like “Iron Python” that can exist in the .NET ecosystem, this is why. Someone has written code that will parse Python source code and generate .NET IL (you’ll also see this idea referred to as “Common Language Infrastructure” or CLI).

Anyway, what better way to look at the differences or lack thereof between static methods and extension methods. Let’s write them and see what the IL looks like! But, in order to do that, we need to do a little prep work first. We’re going to need easy access to a tool that can read .NET exe and dll files and produce the assembly in a readable, text-file form. So, here’s what we’re going to do.

  1. In Visual Studio, go to Tools->External Tools.
  2. Click “Add” and you will be prompted to fill out the text boxes below.
  3. Fill them out as shown here (you may have to search for ILDASM.exe, but it should be in Microsoft SDKs under Program Files (x86):ILDASM
  4. Click “Apply.”  ILDASM will now appear as a menu option in the Tools menu.

Now, let’s get to work.  I’m going to create a new project that’s as simple as can be. It’s a class library with one class called “Adder.” Here’s the code:

public static class Adder
{
    public static int AddTwoNumbers(int first, int second)
    {
        return first + second;
    }
}

Let no one accuse me of code bloat! That’s it. That’s the only class/method in the solution. So, let’s run ILDASM on it and see what happens. To do that, select “ILDASM” from the Tools menu, and it will launch a window with nothing in it. Go to “File->Open” (or Ctrl-O) and it will launch you in your project’s output directory. (This is why I had you add “$(TargetDir)” in the external tools window. Click the DLL, and you’ll be treated to a hierarchical makeup of your assembly, as shown here:

ILDASMPopulated

So, let’s see what the method looks like in IL Code (just double click it):

.method public hidebysig static int32  AddTwoNumbers(int32 first, int32 second) cil managed
{
  // Code size       9 (0x9)
  .maxstack  2
  .locals init ([0] int32 CS$1$0000)
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  ldarg.1
  IL_0003:  add
  IL_0004:  stloc.0
  IL_0005:  br.s       IL_0007
  IL_0007:  ldloc.0
  IL_0008:  ret
} // end of method Adder::AddTwoNumbers

Alright… thinking back to my days using assembly language, this looks vaguely familiar. Load the arguments into registers or something, add them, you get the gist.

So, let’s see what happens when we change the source code to use an extension method. Here’s the new code:

public static class Adder
{
    public static int AddTwoNumbers(this int first, int second)
    {
        return first + second;
    }
}

Note, the only difference is the addition of “this” before “int first.” That is what turns this into an extension method and alters the calling semantics (though you can still call extension methods the same way you would normal static methods).

So, let’s see what the IL code looks like for that:

.method public hidebysig static int32  AddTwoNumbers(int32 first, int32 second) cil managed
{
  .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) 
  // Code size       9 (0x9)
  .maxstack  2
  .locals init ([0] int32 CS$1$0000)
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  ldarg.1
  IL_0003:  add
  IL_0004:  stloc.0
  IL_0005:  br.s       IL_0007
  IL_0007:  ldloc.0
  IL_0008:  ret
} // end of method Adder::AddTwoNumbers

The only difference between this and the plain static version is the presence of the line:

.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )

The “this” keyword results in the generation of this attribute, and its purpose is to allow the compiler to flag it as an extension method. (For more on this, see this old post from Scott Hanselman: How do Extension Methods work and why was a new CLR not required?). The actual substance of the method is completely identical.

So, there you have it. As far as the compiler is concerned, the difference between static and extension methods is “extension methods are static methods with an extension method attribute.” Now, I could go into my opinion on which should be used, when, and how, but it would be just that: my opinion. And your mileage and opinion may vary. The fact of the matter is that, from the compiler’s perspective, they’re the same, so when and how you use one versus the other is really just a matter of your team’s preferences, comfort levels, and ideas about readability.

By

Recall, Retrieval, and the Scientific Method

Improving Readability with Small Things

In my series on building a Chess game using TDD I’ve defined a value type called BoardCoordinate that I introduced instead of passing around X and Y coordinate integer primitives everywhere. It’s a simple enough construct:

public struct BoardCoordinate
{
    private readonly int _x;
    public int X { get { return _x; } }

    private readonly int _y;
    public int Y { get { return _y; } }

    public BoardCoordinate(int x, int y)
    {
        _x = x;
        _y = y;
    }

    public bool IsCoordinateValidForBoardSize(int boardSize)
    {
        return IsDimensionValidForBoardSize(X, boardSize) && IsDimensionValidForBoardSize(Y, boardSize);
    }

    private static bool IsDimensionValidForBoardSize(int dimensionValue, int boardSize)
    {
        return dimensionValue > 0 && dimensionValue <= boardSize;
    }
}

This was a win early on the series to get me away from a trend toward Primitive Obsession, and I haven't really revisited it since. However, I've found myself in the series starting to think that I want a semantically intuitive way to express equality among BoardCoordinates. Here's why:

[TestMethod, Owner("ebd"), TestCategory("Proven"), TestCategory("Unit")]
public void Returns_1_2_For_1_1()
{
    Assert.IsTrue(MovesFrom11.Any(bc => bc.X == 1 && bc.Y == 2));
}

[TestMethod, Owner("ebd"), TestCategory("Proven"), TestCategory("Unit")]
public void Returns_2_2_For_1_1()
{
    Assert.IsTrue(MovesFrom11.Any(bc => bc.X == 2 && bc.Y == 2));
}

[TestMethod, Owner("ebd"), TestCategory("Proven"), TestCategory("Unit")]
public void Returns_3_3_For_1_1()
{
    Assert.IsTrue(MovesFrom11.Any(bc => bc.X == 3 && bc.Y == 3));
}

[TestMethod, Owner("ebd"), TestCategory("Proven"), TestCategory("Unit")]
public void Does_Not_Return_0_0_From_1_1()
{
    Assert.IsFalse(MovesFrom11.Any(bc => bc.X == 0 || bc.Y == 0));
}

This is a series of unit tests of the "Queen" class that represents, not surprisingly, the Queen piece in chess. The definition of "MovesFrom11" is elided, but it's a collection of BoardCoordinate that represents the possible moves a queen has from piece 1, 1 on the chess board.

This series of tests was my TDD footprint for driving the functionality of determining the queen's moves. So, I started out saying that she should be able to move from (1,1) to (1,2), then had her also able to move to (2,2), etc. If you read the test, what I'm doing is saying that this collection of BoardCoordinates to which she can move should have in it one that has X coordinate of 1 and Y coordinate of 2, for instance.

What I don't like here and am making mental note to change is this "and". That's not as clear as it could be. I don't want to say, "there should be a coordinate in this collection with X property of such and such and Y property of such and such." I want to say, "the collection should contain this coordinate." This may seem like a small semantic difference, but I value readability to the utmost. And readability is a journey, not a destination -- the more you practice it, the more naturally you'll write readable code. So, I never let my foot off the gas.

During the course of the series, this nagging readability hiccup has caused me to note and refer to a TODO of implementing some kind of concept of equals. In the latest post, Sten asks in the comments, referring to my desire to implement equals, "isn't that unnecessary since structs that doesn't contain reference type members does a byte-by-byte in-memory comparison as default Equals implementation?" It is this question I'd like to address here in this post.

Not directly, mind you, because the assessment is absolutely spot on. According to
MSDN:

If none of the fields of the current instance and obj are reference types, the Equals method performs a byte-by-byte comparison of the two objects in memory. Otherwise, it uses reflection to compare the corresponding fields of obj and this instance.

So, the actual answer to that question is simply, "yes," with nothing more to say about it. But I want to provide my answer to that question as it occurred to me off the cuff. I'm a TDD practitioner and a C# veteran, for context.

Answering Questions on Language Knowledge

My answer, when I read the question was, "I don't remember what the default behavior of Equals is for value types -- I have to look that up." What surprised me wasn't my lack of knowledge on this subject (I don't find myself using value types very often), but rather my lack of any feeling that I should have known that. I mean, C# has been my main language for the last 4 years, and I've worked with it for more years than that besides. Surely, I just failed some hypothetical job interview somewhere, with a cabal of senior developers reviewing my quiz answers and saying, "for shame, he doesn't even know the default Equals behavior for value types." I'd be laughed off of stack overflow's C# section, to be certain.

And yet, I don't really care that I don't know that (of course, now I do know the answer, but you get what I'm saying). I find myself having an attitude of "I'll figure things out when I need to know them, and hopefully I'll remember them." Pursuing encyclopedic knowledge of a language's behavior doesn't much interest me, particularly since those goalposts may move, or I may wind up coding in an entirely different language next month. But there's something deeper going on here because I don't care now, but that wasn't always true -- I used to.

The Scientific Method

When I began to think back on this, I think the drop off in valuing this type of knowledge correlated with my adoption of TDD. It then became obvious to me why my attitude had changed. One of the more subtle value propositions of TDD is that it basically turns your programming into an exercise in the Scientific Method with extremely rapid feedback. Think of what TDD has you doing. You look at the code and think something along the lines of, "I want it to do X, but it doesn't -- why not?" You then write a test that fails. Next, you look at the code and hypothesize about what would make it pass. You then do that (experimentation) and see if your test goes green (testing). Afterward, you conduct analysis (do other tests pass, do you want to refactor, etc).

ScientificMethod

Now you're probably thinking (and correctly) that this isn't unique to TDD. I mean, if you write no unit tests ever, you still presumably write code for a while and then fire up the application to see if it's doing what you hypothesized that it would while writing it. Same thing, right?

Well, no, I'd argue. With TDD, the feedback loop is tight and the experiments are more controlled and, more importantly, isolated. When you fire up the GUI to check things out after 10 minutes of coding, you've doubtless economized by making a number of changes. When you see a test go green in TDD, you've made only one specific, focused change. The modify and verify application behavior method has too many simultaneous variables to be scientific in approach.

Okay, fine, but what does this have to do with whether or not I value encyclopedic language knowledge? That's a question with a slightly more nuanced answer. After years of programming according to this mini-scientific method, what's happened is that I've devalued anything but "proof is in the pudding" without even realizing it. In other words, I sort of think to myself, "none of us really knows the answer until there's a green test proving it to all of us." So, my proud answer to questions like, "wouldn't it work to use the default equals method for value types" has become, "dunno for certain, let's write a test and see."

False Certainty

Why proud? Well, I'll tell you a brief story about a user group I attended a while back. The presenter was doing a demonstration on Linq, closures, and deferred execution and he made the presentation interactive. He'd show us methods that exposed subtle, lesser known behaviors of the language in this context and the (well made) point was that these things were complex and trying to get the answers right was humbling.

It's generally knowledgeable people that attend user groups and often even more knowledgeable people that brave the crowd to go out on a limb and answer questions. So, pretty smart C# experts were shouting out their answers to "what will this method return" and they were getting it completely wrong because it was hard and it required too much knowledge of too many edge cases in too short a period of time. A friend of mine said something like, "man, I don't know -- slap a unit test on it and see." And... he's absolutely right, in my opinion. We're not language authors, much less compilers and runtimes, and thus the most expedient answer to the question comes not from applying amassed language knowledge but from experimentation.

Think now of the world of programming over the last 50 years. In times where compiles and executions were extremely costly or lengthy, you needed to be quite sure that you got everything right ahead of time. And doing so required careful analysis that could only be done well with a lot of knowledge. Without prodigious knowledge of the libraries and languages you were using, you would struggle mightily. But that's really no longer true. We're living in an age of abundant hardware power and lightning fast feedback where knowing where to get the answers quickly and accurately is more valuable than knowing them. It's like we've been given the math textbook with the answers in the back and the only thing that matters is coming up with the answers. Yeah, it's great that you're enough of a hotshot to get 95% of the answers right by hand, but guess what -- I can get 100% of them right and much, much faster than you can. And if the need to solve new problems arises, it's still entirely possible for me to work out a good way to do it by using the answer to deduce how the calculation process works.

Caveats

In the course of writing this, I can think of two valid objections/comments that people might have critiquing what I'm saying, so I'd like to address them. First of all, I'm not saying that you should write production unit tests to answer questions about how the framework/language works. Unit testing the libraries and languages that you use is an anti-pattern. I'm talking about writing tests to see how your code will behave as it uses the frameworks and languages. (Although, a written and then deleted unit test is a great, fast-feedback way to clarify language behavior to yourself.)

Secondly, I'm not devaluing knowledge of the language/framework nor am I taking pride in my ignorance of it. I didn't know how the default Equals behavior worked for value types yesterday and today I do. That's an improvement. The reason it's an improvement is that the knowledge is now stored in a more responsive cache. I maintain having the knowledge is trumped by knowing how to acquire it, and I look at reaching into my own personal memory stores as like having it in a CPU cache versus the memory of writing a quick test to see versus the disk space location of looking it up on the internet or asking a friend.

The more knowledge you have of the way the languages and frameworks you use work, the less time you'll have to sink into proving behaviors to yourself, so that's clearly a win. To continue the metaphor, what I'm saying is that there's no value or sense in going out preemptively and loading as much as you can from disk into the CPU cache so that you can show others that it's there. In our world, memory and disk lookups are just no longer expensive enough to make that desirable.