2008-12-30

Domain driven design, Test driven design

I was just reading through the VBUG events list when I came across an event entitled "Domain driven design approach, using unit testing".

"Sounds interesting!" I thought to myself, I hope I can make it! As I started to read it I thought it looked familiar. At that point I realised it was me doing the talk! So hopefully I will be able to make it :-)

The posting is here. If you come along make sure you say "Hello".

2008-12-16

Computer music

You may already know that I used to own a Commodore 64, and (as is nearly everyone else who ever owned one) I am still very passionate about the music people used to produce on it.

The question "Which was your favourite Commodore 64 tune" is a very hard one to answer as there are so many good ones out there, and people tend to go for the same short list "Delta", "Sanxion", etc.

However, recently I was creating some ambient background music for a presentation video. It started off a bit like a Jarre tune, but as I started to add in the percussion (for which I used samples of car doors slamming) it started to remind me of a tune from an old C64 game; "Tetris".

After downloading it and listening to it endlessly over and over as I write code I have come to a conclusion; TETRIS is my favourite C64 tune! It is just so unique, and unlike many other C64 tunes it hasn't aged, and doesn't actually sound that much like a C64 tune at all! Whenever I listen to it I feel like I am in the former USSR, building something out of strangely shaped bricks :-)

There's a (large) Mp3 of the tune here if you are interested.

Well done Wally Beben, you have in my opinion created a classic, and I will undoubtedly continue to enjoy it for many years to come. Actually, I am going to do a remix of it too, I hope he wont mind :-)

2008-12-15

FireBird - Did it burn me?

This morning I spent an hour on the phone to Microsoft support. I tried to log into my machine only to see the error message

The user profile service failed the logon.
User profile cannot be loaded.

The guy on the phone got me to put my Vista install DVD into the drive, boot from that, go to system-recovery, and revert to a restore point. Worked nicely.

The thing is, why did this happen? The only thing I can think of is the open source Firebird DB server. I installed it on Sunday to get an old app to run (installed as app, not service). I didn't install the control panel plugin due to a warning on the site telling me not to install it on Vista or it will trash my Control Panel.

I suppose the warning about the control panel should have been enough to put me off. Still, it works now. I just wont be installing it again, at least for some time.

2008-12-05

The importance of clarity

I wrote and now maintain a Pocket PC app for Imperial Tobacco (yes, despite supporting the ban on smoking in public places). It is important that the date/time on the PPC is accurate so part of the business flow is to get the user to check the date/time immediately after they log in.

Despite this step we were getting invalid dates back from their collected data, in all cases it was always one day ahead of the correct time. We have recently introduced various additional common sense checks such as "You have missed a working day, are you sure?" etc, but the change that will have the biggest affect is the one that was the smallest to change.

When the user enters the current date/time if it is less than the last known date/time on the server (sent in their database of work to do) I showed a message saying it was incorrect. The message read

"The date you have entered is invalid"

At this point the user looks at the date they have entered, thinks "but the date is right!", they click it forward a day and the PPC accepts it, so they continue with their work. Because I used the word "date" the user was blinkered to the value in the date, and didn't even bother looking at the time they had entered. The message now reads

"The date/time you have entered is invalid"

Hopefully this will be a bigger clue :-)

2008-12-01

The ubiquitous language

One of the most important things to do when designing a system for a customer is to to try create a common business language between you and the people who understand the problem domain. A lack of what is known as "the ubiquitous language" can result in misunderstandings and a failed project.

I had a real life experience of a ubiquitious language failure yesterday. My brother went to the shop to buy some credit for his phone and offered to take my children with him to buy sweets. When they got back my son asked me

"How come uncle Stephen was able to buy credit for his phone?"

When I asked what he was talking about he described the sign on the wall in the shop, it read

"Please do not ask for credit as refusal often offends"

2008-10-24

How I would like to write code

Aspect Oriented Programming looks great. It's something I have always wanted to use, but I avoid it because it doesn't work exactly how I would like it to. The first thing I want to avoid is lots of reflection at runtime (compile time is fine), it is for this reason I have mainly been interested in PostSharp.

PostSharp looks great! You decorate your class with attributes that you create yourself. After compiling your assembly PostSharp inspects the result for Attributes that are descended from one of its own special PostSharp AOP classes. When it sees these attributes it modifys your code in a specific way.

To use the same example as everyone else in the world (yawn) you could create an attribute from the method-boundard attribute. Override the methods declared on that attribute for entry/exit of the method, and write some code in there to write to the IDE's output window using System.Diagnostics.Debug.WriteLine(). Now when I add that attribute to a method on one of my classes I get that code injected into my method automatically

[Logging]
public void DoSomething()
{
}

would be the same as

