Skip to content

Avoid just-in-case programming

“Just-in-case programming” refers to code that isn’t sure about itself - adding unnecessary defensive measures driven by fear and uncertainty rather than actual requirements.

// "Just in case" the vector isn't empty
vec.clear();
vec.push_back(item);
// "Just in case" it's not initialized
ptr = nullptr;
ptr = new Object();
// "Just in case" someone passes null
if (data != nullptr && data->isValid() && !data->isEmpty()) {
// Actually, what if data is valid but empty is okay?
}
// "Just in case" we need thread safety someday
std::mutex global_mutex; // Used everywhere "just in case"
// "Just in case" this variable gets corrupted somehow
global_counter = 0; // Reset at start of every function
  • Obscures actual requirements - What are the real preconditions?
  • Adds complexity without clear benefit
  • Makes debugging harder - masks the real source of problems
  • Performance overhead from unnecessary checks/operations
  • Indicates lack of understanding of the code’s contract

Just-in-case programming is the opposite of Make intentional design decisions. It’s driven by:

  • Fear of failure
  • Uncertainty about requirements
  • Lack of trust in other code
  • Cargo cult programming (copying patterns without understanding)
  • Understand your contracts - What are the actual preconditions and postconditions?
  • Use assertions for debugging assumptions rather than defensive code
  • Document assumptions explicitly
  • Write tests that capture actual requirements
  • Trust your interfaces - if they’re unreliable, fix them directly