I could slap myself for not thinking of this sooner.

I have a list. I need to filter said list destructively (ie: modify the provided reference and not return a new list as a function result), and remove items which don’t meet criteria X.
My first dig at the code uses a for-loop and adds items to a second collection when the sub-item meets the criteria. Need to manage the incoming list, a new list and make sure i’ve overwritten the list reference at the end. Messy and as i discovered, error-prone

or….use a for-loop, and count backwards from Length to 0 and delete as i go.

stupido!

When retrofitting tests, should my test cases be designed around code behaviour (ie: what the code is actually doing) or user cases (ie: as if i’d written the code TDD to begin with)?

I’ve been investigating a bug in one of our products which has inherited code written over 10 years ago. The application is written in Delphi, and the one thing i’ve more recently learnt (and realised i’ve taken for granted) are development tools and paradigms we’re used to in .NET land, but scarcely exist in Delphi mainly as a combination of the differences between the languages/environments and the depleting community. Still, the fundamental programming challenges we face are similar, if not the same.

In this instance, I identified the bug to be incorrect logic in an IF statement, nested deep within a highly coupled, highly dependent, impossibly tricky to test procedure.

function TDatabaseModel.GetActionsForLastSessionByHardware(const AUserUID: string; AHardwareID: string): TDBObjectList;
var
  User: TUser;
  MostRecentSession: TSession;
  Action: TAction;
  ActionItems: TDBObjectList;
  I: Integer;
begin
  Result := nil;

  User := DBAccess.GetUserAndSessionsFromDB(AUserUID) as TUser;

  if Assigned(User) then
  begin
    User.Sessions.Sort(SessionSortComparer);
    if User.Sessions.Count > 0 then
    begin
      MostRecentSession := User.Sessions.Items[0] as TSession;
      
      for I := 0 to MostRecentSession.Actions.Count - 1 do
      begin
        Action := MostRecentSession.Actions.Items[I] as TAction;

        if Action.T_HardwareID = AHardwareStringID then
        begin
          ActionItems := DBAccess.GetActionItemsAndAssociatedObjects(Action.UIDString);
          Result := ActionItems;
        end;
      end;
    end
  end;
end;

In a nutshell, this code is dependent on a data access object to query a SQL datastore and get the results as heavy business-objects (not light-weight containers). Once it finds the particular object it needs, it performs an IF comparison on one of the properties to check that particular values are equal. This condition is the one with the bug. Rather than check for equality on these values, there is some logic behind whether the two values are compatible, so straight equality is insufficient.

Having identified the bug, my objective is to expose the bug from a unit test and then provide a fix. The question was – what’s the *right* way to test this?

  1. I can mock out the data access classes and manually inject my mock in testing. In .NET this is insanely easy with Rhino Mocks (for instance). With Delphi, it’s quite painful because there being no runtime environment, means there is no automatic proxy generation. So i’d have to extract the interface by hand (no ReSharper, remember?), statically define my mock object and hard-code any expectations. Oh and there are some idiosyncrasies when working with interfaces in Delphi, because they’re not strictly first-class language citizens. There are means by which the pain could be reduced, but it’s a lot of work
  2. Write an end-to-end test which sets up test data, sets up a valid query and then gets real data from the database. I then need to write several assertions that under different combinations of data, the IF statement reacts appropriately. This is possibly the least likely option given that it is highly dependent on database querying and if getting a Mock to work is tough, then this is like banging my head against a brick wall. Pass.
  3. Create a protected method, refactor the IF logic into the protected, and expose it through a subclass created for testing purposes. This contains minimal impact and will allow me to directly test that the logic used to determine compatibility between the values. It doesn’t test that the original method actually CALLS my logic, but the fix is implied because the test still exposes the problem (and makes the code more expressive)

Having unconvincingly decided in my mind to go with option 3, my code was looking like this, and I was still quite uncomfortable about it because the test is now brittle and not refactor friendly.


