Programmer time and the pitfalls of wasteful work

Programmer time and the pitfalls of wasteful work

Programmer time is precious. This realization should shape our approach to software development, focusing our efforts on tasks that genuinely contribute to the improvement of our code and the software ecosystem.

 

What does matter?

 

  1. 1. Hunting for bugs. I like to add tests, and then even more tests. The time spent building tests should proportionate to the time spent building the software. Fuzzing is also fantastically useful. I love using sanitizers.
  2. Fixing bugs. Bugs disrupt user experience, compromise functionality, and can even introduce security vulnerabilities. Addressing bugs is critical to build trust in the software. 
  3.  Documentation matters. Underdocumented code is mysterious and may trigger unnecessary surprises. Lack of documentation may also harm relationships with users.
  4. Adding new features. Innovation and growth in software come from introducing new features.  Features should be user visible: ‘internal’ features are often wasteful.
  5. Improving Performance. Performance enhancement is all about making the software run faster, use fewer resources, or handle larger workloads more efficiently. This can significantly impact user satisfaction, particularly in applications where speed is paramount. Improving performance is not just about identifying bottlenecks… it is an ongoing journey. You need a good design and multiple rounds of optimizations. You can often continue to improve the performance for years and years.

However, there are areas where I believe our time is not well spent:

  • Patching code to silence false positives from disabled-by-default static analyzers. The level 4 warnings under Visual Studio when compiling C++ code is a good example, but so are the obscure GCC and clang warnings. Static analyzers are tools that can scan code for potential issues without executing the program.  However, when these tools are overly strict or misconfigured, they might report numerous false positives; issues that aren’t actually problems.  Spending time patching code merely to quiet these false alarms is, in my view, wasteful. It diverts attention from more impactful work. This is not to say that static analysis is not beneficial; when used correctly, it can save considerable time and resources. But the effort required to address non-issues can quickly become counterproductive.
  • Aimless refactoring is also often wasteful. Renaming classes, moving code around just so that it looks ‘nice’. I am not against the occasional cleaning round… but it is should not be time consuming. Refactoring for its own sake may become an excuse for not fixing bugs or for not improving the performance. It is easy work, but often not impactful.

Let us take concrete examples. Consider the following function:

uint8_t f(uint64_t x) {
    uint8_t y = x % 256;
    return y;
}        

When compiled with LLVM/clang with the -Wconversion flag, you get the following warning:

warning: implicit conversion loses integer precision: 'uint64_t' (aka 'unsigned long') to 'uint8_t' (aka 'unsigned char') [-Wimplicit-int-conversion]        

The warning is bogus, a waste of time. There is no loss of precision (whatever precision means).

Another favorite of mine is this function:

uint64_t g(uint64_t x) {
    return -x;
}        

Negating an unsigned integer has many applications: e.g., if you want to select only the least significant bit, and zero all others, you can use the expression (-x) AND x. Under Visual Studio, if crank up the warnings, you get

warning C4146: unary minus operator applied to unsigned type, result still unsigned        

Another waste of time.

While we strive for perfection in our code, we must also be strategic about where we invest our most precious resource: programmer time. Let us prioritize what truly matters in the grand scheme of software development.

To view or add a comment, sign in

More articles by Daniel Lemire

  • House prices and fertility

    No, rising house prices are not the driver of sharp fertility declines. The evidence shows only modest, mixed effects…

  • You can beat the binary search

    We sometimes have to look for a value in a sorted array. The simplest algorithm consists in just going through the…

    7 Comments
  • The fastest way to match characters on ARM processors?

    Consider the following problem. Given a string, you must match all of the ASCII white-space characters (\t, \n, \r, and…

    1 Comment
  • A brief history of C/C++ programming languages

    Initially, we had languages like Fortran (1957), Pascal (1970), and C (1972). Fortran was designed for number crunching…

    10 Comments
  • Can your AI rewrite your code in assembly?

    Suppose you have several strings and you want to count the number of instances of the character ! in your strings. In…

    3 Comments
  • A Fast Immutable Map in Go

    Consider the following problem. You have a large set of strings, maybe millions.

    4 Comments
  • Prefix sums at tens of gigabytes per second with ARM NEON

    Suppose that you have a record of your sales per day. You might want to get a running record where, for each day, you…

    2 Comments
  • You can use newline characters in URLs

    We locate web content using special addresses called URLs. We are all familiar with addresses like https://google.

  • How fast do browsers correct UTF-16 strings?

    JavaScript represents strings using Unicode, like most programming languages today. Each character in a JavaScript…

    1 Comment
  • How bad can Python stop-the-world pauses get?

    When programming, we need to allocate memory, and then deallocate it. If you program in C, you get used to malloc/free…

    3 Comments

Others also viewed

Explore content categories