June 2006 - Posts

The problem

In order to be able to build better software for our customers, we need to be able to discover are their needs and how our software could address those needs. This means applying a scientific method which involves the natural steps of: observation hypothesis and experimentation.

The first thing we need to do is observe what the client or potential client does and from that extract some hypothesis and deductions about what he is doing and see where the shortcomings might be, what his needs are. Then based on those needs analyze them and select those that can be addressed by software. Based now on this experiment by building the software, deploying it and starting with the scientific method's steps again, by observing how the software is used and whether it is useful for the client to achieve his own goal, whether the software helps the client. Again based on these observations, modify and improve the software to help the customer.

Where does software help business processes?

Let's make a short experiment and go back to the roots with software in businesses, to see when and how software can help a client's company business processes. At first most companies did everything on paper, and some of them were very efficient at doing this. A very good study about the big transition from paper based processes to software based business processes has been done by nobody else but Bill Gates in his book: Business @ the speed of thought, the book being his observation and deductions of large companies and corporations especially. The experiment and its results can be seen on NASDAQ or by looking at out computer screen, Microsoft on top everywhere.

Going to the back to withdraw (not ATM) money you see the employee there writing all your details on a withdraw form, then printing it off and maybe asking you to sign it. For performance reasons, I noticed that the amount of time spent to write all those details on a piece of paper or on the computer are about the same, so where's the benefit of using software if using it and not using it in this activity is almost the same. The benefit is in reporting. The benefit is that when you have an audit asking you what you did with the money, or you your boss is asking you how are the same for that particular item, in July this year compared to July last year, using software is infinitely faster, as this report can be given back to you in seconds instead of having days and weeks of looking trough the
piles of paper. Not to mention human error.

Information extraction more important then informatrion gathering?

After this small observation, my hypothesis is that software is beneficial in business processes mostly for getting data out, then for putting it in.

In order to be able to be organized in a business, you need to have information available to you: fast and reliable. In order to improve your business processes you need , as a customer of software to be able to observer, draw conclusions and deduct facts based on these observations and experiment in improving the business processes. So, the most critical part of the business software is the part that gives information for the people that can draw conclusions from it and be able to improve their business. So that's where the software should really point at.

I recently emphasized this in a blog entry Do we, programmers, build sellable software? in the part that says: sell to managers. These are the decision makers, so help them apply scientific methods on their businesses with your software. Help them improve their own business by giving them the relevant information they need fast.

Unfortunately a lot of software is being built and "incredibly" for me, sold, although this theory of mine is not applied. Usually the developers make the program, where the client can add data easily, and from usability point of view the reports are left behind. Now the reports are the ones that decision makers can use for their observations, and these should be standing out for them. They shouldn't have to click seven times until a report is shown. Information should be accessible very easy, because that's what they need.

Experimenting on this hypothesis

Some of the programs lately have started with the dashboard or home page concept. When the user opens the application, the most relevant information for him is being displayed with no clicks for him. An example is Microsoft Outlook, where the home page shows you your appointments and not a form where you can add a new appointment. Many websites also have this concept, so when you login as a user you're presented with a home page where relevant info is summarized and displayed for you. However I think this view is still in it's beginning, although steps are being taken in the right direction.


The idea for adding the scientific point of view to the way we can improve business
software, making it more usable and more sellable, came to me after reading in Kent Beck's book: Extreme Programming Explained: Second Edition, the chapter entitled: Taylorism and software. Kent Beck says that the first man that applied scientific methods to industrial production was Frederick Taylor. He was the first that applied the 3 steps in industrial production, calling his methods: scientific management: observation, hypothesis, experimentation. After reading this chapter, I realized that people that want to improve their business processes apply the same steps, and that our software should be adapted to this need. I reached this conclusion by applying myself the 3 scientific steps, observing how management and decision makers need to use software, drawing the conclusions that info out is more important then info-in, and experimenting in the latest programs I designed, where getting information out has a much higher priority.

Final words ...

Applying the scientific method steps, I realized that in some areas our software must help our customer apply these methods for his business and goals. I strongly believe that software must be build with a goal in our minds, and probably my conclusions about building software that helps decision makers in applying scientific methods are mostly appropiate for products being build and then sold by a software company, but maybe the domain is even larger ... this hypotesis can only be confirmed by experimentayion, isn't it? :)
Ever changing databases