public void DoSomething()
{
System.Diagnostics.Debug.WriteLine("Enter");
try
{
}
finally
{
System.Diagnostics.Debug.WriteLine("Exit");
}
}

So, this looks great, but what's so good / bad about it?

Good


On the good side it lets me describe code functionality rather than writing it. Instead of looking at loads of lines of code to see what something does we can look at a .NET attribute which simply tells us what generic task the class/method does. Take Assets as an example. An Asset is worth money so its location and movement history must always be tracked. To achieve this I would have assets always linked to an AssetHolder class...

Asset holder


Now, what qualifies as an asset holder? You could say that a person has an asset, a department could be using it, it could be in a stock room, or it could be out on hire to a customer.

Digressing slightly...Don't descend these classes from AssetHolder! Holding assets is something a person DOES, not something a person IS!

Person with asset holder


Now my Person class can hold assets. I can obtain its AssetHolder instance via its IAssetHolder interface, from there I can create AssetTransfer instances and so on. Now I have to implement the same thing for Department, Room, and Customer! Wouldn't it be nice if I could just do this?

[AssetHolder]
public class Person { }

[AssetHolder]
public class Department { }

[AssetHolder]
public class Room { }

[AssetHolder]
public class Customer { }

That's the good side of PostSharp. I could create an AOP attribute called "AssetHolderAttribute" and then build my business classes with that attribute adorning them. After a successful compilation PostSharp would discover these attributes and do the following to each of my classes

01: Add a member AssetHolder to the class.
02: Ensure that member is created within the constructor.
03: Implement IAssetHolder, returning this new member from the GetAssetHolder method

What we have is a very small amount of code (two words stuck together, wrapped in a pair of square brackets) which not only clearly identifies a feature of these classes, but even implements it

Bad


This is the only thing that is stopping me from using this approach to write applications. PostSharp cannot add the code until after the assembly has finished compiling. This means that an assembly consuming the business classes can easily write code such as

IAssetHolder holder = (IAssetHolder)person;

but code within the same assembly as the Person class cannot, because Person does not implement IAssetHolder until after the assembly has successfully compiled. A catch-22 situation!

How I would like to write code


I would love to see pre-compile time support for AOP, so that it feels like part of the development experience rather than like something that has been bolted onto my binary afterwards. Instead of a UML diagramming tool to help me to design my complex models, what I would like to do is to use the diagramming tool to design patterns that occur frequently in applications (archetypes), and then in simple code decorate my classes to identify what they are capable of...

[BusinessObject] //Adds persistence capability using your favourite framework
[AssetHolder] //Responsible for holding assets
[StockHolder] //Responsible for holding stock
[RoleHolder] //Can be assigned roles, such as Customer, Supplier, etc
public class Person
{
[DataMember] //This property is persistent
public string FirstName { get; set; }
}

//I could now write code like this
Person p = new Person(EcoSpace);
decimal heldValue = p.AssetHolder.GetHeldAssetValue();
heldValue += p.StockHolder.GetHeldStockValue();

Or for defining the model itself using simple code...

[BusinessObject]
public class PurchaseOrder
{
//Persistent property that is an AutoIncrementing column in the DB
[DataMember(SaveAction = SaveActionKind.DbAssigned)]
public int OrderNumber { get; private set; }
}

[BusinessObject]
public PurchaseOrderLine
{
//Also adds a property to PurchaseOrder called "Lines"
[Association(Aggregation = AggregationKind.Composite, OtherEndName="Lines")]
public PurchaseOrder Order {get; set; }
}

//I could now write code like this
var order = new PurchaseOrder(EcoSpace);
var line = new PurchaseOrderLine(EcoSpace);
line.Order = order;

//AOP created property "PurchaseOrder.Lines"!
if (order.Lines.Count != 1 || order.Lines[0] != line)
throw new ........

The future


I really hope to see pre-compiler support for AOP in the future in C#. I've been working on one of the guys at RemObjects recently who writes the Oxygene .NET language compiler (formerly known to me as "Chrome"). I have always thought their language has some really nice features in it, but never started using it because of two reasons

01: No ECO support.
02: I wanted to stay in C# to keep my skills more "main-stream".

Oxygene support is being worked on in ECO 5, which only leaves the second point. I really like some of their features as I said, but not quite enough to make me switch. However, if you are going to gain massively from working in a less popular language then switching to that language is the right thing to do, and this would be that feature for me! If in the future I need a C# job I believe my skills will remain current enough to be able to not exclude me from this part of the job market.

In the meantime I will continue to use C# and hope that some relentless annoying nagging will get me what I want on the Oxygene front, and that my dream of writing solid reliable code with very little effort takes that big leap towards becoming a reality! :-)