Intro TDD

(This article is subject to deletion, and I can't find the de-Wordify button)

 

This object started out complicated, it started when I saw an example online. The example addressed a recurring problem but there was something about the solution proposed that just didn’t sit well with me.

Having the problem stated clearly and a solution in front of me I had a good idea of what I needed so I started writing some tests. The tests and the code got pretty complicated.

 

When I had green on a workable control. I tried to use it on an asp.net page and quickly found out that I hadn’t exposed the properties that I really needed. I had gotten stuck on my ideas about the implementation instead of writing tests for how to use it.

 

I’m trying to learn test driven programming, so I started again. 12 Tests later, I have a class 60 lines long that passes all the tests and seems to do what I need.  I have some xml files, one per language, with lists of countries and their constituent states and provinces. The class lets me get a bindable list of countries and of the regions of a country. The language of the list used depends on the thread’s CurrentCulture.

I’ve saved a lot of trouble and kept the class simple by using a dataset’s ReadXml to get my xml as data but it is obviously not complete. A look at the load method makes this clear.

public void Load(CultureInfo culture)

      {

            _cultures.Add(culture,null);

      }

I have tests that check the number of loaded  cultures and the keys of the _cultures hashtable but none that check the value. In the first version, the Load method was where I was loading the data, and I’m pretty sure I still need to load the data once and not every time there is a call to GetCountries or GetStates.

 

I need fail-over from a culture to it’s parent culture. Instead of just returning void, Load needs to return the culture of the data it loaded (if it was able to load data). If I ask it to load “en-CA” and there is only a common “en” then it should load “en” and return the “en” culture. I must have this same kind of fail-over when retrieveing the data. When the current thread’s culture is “en-CA” or “en-US”, I must get the data from “en”.

 

A lot more tests; construction tests and data loading tests. The construction tests led me to a GetCurrent method that could replace my public constructor.  When it was tested, I made the constructor private. The only way to get an instance was with the GetCurrent.

 

GetCountries does its job, but it returns a DataTable; You need to know in advance what the column names are. A class and a collection would be a lot easier to use.

The tests are just a reflection (prediction) of how an object will really be used and mine are full of "countries[0][“DisplayName”]", which is harder to write than "countries[0].DisplayName", especialy when intellisense is working. I start to change a tests and suddenly I need a typed object, in fact I need a two of them and two collections for them: CountryInfo,StateInfo, CountryInfoCollection and StateInfoCollection.

 

The collections satify me when I try using the control in an aspx page, but the RegionalDataManager is full of stuff.

 

In short , it works but it is ugly. This seems to bring me right back to the beginning, but there is one huge difference: I have a lot of tests that require the object to behave in a certain way. Time for some refactoring.

 

The refactoring was a suprisingly short process, moving the actual data out of the RegionalDataManager and into a RegionalDataStore. I accomplished this by building it along side what was already working. Repeatedly building and running the test to make sure I didn’t break anything and then swapping it in to see if it passed the tests; It did.

 

The RegionalDataManager has a fair amount of code, but the code is focused. It loads data from xml files and uses that data to create RegionalDataStore objects which it keeps in a hashtable. When asked, it returns a CountryInfoCollection from the appropriate RegionalDataStore for the current culture.

No Comments