Page 1 of 1

### Use the NOT operator as little as possible

Posted: 21 Feb 2013, 22:20
Simplify Boolean expressions using the De Morgan's Laws:

(NOT a) OR (NOT b) can be expressed shorter as NOT (a AND b)
(NOT a) AND (NOT b) can be expressed shorter as NOT (a OR b)

So, in that situation, the NOT operator is used only once. A COMPLEX expression is converted to a SIMPLE expression which is negated.

EXAMPLE 1 - "AND" BECOMES "OR":

The expression

Code: Select all
`gas = (NOT liquid) AND (NOT solid) AND (NOT plasma)`

should be simplified to

Code: Select all
`gas = NOT (liquid OR solid OR plasma)`

EXAMPLE 2 - "OR" BECOMES "AND":

To go to a restaurant, 2 conditions must be satisfied: you must be hungry (you will not force yourself to eat if you are full), AND restaurants must be open now (in 2 AM, you will go to your fridge, not to a restaurant ):

Code: Select all
`i_stay_home = (NOT i_am_hungry) OR (NOT restaurants_are_open_now)`

The code reader makes an effort to understand a COMPLEX condition - "(NOT i_am_hungry) OR (NOT restaurants_are_open_now)". But let's simplify the expression to

Code: Select all
`i_stay_home = NOT (i_am_hungry AND restaurants_are_open_now)`

Now, the code reader sees a SIMPLE condition - "i_am_hungry AND restaurants_are_open_now"; the Boolean variable is set to TRUE when that condition is not satisfied.

Try to avoid the NOT operator at all

From the book "PL/SQL Best Practices":

Use IF...ELSIF only to test a single, simple condition

The real world is very complicated; the software we write is supposed to map those complexities into applications. The result is that we often end up needing to deal with convoluted logical expressions. You should write your IF statements in such a way as to keep them as straightforward and understandable as possible. For example, expressions are often more readable and understandable when they are stated in a positive form. Consequently, you are probably better off avoiding the NOT operator in conditional expressions.

Example

It's not at all uncommon to write or maintain code that's structured like this:

Code: Select all
`IF condA AND NOT (condB OR condC) THEN   proc1;ELSIF condA AND (condB OR condC) THEN   proc2;ELSIF NOT condA AND condD THEN   proc3;END IF;`

It's also fairly common to get a headache trying to make sense of all of that. You can often reduce the trauma of headache by trading off the simplicity of the IF statement itself (one level of IF and ELSIF conditions) for the simplicity of clauses within multiple levels:

Code: Select all
`IF condA THEN   IF (condB OR condC) THEN      proc2;   ELSE      proc1;   END IF;ELSIF condD THEN   proc3END IF;`

Don't forget, by the way, to take into account the possibility of your expressions evaluating to NULL. This can throw a monkey wrench into your conditional processing.

An Exception to the Rule

A notable exception to this best practice is when you need to negate a large AND expression in order to find out efficiently whether one value out of a group is different. For example, I recently needed to test the counts of 10 parallel index-by tables, to see if even one of them was different; if so, it was an error. Because AND expressions short-circuit on FALSE (whereas ORs short-circuit on TRUE), this was more efficient than using a group of ORs. Moreover, the logic read more naturally. For example:

Code: Select all
`IF NOT (arr1.count = arr2.count   AND arr1.count = arr3.count   AND arr1.count = arr4.count AND . . .   AND arr1.count = arr10.count) THEN RAISE e_missing_value;`

Benefits

Following this best practice will make your code easier to read and maintain. Breaking an expression into smaller pieces can aid maintainability; if and when the logic changes, you can change one IF clause without affecting the logic of others.

Challenges

Multiple levels of nested IF statements can also decrease readability. You need to strive for a workable balance.