Well I’d have to say I haven’t had so much fun for ages. Playing with familiar stuff (and some less familiar stuff) has revived my joy of writing complicated algorithms and creating useful utilities. It’s almost like being back in the old days of creating COM components for classic ASP web sites to do the things that VBScript couldn’t do. I even got to write some more VBScript – and, yes, it was a politically correct circumstance ‘cos I was executing it through Windows Script Host.
Over the past few months I’ve been revisiting some old utilities I created – in some cases years ago – that would actually be useful again. For example, I now have a dual failover Internet connection (ADSL and cable) so if the ADSL fails, which it does fairly regularly, I don’t get to know that the local village and parish web sites I host are offline until the condescending emails start to arrive.
So I revived an old web site checking utility and updated it to VS 2008. By running it on an internal machine, and going out on the cable and back on ADSL, it gives me a proverbial nudge when the ADSL line is down. It just needed some fettling to resolve a few poor code practices applied at the time, a few extensions to make it do additional things, and a UI makeover to make it seem less amateur (though with my design skills, I probably only managed to make it contemporary with the late 20th century).
However, prompted by this flush of success, I expanded the log file monitor that I threw together some time ago to try and fend off the DNS amplification attacks I was suffering at the time. Now it monitors DNS, WWW, and SMTP logs with a broad range of search options. It can also send email notifications and execute scripts or programs. I use this feature to execute the aforementioned VBScript script to automatically create and manage IP address blocking rules in Windows Firewall (WFWAS).
Finally, I decided to tackle the problem of synchronizing specific sets of files between two machines. Yes, I know there are several ways you can do it in the O/S and with other utilities, but I wanted to be able to view and control the process in several specific ways. It comes about because I have a computer that contains the set of folders and files synchronized with Team Foundation Server (TFS), but I tend to work on other computers with individual subsets of these files. It’s also made more complex by the fact that the files are read-only in TFS when not checked out, and the file date controls whether files are updated in TFS when you synchronize.
The idea was to be able to see the two sets of files (local and TFS) with information about the date/time, archive status, relative path, read-only setting, and easily see which were newer than the equivalent in the other location. I also wanted to be able to copy, synchronize, merge, delete, and set the last-modified date with one click. The result saves me loads of time and effort, and probably helps to avoid errors when managing the files. OK, so I probably won’t be subjecting the source to a proper code review, but there are only a few bits left in there that I’m embarrassed about.
If you want a copy of any of these, you can download them here. I’ve even included the VS2008 source code so you can see what they are doing – as long as you promise not to show it to anyone (or laugh)…
But I suppose the real reason for all this rambling scribble is that, during the process, I realized just how much fun basic task programming really is. It’s like discovering the old home computers all over again, but much easier this time round. It really is amazing how .NET and the powerful framework classes save a ton of effort. I’m by no means a virtuoso programmer compared to most of my learned colleagues, but having things like complex conditional statements, capabilities such as generic lists, and features such as simple file and folder handling functions available really makes it easy to concentrate on the algorithmic logic rather than worrying about file modes and array indexes.
And, because my history in languages pretty much follows the evolution of Pascal, Delphi, classic ASP, VB for Applications, and Visual Basic as far back as version 1.0, I’m still most comfortable using VB.NET. While almost everything I do in my p&p day-to-day work is C#, I still find VB easier to read and write, and I love the way it does all the magic indenting and formatting for me. And, of course, it runs just as fast as C# (as long as you write good code) so I now only feel like a one-and-a-halfth-class citizen in our wonderful world of technology, rather than the second-class citizen I was before the advent of .NET.
What continues to amaze me, however, is how – after I agonize about every minor instruction I need to add to make the algorithms work, and every extra conditional statement they require to cope with the increasing complexity as I decide to add yet another configuration option or code tweak – they still seem to execute in the blink of an eye. I mean, you’d expect that parsing a web log file when the decision tree takes up a whole page in Visio would take a week to run. Or than reading two folder trees to build the lists of files and doing all kinds of comparisons before displaying them in two DataGridView controls would leave you time to make coffee, eat the remains of that cold pizza, and finish the crossword as well.
But, with the memory and processing speed available on modern computers, everything just seems to fly. I’m expecting it to splutter and crawl like a caterpillar in custard, but instead it dances like a cat on a hot tin roof. Even my VBScript script that updates Windows Firewall runs so fast that the screen update can’t keep up with it. I ran it three times wondering why it wasn’t working, and only discovered it was when I looked at the log file…
Maybe I’m picking up some good programming habits from the plethora of clever code I encounter every day in my proper job. Perhaps the constant exposure to design patterns, extensible code techniques, and the latest features of the framework are gradually permeating my aging brain. Or is it just that a quad-core Xeon box with 8 GB of memory can eat any code I throw at it without even blinking? Does replacing my complex sets of arrays with generic lists of custom classes, and my Ands with AndAlsos in the appropriate places, really have any discernable effect on execution time? Or am I just pandering to the typical programmers’ paranoia of wasting any of those valuable execution cycles?
But there is always that wonderful warm glow inside when, after pondering over recalcitrant algorithmic constructs for ages, it all works as though it was written by somebody who actually knows what they’re doing. And, anyway, I have to stop writing now. I need to think up some more exciting new and totally unnecessary features to add…