Wednesday, November 10, 2004

In the 'for what it's worth' category

I've been going over some older code I've written (more than 2 years old) and comparing it with more recent code. In a purely subjective judgement I think much of my recent code is much more OO than previous code.

For example, say I'm writing a class that performs some lengthy operation in a separate thread where there's a need to periodically inform the containing application of progress. The way I used to do it was to add a window handle, and a custom message code to the class and post messages as necessary. In other words, I'd build into the object the assumption of a specific notification method with no easy way to change the behaviour.

These days I do the same thing by calling a virtual function passing the notification message and expect the user of the class to write a derived class that does application specific things with the notification message. Simple and obvious huh? With my 20/20 hindsight yes, but it's taken a while to get there. and I attribute the change to my writing articles for CodeProject. The fact is that when you know your article is going to be picked apart by a ravenous mob of bloodthirsty nit-pickers it concentrates the mind wonderfully!

Saturday, November 06, 2004

You just never know

Yesterday I posted another article on CodeProject[^], about an encryption scheme I wrote 5 or so years ago for an IRC chat client and matching game software. I wrote most of the article a year or more ago but always felt nervous about publishing it. Why? A couple of reasons. The first is that I'm no cryptographer. I've read just enough of the literature on the subject to be completely certain of that . So there was a certain amount of diffidence about putting a simple XOR encryption scheme up for public scrutiny and ridicule. The second reason is that I take considerable pride in my involvement with CodeProject and am proud that most of my articles have high ratings. I wasn't convinced that this latest effort would rate all that well.

It's early days yet but the rating so far amazes me. 4.94/5 with 8 votes.

This brings up a whole bunch of philosophical issues. I've seen writers on CodeProject protest that they don't care what the ratings are. I've even indulged in that high minded sentiment myself at least once. But I don't really believe that. I write articles published on CodeProject because I want to share knowledge and experience but also because I want to show people what a clever bastard I can be . It's also a real pleasure when people write complimentary comments at the end of the article.

Ego? Of course. But why else would anyone other than Albert Schweitzer write 31 articles for no payment? And never underrate the power of constructive ego.

Monday, October 18, 2004

Sometimes it pays to have to pay for something

Today my inbox had about 35 spam emails in it. That may not sound like a lot but this is after we added the cox.net spam filtering service to our email. Before then it ran 150 or so a day.

Anyway this got me thinking about unwanted communications and how it relates to the financial cost of communicationg.

On my first visit to the US way back in 1982 I remember reading through the terms and conditions, in my hotel room, printed in the local phone book. Let's not go into why I was reading the phone book . I remember being surprised that the residential plans involved a flat fee and unlimited calls. By contrast, the plans offered by Telecom Australia at the time were a fixed fee plus so many cents per local call (and still are so far as I know). At the time and for many years afterward my thinking was that the Australian model was rather expensive by comparison with the US model.

Fast forward to 2002. I've now married a US citizen and migrated to the US. On my second day in the country the phone rang and I answered. A recorded message ran something like this: 'This is so and so. Please hold the line until one of our operators is available'. So and so was a well known telemarketing company (and the only reason I'm using the phrase so and so is because I can't remember who the so and so's were!). I was outraged! These bastards ring me and they want me to wait for THEM? I hung up immediately.

In the following months I think I must have fielded a couple of thousand such calls (I was unemployed for quite a while). Fortunately, the Do Not Call list does seem to work - the number of calls has dropped dramatically since the DNC list kicked in. I might add that I entered our number in the DNC list when it was announced.

Contrast that with my experience in Australia where you pay so many cents per local call. Back there almost the only unsolicited marketing calls you get are from the phone companies because they're the only ones who get essentially free calls. Every other marketing organisation has to justify the price of each call. I'm not sure on the commercial rates; the only price I know is 22 cents per untimed local call from a residential phone. But even assuming commercial discounts down to, say, 10 cents per call, it wouldn't take long for a company to rack up a large phone bill.

The analogy with email spam should be obvious.

Sunday, October 03, 2004

Professionalism

or lack thereof.

As some of you know, I've just got back from a longish stint in the Philippines, on our customers site. They had a long list of wants/needs/demands for us. Most of the list concerned functionality - the usual list of suspects. A report was missing this item, there were too many steps needed to accomplish that, etc etc. As I say, the usual list of suspects.

But there was one item that surprised me. They wanted a full revision list - which versions of the software contained what enhancement, bug fix etc. It wasn't the request that surprised me though, what surprised me is that we were unable to comply. Why? Because my predecessor had never bothered to update the version resource in the executable. Our product contains as of now about a dozen executables and DLL's. One or two of them have version 2.2.0.0 and all the rest have version 1.0.0.1 in the resource. Does that 1.0.0.1 look familiar?

