Summary of "If considered harmful: How to eradicate 95% of all your bugs in one simple step - Jules May"

Summary of "If considered harmful: How to eradicate 95% of all your bugs in one simple step" by Jules May


Main Ideas and Concepts

  1. The Core Problem: Synchronized Conditions (Ifs) as the Major Source of Bugs
    • Jules May claims that about 90% of bugs in large codebases stem from a single anti-pattern involving duplicated or synchronized conditional checks (i.e., repeated if statements controlling different parts of code).
    • This anti-pattern causes "wormhole code," a form of "spooky action at a distance" where logically connected conditions are physically separated in code, leading to desynchronization and bugs.
    • Secondary bugs (bugs caused by fixing other bugs) approach 99% and are also largely due to this pattern.
    • Contrary to popular belief, the goto statement is not the main culprit; rather, it is the misuse of if conditions that causes the majority of problems.
  2. Historical Context: Edsger Dijkstra’s Work on structured programming
    • Dijkstra’s 1968 letter, "The Case Against the Go-To Statement," linked the presence of gotos to bugs and introduced the concept of structured programming.
    • He introduced the concept of an execution coordinate, a way to link program code location (spatial/static) with the point in time during execution (dynamic), allowing better program understanding.
    • structured programming replaces free-form gotos with controlled flow constructs (loops, conditionals, function calls) that maintain a clear execution coordinate.
    • Modern programming has tamed gotos through structured constructs, but the equivalent discipline for if conditions is lacking.
  3. Execution Coordinates and structured programming
    • Execution coordinates represent a program’s position both in code and in execution time, including call stack and loop iterations.
    • Structured programs maintain a one-to-one mapping between code location and execution time/history.
    • Unstructured code (e.g., excessive or unsynchronized ifs and gotos) breaks this mapping, making debugging and reasoning difficult.
  4. The Anti-Pattern: Repeated or Synchronized If Conditions
    • Having the same condition tested in multiple places leads to bugs because these conditions can get out of sync.
    • This is worsened by debugging practices that patch bugs by adding new if conditions scattered throughout the code, increasing technical debt.
    • These scattered conditions represent latent defects waiting to cause malfunctions.
  5. Distinction Between Defects and Malfunctions
    • A defect is a fault in the code; a malfunction is the observable failure caused by a defect.
    • Not all defects cause malfunctions immediately; many sit dormant until triggered.
    • Adding scattered conditionals as patches increases defects rather than eliminating them.
  6. Proposed Solution: Decision Structure and Concentration of Conditions
    • Instead of scattering conditions (ifs) throughout the code, centralize the decision logic in one place.
    • Separate decisions (conditions/tests) from their consequences (actions).
    • Use constructs that imply decisions from the shape of the code rather than explicit repeated conditionals.
    • This mirrors how structured programming replaced goto with loops and function calls.
  7. Techniques and Methodologies to Implement the Solution
    • Assertions:
      • Use assertions to enforce preconditions and invariants, stopping execution immediately when conditions fail rather than patching with if.
      • Assertions can be runtime (throw exceptions, abort) or compile-time (type checks, contracts).
      • Assertions document intent and improve reliability by catching defects early.
    • Polymorphism and Value Polymorphism:
      • Use polymorphism to handle different cases instead of if-based conditionals.
      • Value polymorphism (common in functional languages like Haskell or F#) allows dispatch based on values as well as types.
      • Express decision logic at the function or class level, not scattered in multiple ifs.
    • Factory Methods and Object-Oriented Design:
      • Concentrate decision logic in factory methods that instantiate appropriate subclasses based on input conditions.
      • Make constructors private and expose creation only through factory methods to control instantiation logic centrally.
      • This reduces scattered conditional logic and keeps consequences grouped in related classes.
    • Null Object Pattern Instead of Null Pointers:
      • Avoid null pointers as they cause many bugs requiring scattered null checks.
      • Use null objects that implement the expected interface but represent "no operation" or default behavior.
      • Null objects can be checked at compile time and reduce runtime defects.
    • Pre-compilers and Compiler Extensions:
      • Use pre-compilers or compiler extensions (e.g., Roslyn for .NET) to enforce code hygiene, such as ensuring fields are initialized and conditions are centralized.
      • Automate checks to prevent introduction of defects.
  8. Modern Language Support

Category ?

Educational


Share this summary


Is the summary off?

If you think the summary is inaccurate, you can reprocess it with the latest model.

Video