Language and Architecture

Composite keys: friend or foe? ... or, why my iPod can't handle duplication

Playing with my iPod yesterday, I found a very irritating bug. I have two albums called "Still", one by Joy Division and one by Wolverine. When I select either one of them from the albums list on the iPod, I get both albums smushed together rather than just the one I selected. In fact, despite Cover Flow showing both albums, the albums list only shows one with all the tracks in it.

TFS Made To Suck Less!

I suppose I should come clean about something. I recently installed the Team Foundation Server PowerTools and have been using them successfully for a while. They have one or two very handy features that make TFS suck less. Get them direct from the TFS PowerTools page at MSDN.

Online Mode

Using the tfpt.exe command line, the 'online' mode will search your repository for changed files, added files and removed files and check out, add or remove the files as necessary. It also has a simple preview mode. This means that, with only one extra step, you can fix all the missing icons or forgotten checkouts or whatever. It would be nice not to have to do this step at all, but at least it's not entirely manual now.

Annotation

The PowerTools add a new feature to the Source Control Explorer: Annotation! Now you can actually see, line by line, who changed what, why and when. Jolly good.

Recursive Diff

Probably the biggest, most important change is the ability to diff entire directory trees. This will show you a nice window with all the missing files, all the changes, all the things that have not been checked out but should have, and everything else all in one lovely window. This alone is worth installing the PowerTools for.

Unchanged File Undo

A problem that arises from the 'check out required' nature of TFS is that sometimes Visual Studio checks things out automatically that are then never edited. When you check in, the files haven't changed so are not included in the changeset. This means you have a bunch of unchanged files marked as checked out. Very annoying.

Enter the tfpt.exe command line tool, with its 'uu' command. I assume that 'uu' stands for 'undo unchanged' or something. It basically performs an 'undo' on any checked out files that haven't actually changed since being checked out.

News just in: Team Foundation Server sucks. More at 11.

One of the banes of my current working life is the heaping mound of crud known as Team Foundation Server. I know I've ranted about it before, and I'm sure I'll rant again. Such is the heinous evil that is TFS.

This time, I'm going to list 4 things that TFS does (or doesn't) that means it's completely unsuited to modern development practice. I'll be comparing the functionality with that of Subversion, currently a very popular open source VCS that I like a great deal.

So, on with the rant ...

VBA Unicode done right, redux

Some time ago I wrote a short article on forcing VBA to use some form of unicode to allow simple insertion of non-latin1 text into VBA modules. It sort of worked, for the most part, kind of. Well, it didn't. The problem is down to the VBA editor being locked to the local encoding of the machine it is running on. You can only type characters from BIG5 in China, Shift-JIS in Japan, and so on. If you have a need to make a VBA module that uses strings suitable for all locales ... you're pretty much stuffed.

Except you're not. If you do it properly, you can have any unicode character displayed in any VBA locale. So how do you do it properly? Well, you're supposed to use ChrW$() to generate unicode characters individually. Yes. Really.

Stop Patching Like Monkeys

It seems that my previous rant on the evils of runtime modification of types is no longer alone in this big wide world of hacks and bodges. No indeed, it seems there is even a semi-official name for this practice; Monkey Patching. How very appropriate.

The basic problems being highlighted in this post basically reiterate what I already said before. Monkey patching means that bugs are hard to find because you simply don't know what code is running at any point in time.

Now, I make my opinion of the blind Ruby-loving, Rails-abusing trend followers no secret. I think they're bad coders, for a start. That's not to say they're stupid, or don't understand the technology. I'm just saying that they're throwing away good practice in favour of little more than a quick fix. They're not engineering, they're bodging. I also think they're guilty of herd mentality. They are undoing years of software engineering to be in with the "it" crowd, and monkey patching is just one example of how this manifests.

