C++ : Strong types and the C difference

Developers Kindergarten

This is Episode 3 from a miniseries on “Strong Types”

  1. C++ Strongly Typed Duck
  2. c++ Strong Type Use-Cases

Motivation

You are a software developer.  You are first-time reading two header files of two phone book components. Your task is to select one, make your company pay for that one you just selected, and then ask everyone to use the one.

A

B

Which one is better and why?

I vote B. I can see shredded glass on the path of the developer who selected the option  “A”.

The  omnipotent “Access violation”

And with that, we are entering yet another real-life use case, helping you to decide in favour of simple strong types.

Recently I was given an “honourable” task to find and remedy a “mystery” bug in a pretty complex multi-threading system. The core is written in C.

In software development we all know: “mystery” is one sure way to “misery”.

Run-time “Access violation” coming from previously working parts. In particular, freeing pointers to corrupted heap. And not always.

It was one of those: “But it was working before?!” kind of a mysteries. And to cut the long story short. here was this function:

It is used from a lot of threads upon starting each of them. It is part of the tried and tested common library. It is passed as initial thread data, and it is the responsibility of the thread to free it upon specific usage.

So. A lot of developers calling one simple function from a lot of locations, sprinkled around their complex code.

What could possibly go wrong?

What went wrong is very simple. And extremely hard to test properly. Some of the callers have mixed the order of the arguments.

But which callers? In where? We are talking about many components, many developers and several projects.

That mistake was easy to make. Both arguments are of the same type. The compiler can not spot logical mistakes.

Enter Strong Types

So instead of spending a lot of coordinated effort and time (and that means money), I have re-declared this one function like so.

Infinitely better vs the previous declaration.

Recompile everything and lo-and-behold, the several “culprits” have been found.  As soon as arguments have been re-declared as strong types, they realized they have made a mistake in the order of arguments.

Now the code  required to call make_name has suddenly made it very obvious which argument is which.

In any case, it is very obvious which value is used as which argument. Maintenance of the software code is often forgotten as a critical and potentially very costly activity. Anyone diving into the code above, even years after the release, will be immediately clear, calling the make_name is all ok.

That “strong types as literals” C code is better C++. Why? Please compare.

You have not seen this code before. You need to debug it. In the C++ call above, are you always going to be sure which argument is Id and which one is Origin?

That is the same logical bug, again. It compiles in C++. But not in C.

Addendum

Before I left, the team has decided they like the approach and  they have improved the declaration of the “offending function” :

They have added yet another strong type, to this function signature: Name. As the return value type. After that, they have compared the performance of this version with the previous version with no strong types.

The difference in favour of no strong types was negligible. They have paid the cost, learned the lesson, and decided to stay with the “strong types” variant.

Option C

Ah and by the way. Option B is better than option A. But the best option I vote for is:

Wink, wink … Enjoy.