More thoughts on change and typedefs

Of course, now that I’m well into using the “option 4” I start to remember why I kept sliding back from options 2 and 3 towards 1. Although option 1 uses native types instead of typedefs which is bad for all the reasons I listed in the previous post, the other options only give the illusion of type safety because they use typedefs…

Of course I knew all of this, but it doesn’t hurt to go full circle and remind yourself of the pain once in a while. I find that if you do that then you sometimes solve the problem properly ;)

It’s all very well having a CodeLocationIndex concept and a OperationIndex concept and it’s great if these are represented as typedefs rather than intrinsic types:

typedef size_t CodeLocationIndex;
  
typedef size_t OperationIndex;

rather than just using size_t everywhere. Using the typedefs makes the code communicate more. Unfortunately it doesn’t help the compiler.

I was feeling a little embarrassed about how I kept gravitating to option 1. After all the arguments for the other options were compelling and I though that I’d become a little too focussed on coupling to the detriment of the code. Now I realise that the reason that I kept ending up back at option 1 was that using typedefs is a bit like using comments. It’s something that allows the code to communicate to the reader but the compiler is excluded from the conversation; which means that typedefs, just like comments, can become a little detached from reality and at that point the communication is just marketing ;)

The key point, of course, is that typdefs do not create new types, they simply introduce new names for existing types. The compiler doesn’t care that your function takes a CodeLocationIndex and instead you’re passing it a OperationIndex, they’re both just a size_t in drag.

I like restrictions; I want the compiler to tell me when I make a mistake so I want the compiler to restrict what I can do. I’d rather learn to play by its rules than assume I’m clever and don’t need the rules. I also despise unnecessary fluff. As such I was obviously drawn to option 1 because the other options added no additional type safety and yet added fluff.

I can see where this is heading; now that I have my typedefs in their own header files they may as well become fully fledged types. It’s not such a big step; a single base class would deal with most of the work. My one liner typedef headers would grow a little, they’d include the base class and then the “typedef” would become something like this:

class CodeLocationIndex : public CUnsignedScalar {};

The abstraction becomes a “first class” type and the compiler joins the conversation.

This is the kind of thing that I would never have considered to be ‘worth it’ until the types were already in their own header files… Perhaps this idea isn’t so extreme after all.

I’m sure someone’s already done most of the thinking behind this, time for a Google.