When adding loops and conditionals, even simple code can become difficult to understand.
Consider this change:
if (commode.HasPreferredCustomer()) { | if (commode.HasPreferredCustomer()) { |
commode.WarmSeat(); | commode.WarmSeat(); |
| } else if (commode.CustomerOnPhone()) { |
| commode.ChillSeat(); |
} | } |
While the above change may seem simple, even adding a single else statement can make the code harder to follow since the complexity of code grows quickly with its size. Below we see the code surrounding the above snippet; the control flow on the right illustrates how much a reader needs to retain:
while (commode.StillOccupied()) { if (commode.HasPreferredCustomer()) { commode.WarmSeat(); } else if (commode.CustomerOnPhone()) { commode.ChillSeat(); } if (commode.ContainsKale()) { commode.PrintHealthCertificate(); break; } } |
Code Control Flow with 5 structures and 9 edges: challenging for a reader to retain in memory. |
In order to fully understand the code, the reader needs to keep the entire control flow in their head. However, the retention capacity of working memory is limited (source) Code path complexity will also challenge the reader, and can be measured using cyclomatic complexity.
To reduce cognitive overhead of complex code, push implementation logic down into functions and methods. For example, if the if/else structure in the above code is moved into an AdjustSeatTemp() method, the reviewer can review the two blocks independently, each having a much simpler control graph:
while (commode.StillOccupied()) { commode.AdjustSeatTemp(); if (commode.ContainsKale()) { commode.PrintHealthCertificate(); break; } } |
3 control structures and 5 edges: easier to remember |
Commode::AdjustSeatTemp() with 2 structures and 4 edges |
Avoiding complexity makes code easier to follow. In addition, code reviewers are more likely to identify logic errors, and maintainers are less likely to introduce complex code.