Bug Hunting Adventures #1: Logging Binary Data

Normally, loggers are used to track down bugs, but today, I present a Logger class method that contains a bug itself — isn’t it ironic?

Logger::logbuf() takes ‘len’ bytes of binary data from memory pointed to by ‘buf’ and converts it into printable, zero-terminated hex strings ala “AA 01 B3 C4…”.

For efficiency and readability, the hex string is broken up into smaller parts. Every hex string part is fed to the existing Logger::log() method which is capable of outputting arbitrary, zero-terminated strings (a new-line character is appended automatically).

Happy bug hunting! I will post the solution in two weeks time.

Code
Solution

Bug Hunting Adventures

I’ve always loved to find bugs in code through mental debugging — especially other people’s code. Besides being fun, bug hunting improves product quality as well as one’s programming and problem-solving skills.

One of the books I enjoyed most is “Find the Bug” by Adam Barr. It contains many examples of buggy code in various programming languages, ranging from assembly language to Python. I heartily recommend it to everyone who shares my passion.

What a pity that there aren’t more books like this on the market!

To relieve our misery, I’ve decided to setup a new series: at irregular intervals I will post a bug-afflicted piece of code and challenge you to spot the problem. I don’t want to limit this sport to particular programming languages or defect categories; some bugs will be straightforward while others may be intricate, potentially only showing under certain, favorable circumstances.

Anyway, I hope you enjoy this new series as much as I do — stay tuned, the hunting season is open!

The God’s Equation for Perfect Highballs

“Mix a stranger a good drink and no longer will he be a stranger”
— Yours truly

I’ve never been a fan of pure mathematics. Even though I must admit that pure maths bears a lot of elegance, it’s real-world applicability that makes mathematical discoveries shine.

Boy oh boy, how time flies! It’s summertime again, at least in the northern hemisphere, on this planet, and what a great time it is for drinking plenty of highballs. For those of you who don’t know: highballs are simple long drinks that are made up of two ingredients: liquor (eg. gin, whisk(e)y, rum) and a non-alcoholic beverage (eg. soda, juice, cola).

Even though there are usually only two ingredients it is not that easy to make a perfect highball. It all depends on the right mixture. Some like their highballs stronger, others lighter. So how do you determine the perfect ratio? The task is complicated by the fact that the strength of the liquor used might vary (for instance, rums come with alcoholic strength levels reaching from 35% to 80%).

So I sat down for a while and did a little math — to solve a real-world problem once and for all. What I’ve come up with is this:

In this equation, Vn is the volume (amount) of non-alcoholic beverage, Vl is the volume (amount) of liquor, R is the mix ratio, Sl is the alcoholic strength of the liquor used and Sh is the desired target strength of the resulting highball. Isn’t this wonderful?

As an example, I happen to like my highballs with a strength of 10% and most liquor in Europe is sold with a strength of 40%. What’s the recipe for a perfect Gin and Tonic? Answer: 40% divided by 10% is four, minus one is three. Therefore, you would need three parts of tonic water for one part of Gin to make me smile.

If you prefer a 5% Gin and Tonic (are you a wimp, by any chance?), note that you will need seven parts of tonic water, not six, as a naive would-be drinks mixer would expect.

There you have it — the formula for perfect, repeatable quality drinks. People in the same spirit (pun intended!) — let’s raise our glasses to this discovery!

Epilog

I know, I know. Some of you smug, mathematically inclined folks with an IQ of 180+ would probably have known this right away. I don’t mind if you point out that my pathetic “discovery” is obviously just a special case of something more profound. Congratulations! I will drink a very special toast to you tonight.

And — just in case you haven’t done the maths yourself in the meantime, here is how I derived it:

Strength of liquor Sl is volume of alcohol in liquor Val divided by the total volume of liquor Vl:

Total volume of highball Vh is volume of liquor Vl + volume of non-alcoholic beverage Vn:

Strength of highball Sh is volume of alcohol from liquor Val divided by the total volume of highball:

Inserting (2) in (4):

Inserting (3) in (5):

Cheers!

A Tale of Two Qualities

Green and rotten. Isolated odject. Element of design.

“Here then, as I lay down the pen and proceed to seal up my confession, I bring the life of that unhappy Henry Jekyll to an end.”

— Robert Louis Stevenson, The Strange Case of Dr. Jekyll and Mr. Hyde

The old saying “What gets measured gets done” makes immediate sense: before you can improve anything, you first have to gain insight into it. If you act, you want to see the consequences, as soon as possible, compare them to desired results and adapt accordingly. Further, measurements not only give you a picture of the past and present — through extrapolation you get an impression of the future as well.

In modern software development, we constantly measure the quality of our product right from the beginning. We check for build breakers and failing test cases, code coverage, memory consumption and execution times on a check-in basis, as part of our continuous integration process. We always know the quality of our product — there won’t be any big surprises at major milestones or the end of the project. Running a software project like this removes the chance factor — this is quite the opposite of what happens when you follow a waterfall model with its dreaded big-bang integration phases.

But let’s face it: we mainly focus on controlling external quality; that is, everything that is visible to the customer.

The level of external quality is usually (relatively) easy to determine since external requirements are specified such that they are unambiguously verifiable (at least they should be). Thus, developers and testers can implement automated tests that will reveal any deviations. Because of the fact that external quality is directly visible to customers and directly influences whether they buy (or return) a product or not, it is not difficult to get proper funding for people and tools. In this sense, external quality really lives on the sunny side of software life.

