How I took on a migration and ended up with a tree

Non binary decision tree

A task which fell into my lap recently gave opportunity to an interesting design exercise. The customer had a Windows application in production that – after a few spins around the incident tracking system – was deemed to belong to my team. We knew it existed, but not much more than that. It had run rather smoothly for years, but now it needed to be migrated, and the lucky shepherd to herd this lump of (actually rather well written) Visual Basic 6 code into the future was, it turned out, me.

Oh, for a clean slate…

The code base was not only old but incomplete, so the first decision that had to be made was whether to rewrite the whole thing (except for the old, gray, dependable GUI – that would have to be kept more or less intact). It is a tantalising idea that we developers tend to put more than a bit of wishful thinking into, as we curse systems riddled with technical debt – if only I could start over, redesign this whole mess…

Compromises

The allure of the empty page pushes away the knowledge of all those nasty little obstacles that inevitably will pop up along the way: Perhaps the application is dependent on some maze-like database, or a creaky old transaction handling system, or a brand new, super-hyped and completely bug infested system or technology that the customer just has to have. All these things forces compromises, and suddenly implementing that stream-lined design we dreamed up is not so simple anymore.

(Don’t get me wrong: compromises have to be made, and more importantly (but not at all as fun) remade, re-evaluated and refactored, if we are to ward of the spectre of mounting technical debt. This is fundamental, and a good test of the robustness of the initial design idea.)

OK, then, so a clean tree at least?

In this instance, though, the decision was more and less made for us by the incomplete codebase. Moreover, it was a contained, stand-alone application that could go from unmaintainable to easily incorporated in the team’s responsibilities. The GUI was made in Windows Forms, its’ menu a non-binary tree structure with different kinds of business related information depending on the level of the node. The original design was not object oriented, operations was made independently and then tucked into a Windows Forms TreeView, the assembly of which was complicated and hard to survey. Copying the GUI and connecting the wires to some fresh C# code seemed to be the easiest way forward.

My first intuition was to implement my own tree structure, specialised to the specific requirements of the client. It’s the kind of exercise that your computer science professor would send home with you: nice, clean and simple. Something like;

delegate void NodeAction<T>(T nodeData);

public class Node<T>{

private T nodeData;
private List<Node<T>> children;
public Tree(T nodeData){

this.nodeData = nodeData;
this.children = new List<Node>();
}

public void traverseTree(Node node, NodeAction action){

action(node.nodeData);
foreach(Node child in children){
traverseTree (child, action);
}

}

In fact, I think that my first run-in with recursion was in school while implementing something similar, possibly a LinkedList. (Speaking of which, a LinkedList would perhaps be a better choice for storing the child nodes.)

Reinventing the wheel

The idea was to start with this new tree as a base for the coming implementation of business logic – I even started creating classes before I got one of those Forrest Gump moments that happen so often in software development. I looked at my sweet, simple sapling of a tree structure. Then I looked at the TreeView that would display the lot in the GUI, with its list of children, its Find() function wich accepted delegates as inparameters, its myriad of other options that teams of designers had added over time… My brain went “I am not a smart man” in Tom Hanks’s voice (woman, but it still applies). Then I wrote

public partial class CustomTreeView : TreeView

and

public abstract class Selectable : TreeNode

Parents and children

By creating the abstract class Selectable, child to Windows Forms’ native TreeNode and parent to all my different versions of nodes, I got what I needed and then some. In the same way, a parent dialog handler class gave birth to different flavours of dialog handlers depending on what each level of the tree needed (the contents was displayed in another, more user friendly view).

It may seem like a crazy idea to trim down an application until all that’s left is a tree and some handlers, but in fact, it was a very logical structuring of the business information. I created some data carrying classes that the nodes would handle, hid away calls to the database so they wouldn’t be accidentally tampered with if the tree needed to be modified (or rather, extended, if we are to be strict about the open/closed principle, which we should), and found myself with a functioning copy of the original application.

Summary

Sometimes, the simpler solution is the better. Using abstract superclasses and interfaces generously meant that I could write a very generic main form and trim away literal meters of duplicated old VB6 code, and the result was much slimmer and easier to understand.

So this was the last thing I did before going on summer vacation: I went at it with my figurative pruning shears, and left behind – a tree.

Dela:

Relaterade inlägg ↓