In a world where we have to adopt new processes to develop software in order to adapt to ever changing environements, what happens to our databases. Do our databases, keep up the rhytm with the code in changing conditions?

Although we made big progresses in 'becoming agile' we are still at the beginning although instant results were seen ever since we started. But although there are lots of materials about agile processes, about agile techniques that are focused on making agile processes work like unit testing and TDD, refactoring, continuous integration, frequent delivery, evolutionaty design etc there are few materials over the web that deal with databases in agile processes.

I would like to say that mostly we are confronting ourselves with simple databases (

The questions I have are:

1. How do databases deal with changes?
2. How to develop tests that are easely maintenable in these conditions?

1. How do databases deal with changes?

After adopting a two week iteration technique, we were confrunted with many versions of a database, one every two weeks. The database was evolving and often changed. The problem is bigger if the system has gone live. You must make an update to the live database with every new version. In the first iterations of a project, usually until a 'stable' database schema is adopted, it changes a lot, but if the system doesn't go live this is a minor problem as old databases can be just dropped and rewritten. After the stable version is reached, the updates from one version to another can be done more easely with alter scripts.

From time to time the client told us they were having difficulties with the new version we just sent, as it just crashes immediately after start. We noticed that this is usually because the database scripts haven't been run and the program is the new version, but the database is old and it the application just crashes at some time. This has given us a lot of sweats and afterall,clients that came to see the new version and see it crashing remember that your software is buggy not that this has something nothing to do with you.

Versions table and update scripts

A way to deal with this was the versions table and update scripts. Each modification in the database from one version to another version is made with a script and not directly. The database also contains a Versions table the logs all these updates. This way we can know what is the current database version, when was it created , what modifications were made (a comments field) who did the script and when it was actually run. How do we know this? By simply putting an insert line into our update script that puts in this data into the versions table.

After applying this techinque we thought about putting in the application installer, a part of code that runs the update. And we did it, but new problems arrived. A client managed somehow to override a live database, although we put in a lot of messageboxes asking to confirm whatever he did. So we thought of adding a line in the configuration file of the application which says which version should the database have in order to start the program and unless the database has the right version, the program won't start. Now noone forgets to make the updates.

Automating the update script creation

This is a simple solution that seems to work well. However a problem with it is that manually creating the update scripts is taking a lot of time to do and to test. This problem brought to our attention a product, build by RedGate, that knows to generate the update script after comparing two databases. This greatly reduces the amount of work, needed to make the update scripts, we can now make them manually on a test database then with the tool generate the update script.

2. How to develop tests that are easely maintenable in these conditions?

Everyone teaches us to make our database related tests, data independent. The most used techniques are made either by having a separate database used for testing , creating the test database with data on setup and dropping it on teardown and using a rollback technique (database server rollback or using Entreprise Services). Each of these techniques have their own problems, although seem to solve the problem of making the database tests independent from the data in the database. But are they easely maintenable if the database stucture changes often?

ORMs

It seems that using ORMs makes database access code more testable and easely maintenable, as errors after a change was made is detected fast. Some ORMs even know how to generate the create, and most importantly the update scripts themselves. If you have the unit tests related to the ORM's persistent objects the errors in tests can be detected very fast, first just by compiling then by running them so that query problems are revealed. ORMs seem in my opinion more agile then other approaches as using ADO.NET connected and disconnected database access. Is this the solution for all problems? No, however they seem to embrace change more easely.

Regression query integrity tests

Whether you are using ORMs or not, when making a structure change to a database you need instant feedback to see if you broke anything. It is very important to know that at least,that all sql queries (queries/stored procedures etc) work. Not that they work ok, but that they work. It is very important to know this immediately after making the changes. So maybe one technique is to make a test suite that just verifies validity of sql queries and not functionality. I call these regression query integrity tests.

My idea is to create a list of very simple tests, that just run the queries, to see if they break or not. This can be easily run each time, a structural change in the database is done, to see if something was broken or not. Some of the code for this kind of tests can be generated. Code generation, is in my opinion the great missing piece from any agile metholodology's list of practices, as by using code generation, productivity can dramatically improve.

Conclusion

Although we develop projects that are quite simple, from a DBAs point of view, we must keep in mind that it is very important to have techniques that enable us to change the database code, just as easy as the code itself, otherwise this can rapidly become the big bottleneck of our project, that 'embrace chage'.
About two months ago, one of our clients decided, to change the way one java web application that we built for them a few years ago worked. The application is built to gather and process different kinds of measurements in a medical sector, building different charts and analysis reports on these measurements.

The requirements

When the application was first built, it was decided that each client (hospital etc) will have their own instance of the application installed at their location. That meant for instance that when a report is run, it is done on all the data from the database.

Now the client, after a market research decided that it was to hard to deploy and maintain a vast amount of applications in different locations, so they asked me if we could change the way the aplication working, so they could host the application, the application can have one database, but multiple clients can log into it and work. This would mean that the data in the database should be divided for each of their clients so they can only see their own data and now the other's.

The solution was to have a master table, I called it entities, which would now have a foreign key in all measurement tables. Although altering the database wasn't such a problem, I had to maintain the existing functionality as it was, and because of the domain there were some difficulties, especially because some complicated phisical methods of calculations were used troughout the software.

How can I change but keep existing functionality exactly the same?

If the application needs to stay the same, I had the idea of recording some testing scenarios using the great open source Selenium[1] and the Mozilla Firefox extention, called Selenium IDE [2], trough the web interface that worked for the legacy version, that would need to work with the new version also.

But if I record a database test, and want it to work after I change the internals of the project, this means that I need to have the same data into the database, when the test is rerun. For this first I created a servlet which I called CreateTestDatabaseServlet who's mission was to reset the entire data from a database to a known state. Based on that state I could record my tests, because I knew what should appear on the user interface. For instance, my servlet, cleared all FilmType rows from the database and added Film Type A, Film Type B and Film Type C. Now when going into the web application, I knew for sure that the combo on a screen , where I can choose a FilmType has the 3 values all the time:

The code of the servlet is like:

public void doGet(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException{

this.session = HibernateUtil.getSession();
response.setContentType(CONTENT_TYPE);
PrintWriter out = response.getWriter();
out.println("");
out.println("

The servlet has received a " + request.getMethod() +
". This is the reply.

");
out.println("

"+this.createTestDatabase()+"

");


try
{
out.println("

" + this.insertTestData() + "

");
}
catch(Exception Ex)
{
Ex.printStackTrace();
}
finally
{
try {
this.session.close();
} catch (HibernateException ex) {
ex.printStackTrace();
}
this.session = null;
}
out.println("");
out.println("");
out.close();
}

where:

private String createTestDatabase() {
new AECBO(this.session).deleteAll();
new TubeRoomBO(session).deleteAll();
new UserBO(session).deleteAll();
new EntityBO(session).deleteAll();
new SUMBO(session).deleteAll();

...

return "";
}

and

private String insertTestData() {

...

createFilmType("Film Type A");
createFilmType("Film Type B");
createFilmType("Film Type C");

...

createProjection("Left Crano-Caudal");
createProjection("Right Crano-Caudal");

....

createUnit("FFD","centimeters (cm)",1);
createUnit("TRC","centimeters (cm)",1);
createUnit("FSD","meters (m)",1);
createUnit("BT","centimeters (cm)",1);
createUnit("CIO","micro-Grays (µGy)",1);

...
}

Now when a Selenium test is run, the first thing it does it reset the database to the known state, then login (I already know I have a user created by the servlet, that has a/a as credentials) and do what is necessary:

|open|/app/CreateTestDatabaseServlet|
|open|/app/login/login.faces?random=734574375|
|type|loginForm:userName|a|
|type|loginForm:password |a|
|clickAndWait|link=Login|
|clickAndWait|link=Image Quality|
|type|_id1:main:dateinput||


With the method to reset the database in place, using Selenium IDE [2] I started recording tests for all parts of the application, following different scenarios, which I then saved and created a suite of selenium tests, and after I made sure all of them work, I started dissecting the code.



Then I took a test, refactored the code and database until I made that selenium test work. Then I took the next test, until it and the one before it worked. I looked if I could make some refectorings, I did them ensuring nothing is broken and moved to the next test, until one month later all tests were working.

Although it doesn't seem like very much, the selenium regression tests helped me a great deal, telling me in 7 minutes if the existing functionality of the application (which took more then a year to develop because there are some very complicated phisics formulas in it) is working exactly as it did before, but with the extentions added. One of the big refactorings I did also was to remove the built in data access layer and business objects, and replace everything with Hibernate [3].

So it proved that my plan of action
1. Reset state of the database
2. Record the tests
3. Refactor - test until the recorded tests works again

worked very well and very fast.

Conclusion

Without Selenium, Selenium IDE and Hibernate, the entire operation could have taken a lot more then a month, because of the constant fear that the existing functionality will be broken and would need tobe rebuilt, after more then a year was already invested in the project.

[1] Selenium - www.openqa.org/selenium
[2] Selenium IDE - www.openqa.org
[3] Hibernate - www.hibernate.org
Sharing the thrills with the customer: the good

Programmers want customers to use their software. Some of them want to be given feedback in order to improve the software. Most programmers, want even, their customers to be thrilled by their software, if they are thrilled by it. They want their client to share this with them. This is a good thing, it makes us developers proud, knowing that the software is being used, that the customer shares our enthusiasm for a solution we thought of, doesn't it? This is good.

Sharing the thrills with the customer: the bad, the ugly

Unfortunately, programmers want more, and like any excess it ends up bad. The programmers want the client to be thrilled by their technical accomplishments, by the 'smooth' things in the solution, techincally speaking, by how ingenious the solution was developed. They want the customer to be excited that the programm works 28 times faster then another solution. This is bad and ugly. It is naive. We programmers like logical things, but this is against logic. At least at the beginning.

The customer will only be thrilled by a software if it will improve his life, if he can achieve his business goals faster. It doesn't matter if the product was ingeniously build but whether the product is an ingeniuos tool for him. He doesn't care whether it is faster 28 times faster then another technology, unless the second was slow by his standards, he doesn't care if you used n-tier , unit testing or automated builds, 'healthy' approaches or not. He only cares if he can be more efficient with his new tool, your software.

So where is the problem in sharing the thrills with the customer?

Programmers and customers are both thrilled by being good at what they do. This is the common thing. The problem is that they act in completely different areas (mostly), so 'at what they do' means completely different things. Let me give a very simple example: management likes reports about what developers do, so sometimes as a programmer you're not very happy at the end of the day to fill in a report about your activity. Well that data makes them happy, but takes time out of your programming time. They even sometimes, show you the reports very enthusiastic believing that you would share that too, but do you?

Software is a tool. Just having it doesn't make your customer happy

It's not that easy to be thrilled just by the fact that you have a tool. You'll be thrilled only by achieving a goal. If achieving this goal, involves using a tool, you will be thrilled by the action of achieving the goal and not by the fact that a tool helped you achieve it. Just having a tool or using it without meaning doean't make you happy.

Let's say that you're a mobile phone manufacturer. You want to sell your customer mobile phones. If you sell them mobile phones, they won't be thrilled by how good you phones are. They will only see their potential when they'll achieve the goal of speaking from everywhere. They will be thrilled by the fact that they can go everywhere, and still be able to be called and call anyone they like. This is the first thing they will notice, this is their goal, to be mobile and not to own a mobile phone. They won't care if it is GSM or CDMA, if it works on triband or not. Fortunately, as the time goes, they'll start realising that in order to achive their goal of mobility better, they depend on the mobile phone. Some will even notice, that it works on three frequency bands. They will see that they can be more efficient at their primarily goal by improving their tools.

Turning priority lists arround

If you have real good marketing people, you might find out that at a time, this goal changed, they care more about having powerfull mobile phones with color display, calendar, mp3 player and camera more than speaking from everywhere. People become addicted. Another example would be skiing. At first you don't care about what helps you ski but about the action of skiing.

Unfortunately, we as programmers often missunderstand the approach we need to use. We think that proirities are already changed, and we show the client how great the software is compared to another, and not how it will help him. We assume that the customer is already addicted.

Show the client not how to use your software but how your software helps him

Think about car manufacturers (and salesman), 2-3 decades ago, when they suddenly realised that there a huge new market: women. So, the salesmen turned their entire arsenal towards women. They started showing women mustangs and corvettes, impressive V8 engines, incredible horse power, the beautiful roar of the engine, how fast and powerful they are, how fast they go from 0 to 60 miles per hour, how cool the cars were.

Cool vs Chic

Well, this meant nothing to women. They didn't want cool they turned out to want 'chic'. Women had no idea what V8, 5s 0-60, 160mph, roars etc meant. The first thing they wanted was a mirror to be able to powder their noses, check the makeup, a place to put their purse?, colors to match the shoes etc. Of course, I am kidding, but I am trying to emphasize that women had completely different expectations about cars. They didn't want 'cool', they wanted 'chic'. They didn't want to show power and masculinity , but independence.

The reason behind this strory is to explain how important is to know your market. Men knew how to sell cars to men. We programmers try to sell software to clients as if they were programmers, when instead the client has completely other objectives, just like women did with cars.

Sell to managers

I noticed that many presentations of a software solutions miss their target, because instead of showing the customer representatives there, which are mostly management people how the program works for managers, how to extract the info, because this is what managers want, they show them how the application can add and save data to a database.

The managers see the purpose of a program as getting THE information needed now. This gives them what they want: power by controlling the information. If you present a software to managers, show them the manager's dashboard that displays the instant data, the main reports and not how your application puts the data in (unless they ask).

I strongly advise you to look at Google. It is so sucessfull not by being a search tool, but by giving you the info you want. Everyone feel the power of getting information instantly at Google. They sell the solution because they know that the clients don't want to search, they want to find.

Conclusion

I hope to have achived to explain you that us programmers ofter put techincal ingeniousity before customer demands, we ofter tend to tell the customer what he wants instead of letting him tell us what he wants. I believe that because of this reason we do not build sellable products, but we tend to build expressions of our egos in our software, to show the other programmers how good we are and not the customers.
Can you be agile and "test-infected" in environements that provide no or little similarity to the platforms used for doing unit and functional tests? Can you still do test first programming in an development environement where you don't have NUnit or FIT?

Test Driven Development and Test First Programming

Let's start from the roots of Test Driven Development and Test First Programming. I noticed that around these two concepts there is a little missundestanding, some people condidering them to be the same, others considering them different. My opinion is that the two are slightly different, TDD being a method of programming where you think about how you are going to implement a feature before implementing it. The second, TFP is a more concrete approach, that says to write a test before you write the code. So where's the difference. The difference in my opinion is that TDD does not really force you to write the test before writing the code or writing the test at all. It just says to think about how you could automate the testing of the feature you want to implement, how to design a testable piece of software. TFP forces you to write the test first, whereas TDD forces you to design thinking about testing, but giving you the option to write the test when you want to.

So, as a conclusion, in my opinion TFP is a particular case of TDD whichis more generic. Don't get me wrong I do like very much to write the tests before.

Were there automated tests before xUnit and/or FIT?

Coming back to our problem with TDD on environements where you have no or little documentation, where you're a pioneer, I would say that we need to go back to the basics. Automated tests do not mean NUnit (xUnit) or Fit. These two frameworks and the ones deived were build to help making automated tests easier, but what was before these arrived?. Did people not write automated tests for their software? I doubt that. But how did they do automated tests it?

Well I belive that there were several techniques but the most popular were either adding a test button on the UI (desktop apps , we are talking about early internet or before internet times) or by adding a main method to the class (java). This were probably the most populat methods of building both functional and unit tests.

The 'test button' functional tests actualy put values into the controls on the form then simulated the click of a button then checking the results of that action. As a dear friend of mine said, this had the drawback that you needed to remove the test button when going into production, and more complex testing scenarios were increasingly hard to do.

How do you build functional tests on Windows.Forms apps for .NET CF?

You have no NUnitForms, no NUnit not a thing like this. What do you do? In order to be able to automate the testing of my forms, I thought how about adding the test button, but I remebered I wasn't particularily fond of it. Then I had the idea that for each form, I could add a "region" where I can have my test helper methods, each of them starting with Test. This meant, that in my application designed for PocketPC and used to collect measurements for medical equipment on daily, weekly, monthly and quarterly basis, having for each of these at least two forms, one dispalying the
list of available measurements and the add/edit/delete methods and the other to be able to add or edit a record, with ok/cancel buttons.

In each form, I added a region "Testers" where I added my testing helper methods like:

#region testers
public void TestTypeQuantity(double q)
{
TestingHelper.Type(this.txtQuantity, q);
}
public void TestSelectMeasurementUnit(int index)
{
TestingHelper.SelectMeasurementUnit(this.cbxQuantity, index);
}
public void TestClickAddDailyMeasurement()
{
TestingHelper.Click(btnAddDailyMeasurement);
}

#endregion


In order to be able to interact easier with the controls I have a TestingHelper class, that helps me work with the controls as if I were the user. For instance in order to click on a button, I have:

public virtual void Click()
{
if (Control.Visible)
{
FireEvent( "Click" );
}
else
{
throw new Exception("Control " +control+" is not visible." );
}
}

public void FireEvent( string eventName )
{
MethodInfo minfo = Control.GetType().GetMethod( "On" + eventName, BindingFlags.Instance BindingFlags.Public BindingFlags.NonPublic );
ParameterInfo[] param = minfo.GetParameters();
Type parameterType = param[0].ParameterType;
minfo.Invoke( Control, new object[]
{
Activator.CreateInstance( parameterType )
} );
}


or for typing something in a TextBox:

public static void Type(Control control, string text)
{
control.Focus();
control.Text = text;
}


The test and handling modal windows

For the test, I have a simple singleton class, that tests like:


public class TestingInstance
{
#region members
private static TestingInstance testingInstance = null;
private Hashtable expectedModals = new Hashtable();
#endregion

private TestingInstance()
{

//specify what method to be invoked when DailyChecksForm modal is shown
ExpectModal(typeof(DailyChecksForm),"RunDailyChecksForm");
}

private void ExpectModal(Type formType, string param2)
{
this.expectedModals[formType] = param2;
}

public static TestingInstance Instance
{
get
{
if(testingInstance==null)
{
testingInstance = new TestingInstance();
}
return testingInstance;
}
}

public void OnModalShown(Form form)
{
string methodName = expectedModals[form.GetType()] as string;
MethodInfo mi = this.GetType().GetMethod(methodName);
object[] parameters = new object[]{form};
mi.Invoke(this,parameters);
}

public void Run()
{
MainForm mf = new MainForm();
mf.Show();
mf.TestSelectUnitByIndex(2);
mf.Close();
}

public void RunDailyChecksForm(Form form)
{
DailyChecksForm mf = form as DailyChecksForm;
//mechanical checks
mf.TestSelectMechanicalChecksTab();
mf.TestTypeSignature("Dan Bunea");
//x-ray tube
mf.TestSelectXRayTubeTab();
mf.TestSelectTargetFilter1(1);
mf.TestTypeReading1("1.0");
mf.TestSelectTargetFilter2(1);
mf.TestTypeReading2("2.0");
mf.TestSelectTargetFilter3(1);
mf.TestTypeReading3("3.0");
mf.TestSelectTargetFilter4(1);
mf.TestTypeReading4("4.0");
//4cm
mf.TestSelect4cmTab();
mf.TestTypekV("1");
mf.TestTypeMAS("2");
mf.TestSelectTargetFilter4cm(1);
mf.TestTypeDensity("3");
//click ok and save
mf.TestClickOK();
}

...


Since my Win32 knowledge level is low, what could I do to see when a modal form is being shown. Well as always there is a solution, you just have to use your head a little.

All my forms extended a TestableForm, which on load notifies the testing instance that it has been shown . For instance in DailyMeasurementForm I have:


private void DailyChecksForm_Load(object sender, System.EventArgs e)
{
TestingInstance.Instance.OnModalShown(this);
}



which when is loaded and shown tells my TestingInstance that it has been shown, then my testing instance looks in the list of expected modal forms for the type and invokes the specified method, in our case, we have in the tesing instance constructor:

ExpectModal(typeof(DailyChecksForm),"RunDailyChecksForm");

which means that when DailyChecksForm is shown, it will invoke OnModalShown in TestingInstance and that will invoke RunDailyChecksForm. Simple , isn't it?

How do you start the test on the mobile device?

public static void Main()
{
if(IsTestingMode())
{
TestingInstance.Instance.Run();
}
else
{
Application.Run(new MainForm());
}
}


public static bool IsTestingMode()
{
return true;//this can be modified very easely
}


Maybe I could have manipulated VS.NET and would have found a more elegant way of doing it, but let's not forget that I needed to develop software that could be automatically tested not really invent the new all good testing framework for PDAa and respecting the two agile priciples of simplicity and evolutionary design, I think the code is good enough and can be refactored and improved later.

Conclusion

The bad thing about my solution is that it mixes testing code with production code, but I think that even with this drawback, it is still better then testing everything manually. And maybe the test code could be removed from the production code using preprocessor directives, but that is just a supposition.

So do we really need NUunit?...TDD can be done without but apps shouldn't be done without TDD in my opinion. But I guess that I am just "test infected" ... :)