With monkey patching, you get code that you simply can not debug. The best you can hope for is that you get lucky and happen to spot that some completely unrelated module is actually changing code you rely on at runtime. Why do they do this? Because it's hip, it's cool, it's what the "new wave" of developers are doing. The new wave of developers are wrong. Arguing for monkey patching against software engineering has as much merit as arguing creationism against scientific method. It's not good enough to simply believe you'll be smart enough to debug it when everything falls apart.

Just ... stop it.

Nokia 800^H^H^H770

Thanks to the sterling efforts of the chaps over at Maemo.org, I know have the ability to run the Nokia 800 OS, known as OS2007, on my Nokia 770. Flashing the new OS onto the machine was simplicity itself, given that a new FIASCO image is available and can be flashed in the usual manner.

So once it's all working, what can you expect? Well, my personal list of favourite new features is as follows:

  • Better look over all, especially the two on-screen keyboards
  • MUCH better Bluetooth support, including OBEX
  • Native support for Bluetooth keyboards and GPS devices
  • Automatic join of trusted networks on power on
  • Later versions of everything available
  • It might just be me, but it seems faster, too

There is rough to go with the smooth, though. One problem I've found is that the kernel included doesn't have smbfs support. If you use something like smbbrowser to connect to Samba shares on your network then you're stuck (at least, I think. I'll check for a solution.) There are also some battery life issues that might need sorting. The most major ones are the media metadata scanner going mad, and the internal alarm manager turning the device on at odd times.

If you notice, either through top or some other means, that metalayer-crawl is using up a lot of CPU time and draining your battery, then you might need to limit its scope somewhat. This is well described in bug 978. Metalayer-crawl is a simple program that indexes the identifying tags on media files stored on the system (e.g. mp3s), but it seems to get somewhat confused by symlinks and can easily end up recursively indexing the entire system forever. The fix for this bug simply causes it to only index files in the user's media directories.

Secondly, there is a strange problem with some devices that a 'hidden' alarm turns the device on at odd times. This simply needs the hidden alarm removing. First, become root, then run:

    $ /mnt/initfs/usr/bin/retutime -A ''

This simply removes all hidden alarm events. You could set custom alarm events with this utility if you wanted. I'll leave that as an exercise for the reader.

A final little tip that I quite like is the ability to use a long press of the power button to put the device into 'soft off' mode. This is basically the same mode as the device enters when the screen cover is put on, but sometimes it's nice to be able to access it without having to put the cover on. This is especially true if you're just temporarily putting it to sleep while you're otherwise engaged, and have power, USB or earphones plugged in.

To enable this feature, become root and edit the file /etc/mce/mce.ini. Find this line:

    PowerKeyLongAction=poweroff

and replace it with:

    PowerKeyLongAction=softpoweroff

Reboot the device and your new soft power off mode will work. Press and hold the power button in the usual way to turn it back on in a jiffy.

VBA Unicode done right

IMPORTANT UPDATE: It seems that this is one of the most popular posts on this site, so VBA's useless unicode support is obviously a big issue. Seeing as it's so commonly searched for, and seeing as many people don't know the first thing about Perl, I've knocked up a small Windows tool that does the job. You can find it at the updated version of this post. Everything below this line is obsolete!


Some time ago I wrote a short article on forcing VBA to use some form of unicode to allow simple insertion of non-latin1 text into VBA modules. It sort of worked, for the most part, kind of. Well, not really.

The problem, you see, is that the VBA editor is extremely stupid so won't display non-latin1 characters unless that's your machine's native codepage. Couple that with the compiler, which is also pretty stupid, that actually breaks encoding rules if you have the audacity to sign your modules with a proper certificate. It basically forces a revert to the native codepage making non-latin1 text look ... well, ridiculous.

Visual C++ Incompatible time_t Types

One of the main reasons for using the correct named types in C programs is to ensure that, for a particular compiler on a particular architecture, the type is as expected at all times. One of these is time_t, for representing timestamps. In most compilers it is a 32 bit integer value, but you cannot just blindly assume that time_t can be cast to and from int, or long, or whatever, at will.

