Code smell: obscured intent

G16. Obscured Intent. We want code to be as expressive as possible. Run-on expressions, Hungarian notation, and magic numbers all obscure the author’s intent. .. Small and dense as this might appear, it’s also virtually impenetrable. It is worth taking the time to make the intent of our code visible to our readers.

Robert C. Martin. Clean Code. A Handbook of Agile Software Craftsmanship, 2009

A code snippet had me scratch my head while I was creating a new test case for it.

     if (op_orig == 2 && !get_config(obj, flag1))
         raise_fault("bit unset"));
     else if (op_orig == 1 && !get_private_config(obj, flag_foobar))
         raise_fault("bit unset"));
     else if (type != TxOther && mode != 0x3) {
         int seg = get_seg();
         ireg_t offset = get_lea();
         execute_in_core(seg, offset, type);
     }
     else {
         if (!obj->cfg->has_legacy_compat) {
             raise_fault("bit unset"));
         }
     }

The cases for op_orig == 0 and 3 were supposed to behave identically, but they did not. In the end I figured it out (type was depengind on op_orig). The way the code is written contributed to the obscuring of its intent.

  1. Long chain of if-then-else.
  2. Mixing of error handling (three conditions for raising fault) and normal path (call to execute_in_core()).
  3. Arbitrary order of conditionals: two fault conditions in the beginning, one at the end, and the normal path in the middle.
  4. No handling of the pass-through case (when all conditions are false) leaves it ambiguous whether it was done on purpose, or an omission.

As the first step of refactoring it, all the exceptional conditions have to be moved to the beginning of the block (and then to a separate function). There is no need to daisy-chain them using if-else-if, because raise_fault() throws unconditionally.


Written by Grigory Rechistov in Uncategorized on 03.02.2023. Tags: code smell, code quality,


Copyright © 2024 Grigory Rechistov