Timer – Part 1

27 11 2010

Why part 1? Because arrays are zero-indexed for me.
Lame jokes aside, let’s continue… um… now what?

In the army when we’ve done navigation field exercises they told us that whenever we get confused or lost the best option is to find higher grounds and survey the land. This particular advice is just as relevent for me here as it was back then [although no matter how many times I got up I always got lost again on the way down but that’s another story :D].

The equivalent to taking to the higher grounds here is looking back at the original answer to “what do I want?”. Ok, looked at it, now what’s the simplest state in which a Timer object can exist? The simple answer [and simple is the only answer one should look for when testing first] is a Timer that isn’t running. Sounds good, let’s do that. I can already see that I’m going to end up with some duplicated setup code so I’ll write the fixture code now [but keep the previous test in a different file, call this one timer_not_running_tests.cpp].

#include <UnitTests.h>
#include "Timer.h"

struct timer_not_running
{
  Timer::name_type _name;
   Timer _timer;

 ~timer_not_running(){}
    timer_not_running()
    : _name("NotRunning")
    , _timer(_name)
    {}
};

TEST_FIXTURE(timer_not_running, _check_timer_name_is_correct)
{
  CHECK_EQUAL(_name, _timer.Name());
}

Compile, run and watch it flame. Why? Timer::Name() returns a constant string to satisfy the previous test. Stop, let’s reflect here for a second before going on. If we look at the code from last post we’ll also notice that the first test we wrote suffers from a bad case of code duplication. The “Timer1” string is constantly duplicated, in the test and in the Timer class code. I’m going to take the time now to remove the duplication by refactoring the Name() function.

#ifndef _TDD_TIMER_
#define _TDD_TIMER_

class Timer
{
  public:
    typedef char* name_type;

    name_type Name() const { return _name; }

    Timer(name_type name)
    : _name(name)
    {}

  private:
    name_type _name;
};

#endif/*_TDD_TIMER_*/

Compile, run and watch both tests pass. What have I learnt? Removing code duplication as soon as possible leads to more general solutions. So from now on, obvious code duplication should be removed as soon as possible. The second test should always be written though, to verify that the solution is indeed what we want. The other approach for something like this is using the additional tests to force the functionality to change, in this case I would have had to hold the name string in an actual variable in order to have different names. Using more tests to zoom-in on the correct implementation is called Triangulation within the Agile circles and I usually use it to flesh out complex functionality. Alright, less talk more code, I’m testing a timer that isn’t running. If a timer isn’t running then the total time that it counted should be zero, right? let’s test.

TEST_FIXTURE(timer_not_running, _check_total_elapsed_time_is_zero)
{
  CHECK_EQUAL(0, _timer.TotalElapsed());
}

Compile, run, things explode, let’s add the right function.

#ifndef _TDD_TIMER_
#define _TDD_TIMER_

class Timer
{
  public:
    typedef char* name_type;
    typedef double elapsed_type;

    name_type Name() const { return _name; }
    elapsed_type TotalElapsed() const { return 0; }

    Timer(name_type name)
    : _name(name)
    {}

  private:
    name_type _name;
};

#endif/*_TDD_TIMER_*/

Whoops, code duplication. Let’s refactor.

#ifndef _TDD_TIMER_
#define _TDD_TIMER_

class Timer
{
  public:
    typedef char* name_type;
    typedef double elapsed_type;

    name_type Name() const { return _name; }
    elapsed_type TotalElapsed() const { return _totalElapsed; }

    Timer(name_type name)
    : _name(name)
    , _totalElapsed(0)
    {}

  private:
    name_type _name;
    elapsed_type _totalElapsed;
};

#endif/*_TDD_TIMER_*/

Compile, run, all tests pass and I’m happy. The code itself isn’t very exciting to look at, after all of this and I’ve just got two functions up and running. But the bigger picture is a bit more invloved. I’ve learnt the importance of removing code duplication early, I’ve had some more practice in making assumptions about functionality [a timer counts the total elapsed time therefore a timer that isn’t running should have a zero value for it]. And last but far from least, I’ve started documenting the contract between the client [what is needed] and the developer [what the code does] through the tests; that is, the timer must have a name and will measure a total amount of elapsed time. There is one more design decision I’ve made here, it might not be as obvious though, can anyone spot what it is??

“…Into the half light, Another velvet morning for me, yeah…”

Advertisements

Actions

Information

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s




%d bloggers like this: