I Am Not Myself

Bills.Pay(Developer.Skills).ShouldBeTrue()

De Morgan’s Laws: Boolean Logic Is Serious Business

Today, Alex and I were pairing on a bug in our system dealing with an editor screen. Some properties of the item being edited are not editable based on the value of other properties of the item. This is implemented in the system fairly easily as a series of “can edit” like methods on the item’s view model.

The original code containing the bug looked like this:

private static bool IsInitializedAvailable(ModuleClass moduleClass, Indices indices)
{
    return moduleClass != ModuleClass.Liability && indices != Indices.Constant;
}

The bug stated that ArbitraryIndex was also a invalid value for indicies. This sounded like a simple enough fix to Alex and I. And we quickly implemented this:

 private static bool IsInitializedAvailable(ModuleClass moduleClass, Indices indices)
 {
     return moduleClass != ModuleClass.Liability && (indices != Indices.Constant || indices != Indices.ArbitraryIndex);
 }

This failed our unit test. In attempting to figure out why, I used a technique I have used in the past for figuring out boolean logic. I broke the comparisons out into separate pieces. So I could understand the logic of them better. Like so:

 private static bool IsInitializedAvailable(ModuleClass moduleClass, Indices indices)
 {   
    var isLiability = moduleClass == ModuleClass.Liability;
    var isConstantOrArbitraryIndex = indices == Indices.Constant || indices == Indices.ArbitraryIndex;
    
    return !isLiability && !isConstantOrArbitraryIndex;
}

This actually passed the tests, so we reconstituted the one-liner to get rid of the unneeded variables. Like so:

 private static bool IsInitializedAvailable(ModuleClass moduleClass, Indices indices)
 {   
    return moduleClass != ModuleClass.Liability && !(indices == Indices.Constant || indices == Indices.ArbitraryIndex);
}

Both Alex and I were uncertain why there was a difference between the original bug fix implementation and the final correct implementation. The two statements appear on the surface to be the same at a glance. Take a look yourself, can you spot the difference?

    moduleClass != ModuleClass.Liability && !(indices == Indices.Constant || indices == Indices.ArbitraryIndex); //wrong
    moduleClass != ModuleClass.Liability && (indices != Indices.Constant || indices != Indices.ArbitraryIndex);//correct

Alex, and I were stumped. That is when Alex’s CompSci degree from U of W woke up and he diagrammed out a Truth Table for the boolean expressions. It looked like this:

He went on to explain that boolean logic actually has clearly defined laws known as De Morgan’s Laws.

The rules can be expressed in English as:

“The negation of a conjunction is the disjunction of the negations.” and
“The negation of a disjunction is the conjunction of the negations.”

I am going to have to read up on both as they sound like a significant hole in my developer tool box. Thanks, Alex!

2 responses to “De Morgan’s Laws: Boolean Logic Is Serious Business

  1. Mark Simpson (@verdammelt) September 28, 2011 at 5:47 pm

    Oh yeah, DeMorgan’s law – I remember learning that. I guess I ought to re-learn it.

    As for your way of debugging the problem by breaking things out – you also _named_ the parts. I find that is the important part – if i name a part of a boolean expression isAThingie but i see that the boolean expression really checks if it is a Gizmo – then i see the problem – but it would have been invisible without the name.

    To name a thing is to have power over it 🙂

  2. Paul Batum (@paulbatum) September 28, 2011 at 9:38 pm

    I preferred the version with the variables. I understood what the code did!

Leave a reply to Paul Batum (@paulbatum) Cancel reply