function TDatabaseModel.HardwareIsCompatible(AFirstHW, ASecondHW: String): Boolean;
var
  Converter: TConverter;
begin
  Converter := TConverter.Create;
  Result := Converter.CanConvertToBetweenTypes(AFirstHW, ASecondHW);
  FreeAndNil(Converter);
end;

//...and in the original method:

if HardwareIsCompatible(Action.T_HardwareID, AHardwareStringID) then
  begin
    ActionItems := DBAccess.GetActionItemsAndAssociatedObjects(Action.UIDString);
    Result := ActionItems;
  end;

I talked to one of my colleagues about my situation and he had some good advice – that I shouldn’t let the imperfection of testing stop me from testing at all. The basic premise behind the very excellent book Working With Legacy Code by Michael Feathers is that when you have legacy codebase with no tests, the first thing is to do whatever you can to get tests in. Once the tests are there, you can refactor to make the code better and more testable, but without something there to begin with, you’re only making it worse.

So that’s what I did. I put the test in, fixed the bug and life goes on. Moral of the story – When retrofitting tests do whatever is necessary as a first measure. However, i’m interested now to improve the mock generation features in Delphi….Will have to look into this at some point.

By default, skype grabs a hold on incoming requests on port 80, and 443 (https) presumably as a measure to bust through firewalls.

This causes problems when you’re trying to configure IIS.

Moral: If you’re installing IIS and you have Skype running, you should turn off the option in Skype to listen to incoming requests on port 80 and 443

having freshly reinstalled Vista Ultimate on my work laptop, Windows update feels it necessary that i download and install 4 language packs for my operating system. I doubt i’ll ever learn Latvian or Swedish anytime soon so having these items litter my update screen irritated me, but I didn’t know of any way to hide them.

This morning, a colleague showed me a way to hide individual updates in Windows Update if you don’t want them. To hide, simply right-click on each individual update item and select “Hide Update”, as per the screenshot below.
NB: You will have to do this for each item – there is no way of bulk-selecting items (that i know of)
NB2: Once you hie an item, you can’t unhide it unless there is a further update to the hidden item from Microsoft.

This week I was lucky enough to buy an HTC Touch Diamond. This phone runs the latest revision of Windows Mobile (6.1), and is customised so that HTC’s custom developed TouchFlow3D user experience replaces the standard Today screen in WM. In a nut-shell, TouchFlow3D is the sexy user interface with swishing windows, 3d text, fading, animating etc…

Being the self-respecting geek that I am, i spent the first day transferring all my files and contacts to the device and familiarising myself with the phone. I’ve spent subsequent days since then trawling the forums to discover ways of customising and hacking the device. Writing .NET apps for the device isn’t terribly tricky – I have all the tools and skills to do that, and am more interested in understanding how to create slick looking applets for TF3D.

In this post (and maybe subsequent ones) i’ll be jotting down some important points that i’ve discovered. One this that frustrates me is that despite having a very active hacker community, some members of the forum seem more interested in showing off their abilities and holding back information and source examples in an effort to control the crowd. I find this stifling and stupid so i’ll be writing everything I think can help. (NB: This post won’t be targeted at beginners. It’s aimed for people who have a little knowledge about the entire system and find that there are gaps that need filling)

So i’ll start with this aggregate post which summarises how to create TouchFlo3D themes.

Manila File Definition
090661f7_manila = Tab “Display names”
26948339_manila = Tab Definitions (This is the “master” file – sometimes invalidly referred to as “manila.xml”)

For more manila definitions, see Manila_Research

Downloads
I won’t link to the actual posts or upload the utilities here (mainly because i’m lazy) but the following tools are used to reverse engineer TouchFlo3D. If anyone is interested in downloading these tools, just google the filename.

  • ManilaReverserPack.zip – Used to disassemble the .luac compiled LUA scripts
  • Manila Editor v.0.2.zip – Used to modify and update manila files for theme editing