Conditional logic, such as if/else, switch/case constructs, truth tables and state machines are common to most programming languages. In today’s blog, there are two aspects of conditional logic that I want to address in today’s post, independence, efficiency versus clarity.
Let’s compare two simple examples, in the first we have a single variable “A”, in the second we have three variables “A”, “B” and “C”
If we consider the first case the order of the comparisons (A==1) and (A==2) can be changed with no impact on the functional behavior of the code. This is because the two conditions are mutually exclusive (1). However in the second case, without formal analysis, we cannot say if the order affects the functional behavior. That is to say, if both A, B, and C can be true at the same time then the order of evaluation impacts the resulting functional behavior (2).
Frequently people are not aware of this possibility and as a have difficulty in evaluating the functional behavior of their code(3).
Efficiency versus clarity
For most people, the standard gear shift in cars is well known, with the order of states PRNDL as a standard (Park, Reverse, Neutral, Drive, Low). Therefore you commonly see conditional logic (or state logic) that represents the PRNDL like this…
However, from an efficiency point of view, this is poorly defined. The majority of the time the transitions you will see are from park to reverse, park to drive, drive to park or reverse to park. This would suggest the following organization
Why is this more efficient? Simply put it reduces the average number of comparison operations required to reach the desired end state.
The previous example was fairly straight forward; there is a single variable with independent states. It is more common to find compound conditions defining the if/then/else logic. Let’s look at our friends, A, B and C again.
This first example is a classic compound if statement. In this example, the logic is fairly straight forward.
So which of these is more readable? This is a difficult question to answer. In this case, the indented format of the code makes the binary nature of the if/else-if/else conditions clear. However, if I introduced more complex evaluations, non-binary operations, then it would perhaps a hybrid of the two formats would be preferable.
Rules of thumb
- Keep the number of comparisons on a single line 3 or less: Exceeding 3 comparisons per line make validation of the coverage of the case difficult.
- Keep the depth of if/if/if trees to 3 or less: Traceability back to the top of the tree decreases at depths greater than 3.
- Place the binary comparisons at the top level of your if/if/if trees: Placing the binary operations at the top of the tree reduces the overall number of if/else required.
Formatting and density of information are frequently “hot topics” of debate. The rules of thumb listed above should not be considered a final verdict but rather a starting point for discussion. As always I welcome all comments.
(1) Note this may not be true if you move to a quantum computer where a single bit could maintain multiple states. Until then you are fine this statement holds true.
(2) The second screen shot has a common error; lack of documentation. The code should be commented to state if the code can be reordered.
(3)The common scenario has a person perplexed why they do not call “callBsFunction” when B is true. Not realizing that it is gated by the “A” is true if statement.