The Enterprise

Break things when something serious happens

Michael Pankov •

As I wrote in my last post speaking about breaking backward compatibility, errors are better than warnings. I'm going to elaborate on what I mean and why is this so.

Example

Let's start with an example. At some point it is decided that the project build should include a separate stage managed by a different configuration file and performing custom commands, like packaging the built executables and external resources into distribution archive. This archive is composed from files given their paths and corresponding names in the archive. Paths could be relative to the root of project — for the files which are built in this project. Or they could be absolute — for the files which are not the part of this project.

A developer implements a tool which creates this archive given the configuration file. He has a choice: when the tool can't find the file specified in the configuration (i.e. because it doesn't exist), it could just issue a warning to terminal and continue, or stop with error. Issuing a warning seems like a good option, and the programmer chooses it. Let's think what consequences will this decision have.


Consequences

The tool is implemented and is integrated to the build. Well, "integrated" may be a strong word. Let's remember that configuration files are not stored in version control system directly. Rather, an original, sample, version of such file (think .config.sample) is put into git, and then the developer should create the working version of that file (i.e. .config) — in many cases by copying the original. So the integration actually stops on adding the logic to the build system and putting the sample configuration file under VCS.

Then, depending on the level of consciousness and experience of the implementer, the build system may or may not detect the absence of the working copy of configuration file. That's not the main point. Either way, the developer which just pulled the VCS and got an updated build finally figured out they need a local .config to supplement the .config.sample. What's the simplest way to make a local copy of VCS-tracked file? Just copying! Bam, we're in trouble.

The .config, as we intended, contains paths — both relative and absolute. Do you see what may be wrong? The .config.sample may, by mistake (or just as an example!), contain some absolute paths from the original implementer's machine, and they will be copied to the .config. Even if not, the .config will contain the paths to the files which don't exist yet — because the executables we want to be packed are not built.

Then, for some reason, the files needed by tool can be not built — the new build stage wasn't not thoroughly tested yet, after all. Or it's okay in "vanilla" situation, but then you started hacking on your task and broke the build. Some file to be packaged was removed and is not built now.

But the packager then proceeds to process the .config, tries to pack the non-existing files, but doesn't fail — rather just emits several lines of "warning:" lines to the build log, which spans over several screens, even when build commands are not output.

So, it's impossible to notice that something went wrong. If some of the needed files do exist, and some don't — the resulting package will get created, but will be incomplete. And you'll get to know that only after the package is deployed — either by fellow developer, or the DevOps team, or by customer themselves.

Then, depending on quality of error handling in the rest of the system, the team will spend anywhere in a range of from an hour to the couple of days debugging what's going wrong. In the end, the package was meant to include all the required files! And no errors were encountered during the build, so what could be broken?

It all could have been avoided, should the initial implementer of the packaging tool opt-in for errors instead of warnings. Just emit a "file doesn't exist" as soon as a file mentioned in configuration is not found.

Okay, you may think that the scenario I described is inconceivable. That it doesn't happen the way it's shown here. That people are not that stupid and that there not so many mistakes in build systems.

Well, it does happen. Depending on overall responsibility of programmers, size of the team, and pace of development it may happen more, or less, often, but it still happens. In my experience — the actual errors are mistakenly masked by someone (including me) unforgivably frequently. Which brings us to the conclusion…

Warnings are ignored most of the time

Because warnings are just that — non-blocking hints on what could cause some trouble. I'll elaborate on this matter in another post later, but for now — admit it, nobody is ever going to perceive a warning as something which can cause a complete failure of operation of your software.

No manager is going to understand why the package is broken if the build is successful. No DevOps will stop deployment of a new version because it compiles with warnings. Especially when deadlines are pressing and the supervisor is not satisfied.

It's not that hard to steer clear of all that trouble: don't emit warnings which should have been errors. Do not contribute to the confusion.
comments powered by Disqus