Sadly, external quality’s brother, internal quality, lives an unhappy life in the dark: internal quality requirements are usually not nailed down precisely, in fact, they are often fuzzy and neglected. Sure, there are coding guidelines that mandate a certain indentation style and whether to use tabs or spaces (among other things) but are there actually checks against violations? And what about compiler warnings, bad coding practices, size of classes/methods, cyclomatic complexity, coupling of classes, missing API documentation and so on? And who is willing to invest in work the customer doesn’t see, anyway?

In most cases the answer is a blatant ‘No’. Neither are internal quality requirements stated in a precise and verifiable way, nor are they given high priority and almost never are they automatically checked as part of the continuous integration process. Since internal quality is not observable by the user, you can get away without paying attention. But then you have to pay for something else: an ever-increasing amount of technical debt and the compound interest that ensues.

Why does this all matter? In order to compete, a software product undergoes a multitude of major and minor modifications over many years, often carried out by developers other than the original authors. Once the first release is shipped, maintainability becomes a crucial factor and internal quality determines whether future changes this will be easy (cheap), hard (expensive), or outright impossible. Don’t underestimate the impact of even the smallest things; even a single broken window may be responsible for decay and increase of crime level in town districts.

What we need is a shift in mindset: first, internal quality requirements must get the same priority as external quality requirements and second, internal quality is perpetually tracked (and acted upon) as part of the continuous integration process.

It is of utmost importance to keep track of internal quality right from the beginning, when the mental distance is low and issues can be corrected with the least amount of work. Further, the whole team immediately benefits from the improved quality and the learning effect ensures that the amount of effort that needs to be spent goes rapidly down. Postponing internal quality work to late phases of the project is a costly and frustrating experience.

For some internal quality metrics it is necessary to build special-purpose analysis tools that cannot be bought off the shelf, but dynamic/scripting languages and heuristic regex-based parsing can go a long way. But even if you need more precision there are often free/open-source tools and frameworks at your disposal: I know of one C++ project that implemented several clang plugins to ensure that (among other things) identifier names where in line with the coding conventions.

Every developer has different standards as to what good-enough internal quality is. To make matters worse, day-to-day routine and especially schedule pressure will lure developers into accepting the status quo of their code once testing has proved that external quality criteria are met. But the converse is also true: without indisputable measurements, developers might spend more time than needed, endlessly polishing their beloved code.

We should give both sides of the quality coin equal consideration. While external quality is the necessary basis for the short-term success of a product, it is internal quality that ultimately determines the long-term success of a software company. Hence, we should remove the chance factor of internal quality, too.

Free-Riding the Team Train

I usually start my day with a thirty-minutes run in the morning. Since I prefer running through the countryside it is not unlikely that I meet people walking their dogs. Sometimes — for reasons I cannot fathom –, these folks walk their dogs on the wrong side of the road (or rather country lane).

But let’s be fair. Even in Germany there is no law that requires pedestrians to walk on a certain side of a country lane; but what drives me nuts is that when they see me coming against them, most of them don’t dodge, let alone change to the other side of the lane — they just stay where they are. Almost all of them expect me to move, to overtake the wrong-way dog walkers.

Sometimes, just for the fun of it, I refuse to obey and stop right in front of them, which completely baffles them. Then, we stand there, deadlocked for a couple of seconds until I finally decide to give in.

I believe that what the dog walker subconsciously assumes is this: “the other one is faster, so he should move, it’s less effort for him than it is for me“. Even if this might be true in some cases, it is by no means generally true. Just because one is going faster doesn’t imply that doing something extra is easier for this person than for anyone else.

Probably, this is just all too human behavior, to get by with spending as little (effort) as possible. Especially members of sufficiently advanced societies expect that the strong protect and support (or at least are considerate of) the weak: “Those who can should support those who can’t“.

While I fully subscribe to this principle, at least in general, I have observed that this argument is often misinterpreted (misused) by slackers to mean “those who can should support those who don’t want“, an attitude that is totally unacceptable to me, neither in a society, nor in a company, and least in a team.

As another case in point, in 1913, French agricultural engineer Maximilien Ringelmann discovered that people — when working collaboratively on a given task (like pulling a rope) — excert a lot less effort than when acting alone. The bigger the group the bigger the tendency to hide behind others, to free-ride, to prefer taking over giving. Today, social psychologist call this phenomenon “social loafing” and it not only takes place in societies, but also within companies and teams.

In a company, the “Ringelmann effect” does not only impact day-to-day project work. For instance, if you call for a meeting, the more people you invite, the less people will come prepared and even fewer will make substantial contributions. Some “strategists” even exploit this fact by inviting a large party to a meeting where only a few protagonists actually make decisions. The large size of the group then gives an illusion of quality and broad acceptance of the decision, when in fact most people were just daydreaming. If there is one lesson to be (re-)learned from the Ringelmann effect it is this: “less is more”.

Here is my definition of teamwork: a group of self-motivated, self-directed individuals who share a common vision work together to achieve a common goal. If somebody needs support from a team member than never because one doesn’t want to do a task — only because one is temporarily unable to do the task oneself. Further, it is the responsibility of the supported person to keep the support to an absolute minimum and to learn and grow from it — not only to become independent of others but to be able to help others who are in need some day. The ultimate state of any team member is neither dependence, nor independence, but rather interdependence.

Making up for slackers, on the other hand, is not only a waste of time: sooner or later it drains the motivation and morale of even the most self-motivated people and encourages them to loaf as well. While I see a lot of value in so-called “B players“, I have zero tolerance for free-riders.