www.codinghillbilly.com   kyle.baley.org  Subscribe / Contact
 
 
 
 
LATEST POSTS
Friday, November 16, 2007

Today, we'll talk on the virtues of restraint, cleverly disguised as an exercise in TDD.

Here's the bug that I snagged during the stand-up: When I try to delete a Mechanical Doohicky*, I get an unhandled exception.

Careful and value-added analysis led to the following code that checks to see if the Product is being used by another object:

        public bool isPartUsed( IMechanicalDoohicky part )
        {
            foreach ( Heap heap in heaps )
            {
                if ( heap.Engine.Parts.Contains( part ) )
                {
                    return true;
                }
            }
            return false;
        }

The issue should be readily apparent. Namely, heap.Engine might be null.

My first reaction to this was: easy fix. Check heap.Engine for null and spend the rest of the hour playing Whack-A-Mole (not the version you're thinking of).

But nay, coders, let's slow down and see if there's a way we can drag this billable time out a bit in a justifiable way**.

What we're going to do first is write a test to expose this little bug. For those of you who obsess over analogies, think of it as...oh, I dunno, fixing a leak in a dam. You don't want to shut the water off, then have to turn the water on to make sure the leak is fixed. OK, maybe I'll pass on the analogies. Hillbillies are just too real. But I'm writing the test anyway because it's trendy.

Over to our test harness, we add a test that will fail specifically because of this bug:

        private bool Should_not_fail_when_checking_if_part_is_used_in_heaps_with_no_engine( )
        {
            // ... set up part and heaps with one that has no engine ...
            heaps.isPartUsed( part );
        }

Back to our code and we update it to fix the bug:

        private bool isPartUsed( IMechanicalDoohicky part )
        {
            foreach ( Heap heap in heaps )
            {
                Engine engine = heap.Engine
if ( engine != null ) { if ( engine.Parts.Contains( part ) ) { return true; } } } return false; }

So it may seem like a lot of extra work to fix a seemingly simple bug, especially because of the ominous way I commented out all the set up code in the test. But the bug is fixed and I can now prove it without having to launch the UI and going through the pain of setting up the conditions that led to it. And if anyone mucks with the implementation of Engine, we can be reasonably confident this particular bug won't get re-introduced. Plus the test acts as a sort of documentation of the bug that we've fixed.

Final note: There is a reason I stored heap.Engine in a temporary variable other than avoiding duplication.

Kyle the Exposed

* Domain objects have been renamed to protect the innocent. I.E. me

** My lawyer has advised me that, due to my increased readership in the U.S., I should add that I am officially and legally kidding.

Thursday, December 06, 2007 8:14:26 AM (Eastern Standard Time, UTC-05:00)
Final note: There is a reason I stored heap.Engine in a temporary variable other than avoiding duplication.

Which one?
alberto
Thursday, December 06, 2007 8:52:46 AM (Eastern Standard Time, UTC-05:00)
Yeah, I submitted this post without quite finishing it and kinda hoped no one would call me on it. Now, I have to remember what the context was...

Ah yes, I remember. In the tests around this, "heaps" stores a couple of mock objects with an expectation that heap.Engine would be called. Once. If I didn't store it in a temporary variable, these tests will fail because heap.Engine would be called twice with an expectation that it be called once.
Kyle
Comments are closed.

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

Copyright © 2010 Kyle Baley. All rights reserved.
 
CATEGORIES
.NET General (18) alt.net (4) altnetconf (9) ASP.NET AJAX (40) ASP.NET MVC (29) Bahamas (1) Bahanet (9) BDD (1) Brownfield (21) Career (10) Castle (1) Code coverage (1) Code review (2) Coding Style (6) Communication (1) Community (18) Conscientious Coding (35) Continuous Integration (11) dasBlog (12) Development (16) DevTeach (4) Domain (2) Environment (4) Estimating (1) Featured (14) Flamingo (10) Games (1) Google App Engine (3) GWT (9) Hardware (6) Java (2) Javascript (7) Linq (2) Livelink (6) Lucene.NET (2) MbUnit (1) Metrics (2) Miscellaneous (25) Mocking (4) NAnt (4) NHibernate (12) NInject (1) Office (3) Office Development (6) Open Rasta (1) Patterns (6) Presenting (14) Professional Development (15) Refactoring (10) ReSharper (11) REST (3) S#arp Architecture (5) Security (3) Software (11) Sundry (19) TDD (19) Tools (22) User Interface (6) Utilities (9) Visual Studio (8) VSTO (1) Web development (12) Windows (3) Working Remotely (17) Workplace (3) Writing (6)
 
LATEST POSTS
 
POPULAR POSTS
 
 
ARCHIVE