There is an issue with closed source, binary only libraries. What if you are linking them against a different compiler to the one they were built with, and what if it has a different idea of what different types actually are? Well, bad things can happen. In Visual C++ 2005, time_t is defined as a 64 bit integer. In all previous versions it was 32 bit. To demonstrate what can happen, consider this library, built with VC++ 2003, that exposes the following function:

    void populate_user(int user_id, user_t* user);

The type user_t is defined as a structure in the distributed header file like this:

    typedef struct _user_t {
        char username[8];
        time_t creation_time;
        time_t lastlogin_time;
        char realname[64];
    } user_t;

It's a fairly simple struct, but it'll do to demo the problem. So we build a new program that links against our library and #includes our header. It creates a new variable on the stack of type user_t and passes a pointer to it into the exported function.

So what happens? Well, the following values are inserted at the given offsets:

Member Offset Value Memory Contents
username 0 craiga 72 63 69 61 61 67 00 …
creation_time 8 1199215958 47 7a 95 56
lastlogin_time 12 1199216158 47 7a 96 1e
realname 16 Craig Andrews 43 72 61 69 67 20 41 6e 64 72 65 77 73 00 …

However, when that little lump of memory makes it into our VC++ compiled program with its 64 bit time types, this is what it looks like:

Member Offset Value Memory Contents
username 0 craiga 72 63 69 61 61 67 00 …
creation_time 8 5150594180643984726 47 7a 95 56 47 7a 96 1e
lastlogin_time 16 7944666846179979843 43 72 61 69 67 20 41 6e
realname 24 drews 64 72 65 77 73 00 …

What happened?! Well, all the offsets of the members are wrong. The two 32 bit integer values in the library have been crammed into one 64 bit field in the program. Then, the contents of the realname string have been used to populate the time values. The end result is that the realname string is offset by 8 characters and the two times are completely garbled.

Unfortunately, unless the vendor has provided a workaround, you are pretty much stuck with it. Fortunately for us, Microsoft have actually given us a sort-of fix for this issue. Simply include the definition of _USE_32BIT_TIME_T in your project's (or file's) Preprocessor Definitions field and you're away. Unfortunately it means that anything linking against your older binary will be stuck using 32 bit time_t, even if you want to use 64bit time_t. Not a great solution, then, but better than the alternative!

Some musings on Microsoft

Over the last few days I have been thinking. A dangerous habit, but an important one. In this case, I've been thinking about why people continue to use Microsoft products. The old adage "Nobody ever got fired for buying Microsoft" is hardly relevent, because it only shows that the people doing the firing are not the same people as those who are supposed to be technically capable. There are three things that have brough on this round of thinking.

Mutable Mish-Mash

This post is a bit of a cathartic rant, but in as polite a way as possible. Please bear with me.

There have been a few micro-revolutions on the internet of late regarding software development. Not all of them are sane, some are outright bizarre and one or two are just rehashes of very, very old concepts. For example, functional languages are popular on reddit.com, and dynamically typed languages are popular with the web crowd on dzone.com.

One of the most common dynamically typed languages around at the moment in Javascript. It's a strange thing; not in the slightest object oriented, but has a concept of objects. Instead, people seem intent on recreating OO like behaviour using what passes for a Javascript object and piles upon piles of closures and anonymous functions. While this is certainly a step in a pragmatic direction, it seems that this particular paradigm shift sometimes brings with it a bit too much cleverness, and not quite enough sensibility.

Javascript is a bit of a mad beast; classes are defined as closures that are somehow instantiated. Methods are declared as closures within the closure that is the class. It's all a bit mad. This mass of closures within closures within closures is overshadowed by that most heinous of things; mutable types. Heinous? Surely no! I'll have the dynamic language fanbois all over testiculating about the superiority of such things. However, I do have reasons.

Syndicate content