Posts by Topic


Software Sin #3: Mismanaging Global State

Global state isn't the real devil...

In the software engineering community, there's a near universal belief that using global state of any kind is evil because it can lead to undefined behavior and race conditions. It can also makes testing more difficult or impossible depending on the decided scope of the state.

I disagree that it's evil. In some types of projects, especially in low-level systems, global state is required. However, it should always be an absolute last resort.

The issue with global state is neither the state itself nor the application. The problem is developers using and abusing it.

Inserting global state into an application introduces continuous human overhead into the project since it isn’t possible to enforce rules for the variable or object via the compiler.

For your project to remain logical and maintainable in the long-term, everyone working on a project must know:

Successful global state requires clear, up-to-date documentation accessible to all developers working on the project.

However, the best documentation is worthless if people don't read it. Some people won’t, so you must be vigilant with code reviews to ensure that your conventions aren’t abandoned.

If you fail to take responsibility for globals, your project will either cause headaches or fail entirely.

At my first job, there was a sore spot in internal testing that frustrated everybody. When our product was first introduced, it was difficult to install, so someone quickly hacked together some Python scripts that used the Robot Framework to set up servers for basic product testing.

First off, it was a perfect example of reinventing the wheel poorly (another sin) since a dev-ops tool could have accomplished the same task more effectively. Worst yet, the project made liberal use of global state to describe the devices-under-test (DUTs) that were being constructed.

It was a design disaster for the following reasons:

This setup code was run at the end of every single product build. We couldn’t submit code into the develop branch until we got a full pass on builds and tests.

Unsurprisingly, the device setup failed about 10% of the time for all sorts of reasons, primarily exceptions from oversights and bad changes to the setup framework. We could have caught and fixed all of the errors before they happened if the code was testable.

It worked well enough, and we were conpletely swamped with work, so no one had the man-hours to fix it up. When we changed the way the product was installed, it was given a complete overhaul, but the overhead and effects of the poor design were felt for a long time.


Is the human overhead worth the benefit of introducing global state? That’s your call, but remember, bad decisions and mismanagement can topple a project.

Morals:

  1. Avoid using global state whenever possible. Explore alternative design patterns first; there’s usually another way to accomplish your goal such that the data has more limited scope.
  2. Minimize the amount of global state in your application.
  3. Document your globals thoroughly, and ensure that documentation is readily available to anyone that needs it.
  4. Ensure that developers are following the conventions in code reviews.
  5. Never allow unrestricted global state into your project or you may as well call it quits…

26. From Pennsylvania, USA. Software engineer at Amazon.com, travel enthusiast, scuba divemaster, amateur photographer. A bit restless.

View Comments