Friday, September 29, 2006

Google Reader Update

Google has updated their RSS reader. I liked what they had before, but the new features are pretty cool. They had "starred" items (i.e. items you wanted to keep track of for later which you can see in the sidebar of this blog, but now there's a new feature called "shared" items. This is like a poor man's plagaristic blog. You can even add an rss feed for your shared items.

Overall, I'm very happy with it. I tried several readers before going with Google's. I normally use two or three different computers each day, so it's really nice to have all my feeds synced.

Check it out if you're looking for a reader.

Thursday, September 28, 2006

Windows Live Writer Test Post

With images no less!

This picture or Richard was from summer camp last July. I believe this was on the Nantahala river.

Wednesday, September 20, 2006

VMWare Appliances

I've installed the (free) VMWare server on my development server at home and I frequently use a couple of their appliances on it. Specifically:
  • Twiki - This is an awesome idea to be able to install and use TWiki without all the hassles of getting it going on a server. Especially if your server is Windows based. This appliance already has Samba installed, so getting files on and off the box is very simple, as are backups. It also sets itself up with a netbios name, so connecting to it is cake.
  • Helix - This has Trac installed along with subversion. Two very nice tools for managing development. I'm currently only using subversion (since Trac is a little over the top for what I do by myself).
I've installed the Twiki appliance at work, and converted some fairly old (2+ year old version of Twiki) data to the new appliance. This took about 3 hours in all to do.

Overall, I'm very happy with this tool as a solution.

Tests Don't Save You From Being Stupid

Originally Posted On: DATE: 08/29/2005 04:18:31

A couple of weeks back I worked on adding some new capabilities to a software system at work called the `listener'. Essentially, this software receives socket messages (events), assembles, parses (from various protocols), generates `model' events, and passes these off to a subsystem to let various business logic handlers deal with the events and do interesting things with them. The piping internal to the system to move events around includes (among other things) the Visitor Pattern, which is normally very explicit about not being able to handle a new type if a new type has been added.

The capabilities I needed to add depended on creating a new event type that the visitor pattern would pass to the appropriate handler on the back end (like visitor patterns do). I built the acceptance test, ran it, watched everything fail as I expected, then got into modifying the interfaces to force the creation of the new event type, and force the various implementations to implement a `visit' method for the new event. All of this went swimmingly, and after working for about three or four hours, I had the whole system back together with new UT's for the classes that needed changed, and with the original AT that started the whole thing working.

So, I had added about 50 UTs, and about 3 ATs and everything looked copacetic. I took the finished code off to run it on a test system with real data.

It didn't work.

After spending a couple of hours digging through the logs, tests, and finally the code, I found that when we built the system, we had added a base class beneath some of the implementations of the visitor for some reason. This base class provided default behavior for unknown types coming in. Since this base class was embedded in the plumbing, the default handler was taking the new event type, and wasn't letting it get to the endpoint implementation, so the new event wasn't being handled. Once I found that, I found several tests that I had missed on the first pass through the system that would have pointed out these problems, but I had glossed over them.

If I knew then what I know now, I'd:
  • Make sure that if I'm using Visitor, I make the compiler warn me about problems. The fact that I'm using Visitor means that I'm SURE I'll be adding new types. Let the compiler do its job when the types aren't wired up correctly.
  • If there is a compelling reason to stick a base class in there (i.e. a default visit handler), add a test that does reflection to count the number of visit types between the end point implementations and the interface. This might be a little hairy, but the 2-3 hours spent will save me several times in the future.
  • If you're in a situation like this, and the base class is causing you pain, remove the base class.

It was a good learning experience. It just points out once again that hindsight is awesome.

Kent Beck / Alan Cooper Smackdown

Originally Posted On: 08/22/2005 09:11:55


I read a very interesting article today. One of the most interesting things I've read in the last several months. I completely agree with Beck that the XP methodologies would work best and provide a nice process for solving the difficult problems of software development, but my experience has been that getting a "customer" is one of the most painfully difficult things there is. In my experience, it's NEVER been successful for more than a few weeks. I had lunch with some XPers from GSK (GalaxoSmithKline) a couple of weeks ago, and their experience mirrored mine.

Computer Science Challenge List

Originally Posted On: 06/20/2005 03:05:45

Several years ago, I found a document called Challenges for Theoretical Computer Science.  It describes a bunch of 'challenges' that haven't been solved in the computer science area.  The information written in this list is 5+ years old now, and it's amazing how many items on the list are still outstanding.  I don't claim to be able to understand all of the challenges (like 'Make Quantum Computing a Reality'), but there are a lot of them that apply directly to TDD methodoligies (like 'Software Specification').  It would be interesting to track this list (or one like it) over many years.


I think it's useful to take a step back every once in a while and see where we've come, and where we're headed.  A couple of useful things can come out of it:

  • Correction/Validataion of your current course.

  • Realization that most problems have been around longer than our recognition of them, and that some smart people may have spent time thinking about them.

  • Insight into a problem outside of your current vicinity can give a great new angle on your immediate problem.

  • New product ideas.  You may have the insight to solve some problem that nobody else has.

Mickey Mouse Show

Originally Posted On: 06/17/2005 04:22:42
Rob Selph commented to me that he liked the name of the blog, but that I should explain a little about the name. My name is Mark Mackelprang, and with a last name like that, the blog name is pretty natural.  Growing up, it was intimidating to learn to spell an 11-character surname, so my older sister came up with a nice mnemonic trick to do it. I just so happens that there are also 11 characters in the name "Mickey Mouse", and it just so happens that the cadence and flow of the letters is very similar if you sing the Mickey Mouse Club Theme Song with the letters of my last name (What's the surname we adore that's made for you and me? M - A - C - K - E - L - P - R - A - N - G...). It's how I learned it, how my wife and kids learned it, and it's how I teach people I meet now to remember to spell it. Songs are amazing tools for learning things.

Namespace Refactoring

Originally Posted On: 06/16/2005 12:05:04
Over the last week or so, I've spend some time refactoring some namespaces in the C# codebase at work. There were some things that had just been languishing in the wrong
place for a long time. We had a few days to spend cleaning up things that we normally have to live with, so this is one of the things we decided to fix. Like any other refactoring, NS refactoring shouldn't change any system functionality, but just improve the overall design. It's a lot like renaming a class, and maybe it boils down to the exact same thing in the end. Luckily, this codebase is well covered with tests. We have unit tests (class level functionality), acceptance tests (system or subsystem level functionality), and smoke tests (installation functionality).

This process would have taken many times longer with much higher risks without the tests. Even with these tests, there was plenty of pain to feel. I'm a sharing kind of guy, so here's what hurt:

  • File Names: Don't ever use a object type for any part of a configuration file, log (thanks to Andy Sipe for the catch here) file, etc. For the actual code itself, there isn't a problem since all you have to do is rename the file. Whenever the config or logfile depends on the namespace, however, there are several locations you have to go to fix things up again. This bubbles through the system, and clear up to the install process. For upgrades, there will be difficulties merging from old to new when configuration file names change from version to version. For me, it helped to think about the fully qualified type as a unique ID in the db. Whenever that ID is used for something other than identity, trouble follows. The same is true for types. The rule here is name all files after their intended use, not after their location or namespace.

  • Object Identifiers: We used a persistable object layer to insulate the code from the db in the system. When we implemented the object identifier subsystem, we had the object ID's generated from the type of the object. This means that we had an OID table in the database, with type names in one of the columns. This makes the design very resistant to NS refactoring, since it would require a db upgrade to change the code. We ended up putting a mapping layer in the OID layer that takes a type and returns the "name" of the OID object to use. For now, we're using the "old" OID names to prevent an immediate database upgrade. In a future refactoring, that's another thing we'll want to fix.

  • Configuration File Locations: Use the "once and only once" (DRY) principle ruthlessly when setting up config files. We use VSS (don't start with me) and had originally shared various files between all of the projects that needed them. After going through the process of NS refactoring, I believe the correct way to do this would be to store any shared configuration files in a single location, then make it part of the build process (NAnt) to copy the configuration file from the one location to the test location before running the test. For files that are used only once, put them where they're used, but if they ever become shared, spend the time to put them in the single location, and change the build/test to get them there.

  • Tests: Don't even try to do this over a large set of files without good tests around them. The unit tests aren't really useful for this refactoring. The compiler tells you most of the errors that are at this level. The acceptance tests are good since they pull all the parts of the system together, but they can be fairly long running (some of ours take many minutes to run). The best tests for this kind of refactoring are the smoke tests. These validate the installation for the various end products, and generally only take a few seconds to run for each one (plus file copy & startup time).

  • Conclusion: Overall I think this kind of maintenance should be a regular activity.  Company names change, the overall design change.  Failure to update the NS is another "broken window" or "smell" that Andy Hunt and Dave Thomas mention in their Pragmatic Programming book.

Tuesday, September 19, 2006

Trying out Blogger...

Instead of hosting my blog on my home computer, I'm seriously thinking about simplifying things and using Blogger. We'll see how hard it is to import everything into it before I make any permanent decisions...