So, starting from September 30th, all our products will have a version number, easily accessible, of the form X.X.X.YMMDD where the X's are enhancement/version/bugfix related and the YMMDD part is the last 2 digits of the year (without a leading zero), the month and day on which the compile took place. At least then the customer will be able to look at the file and know if it dates from before or after my last stint with them.

But it gets worse. We use SourceSafe for version control. A good enough product for a small development site like ourselves (let's not get into THAT debate). SourceSafe does the usual expected things for a version control product. It lets you comment each check-in, provides the facility to have those comments embedded in the source code, lets you label releases - the usual suspects again. But when I examine the SourceSafe history what do I find? Nothing. Nada. Zip. I know checkins have taken place because I can see many different versions of each file. What I can't see is any indication, in human readable language, of what problem was resolved with each checkin. Nor can I see any version labels that would tell me that if I check out based on label X i'll get the version of the source code used to build the version that customer X has.

This is barely workable when you have just one developer with an extremely good memory. I have an extremely good memory for trivial detail but I don't rely on it to tell me that version x.xx checked in half a year ago contained a fix for bug y.yy. That's what SourceSafe (or any other source control system) is for. That's why I use SourceSafe at home for all my personal projects (and have done using one version control system or another since 1987). It becomes totally unworkable when you're handing responsibility for the code from the original developer to a new developer (me). I don't have the context.

Honestly, it puzzles me how anyone can produce software when the only clue they have as to which version they have is based on a guess from the timestamp on the file. It also puzzles me mightily how anyone can produce software with the attitude that a diff is good enough to tell them what changed. Yep, the diff tells them what changed but it won't tell them why.

After the foregoing would you be surprised to learn that the code contains almost no comments? I didn't think so.

I think this all comes down to an attitude of professionalism. My job as a developer isn't just to write code. My job is to design a maintainable and (hopefully) good solution to a problem whilst keeping future possibilities in mind. One of those future possibilities is where we might take the product. But, equally important, one of those future possibilities is that we might need to backtrack and revisit design decisions. How can we do that if we can't produce (and read easily) an audit trail of what we've done? And how can we possibly grow to cope with new business if all that knowledge is locked up in my skull?

Sunday, September 26, 2004

All programmers should be forced to do release builds!

So I'm still ploughing my way through this legacy application. I've finally got the thing to compile in release mode and now come the joys of getting it to actually work!

My predecessor, it seems, never did release builds. We only have a few copies of the app out there in the wild and they're all debug builds that 'work'. I have to say I was rather surprised at this and set myself the task of making the jump to always distributing release builds.

The first hurdle was to get the code to compile in release. Took a day or so of ensuring the right symbols were defined, the right compiler switches thrown and tracking down the odd ASSERT that was compiled away to nothing. (That in itself surprised me - I've never seen a code base so bare of ASSERTS - so bare in fact that it took a while to realise that what few there were were causing problems).

And now I have to track down why the damn thing doesn't actually work in release.

First problem is that my predecessor uses ints and shorts interchangeably. We have one function that retrieves a couple of numeric fields from a database as shorts and declares it's parameters as pointers to shorts. This is well and good except that the calling code is sprinkled with int declarations and to get the compiler to compile it he casts to (short *). Works ok in debug because the compiler obligingly sets his ints to zero before he uses em. In release you get garbage in the original int. The call to the database function gets what it believes is a pointer to a short and only sets the lower two bytes of the int. The upper two bytes are left as garbage and, as a result, the entire value is just plain wrong.

Aaarghhhhhhhh

Now before you ask, this is a VC6 app using MS STL. That makes it near impossible to use Warning Level 4. Once I get back to the US I'm going to move the app to VS.NET 2003 and invest the month it'll take to get clean compiles at Warning Level 4 with Warnings converted to Errors.

Saturday, September 25, 2004

You wouldn't think it'd be so bloody hard

to write a proper masked edit control. In principle you intercept the stream of characters being typed at the keyboard, apply your filter criteria to them, discard the ones that your mask disallows and let the others through. And in fact, it really is that simple - if all you do is watch what the user types. Override the WM_CHAR message and filter away.

But that ain't enough. You also have to be careful that your user can't paste data into the edit control that violates your mask criteria. And that's much more difficult to prevent. I'm experimenting with a mixture of WM_CHAR filtering as aforesaid, plus WM_PASTE filtering where I pick the data off the clipboard, examine each character and post a WM_CHAR message to myself for each valid character. Of course I know this is going to bite me in the bum the first time someone tries to use the control on a non-US Windows system but I'll worry about that once I go home.

Wednesday, September 22, 2004

Doh!

I've just wasted an hour solving a small problem. The app uses a local path and a remote path - both these are stored in the registry and read on the fly as needed. I needed to activate the remote path (there's logic to test if the remote path exists - if not we use the local path). So I created the necessary key and set the path and... nothing! The app used the local path. So I fired up the debugger and traced the code. Sure enough, when the app tried to retrieve the remote path it came back with nothing and used the local path. Tracing into the Win32 call that reads the remote path it was returning PATH NOT FOUND for the remote path key but finding the local path key just fine. But they're both there! A careful check of the spelling of the keyname - they match. Delete the key and recreate it using cut and paste to copy the keyname from the source code to the registry. Still not found!

So then I tried a different approach. I could read the local path entry but not the remote path entry. Ok, so I changed the local path entry to a different value and traced again. It didn't change. By this time I'm scratching my head. So it's off to the MSDN Knowledge base for anything about registry value caching. Nothing useful popped up. And then....

My eye wandered a branch or two above the branch I had been looking at, in regedit. And there were TWO registry branches for my apps key.

It turns out that the guy who wrote this code (I've inherited it) had made a copy of our products registry tree, appending a dot to the name. And you guessed it, I'd been making all my changes in the copy.

Doh!!!!

Tuesday, September 14, 2004

Acronyms

I'm on site at Texas Instruments (Philippines) Incorporated. TI refer to the location as TIPI and pronounce it 'tippy'. I discover that they also have a site in Taiwan called Texas Instruments (Taiwan) Incorporated. You can imagine my disappointment when I learned they don't use the obvious acronym :-)

Sunday, September 12, 2004

More memory leaks

Toward the end of 1996 I was seconded to a team of developers writing a database management system. The project was to run on Windows NT 4, was written in C++ and used an object oriented database (remember those?). Anyway, the majority of the other developers (all 5 of em) had a strong UNIX/C++ background whilst I had a strong Windows background, which is why I was seconded.

The database leaked memory like a sieve. I'm not kidding when I say that after running a single query and terminating the program the debugger took between 15 and 20 minutes to print out all the memory leaks. Most of the developers simply pressed the 'Stop' button on the debugger to terminate the program immediately rather than let the memory allocator print out it's diagnostics.

I asked them why they didn't fix the leaks. The first answer was that it wasn't their code, it was Windows! If it had been running on UNIX the operating system would handle it so it was obviously Windows fault. Hmm, I never did manage to convince em they were wrong on that one. The second answer was that they were only small leaks, only a few bytes per leak and any decent VM system should be able to handle that. Yes, they were only small leaks, millions of the buggers!

We had the source code to the database but it was 'too hard' to go in and fix the leaks. Now remember, this is 1996 when 128 Megs of memory in your machine put you into the power user category, and NT took about 90 of those megs. With nothing else but our app running it took about 25 queries to leak enough memory that swapping kicked in.

Their solution? They wrapped all the database code into a seperate executable and launched it for every single query. That way the database could leak all the memory it wanted; Windows would clean up after it. Of course, performance suffered but we developers were running on the latest and greatest Pentium systems so it wouldn't hurt us! Only the poor customer who still nursed hopes of getting reasonable performance on a 66 MHz 486. (I hope the sarcasm is coming through).

Mercifully the project was canned after a month or so and the other developers were free to pursue other contracts whilst I returned to normal duties. Oh, and the lead programmer on the team? It turns out he had the Australian dealership for the object database involved. What a surprise!

Ignorance is bliss

I was on the phone to my wife the other day and happened to mention the Jakarta bombing of the Australian Embassy. She hadn't heard of it. So I (mischevious bastard that I am) asked if she'd heard of the Beslan Massacre. She hadn't. She had noticed some flags at half mast and wondered if perhaps a president (maybe Ford) had died but that was the extent of it.

I shouldn't have been surprised. I've noticed quite a few people who've stopped following any kind of news over the last few years.

*shrug*

Friday, September 10, 2004

Wow

that was fast! I suppose it helps to be in a similar timezone to one of the Admins :-)

Er what am I talking about I hear you ask? Elapsed time from requesting blog to receiving blog was about 2 minutes.

Dammit, now that I've started a blog I suppose I'm going to have to update it occasionally. So here's the first entry. I'm standing at the keyboard typing this in Baguio City, Philippines. Standing? Uh huh. There are no chairs! That would be an unwarranted expense. It's getting tough on these old feet to be standing at the keyboard for upwards of 12 hours a day, 7 days a week. With any luck I'll be back in the US sometime in the next month though and able to write code the way any self respecting coder writes - sitting down! :-) I really must investigate my employers obligations with regard to sending me to client sites.

Well, that's my first rant. Not very exciting was it!