@Rank Amateur said:
@dtech said:
I don't know exactly why and how this is used, but isn't that the easiest way if you want to do something, well, when either condition P or not condition P but condition Q?
P || (!P && Q) is logically equivalent to P || Q, but you hit on the cause of the pattern: bad requirements gathering. Someone phrased the problem as, "Do it if the date is in the future, but also do it if the interest is compounded as long as the date is not in the future." That could be interpreted as the above, which is the same as "Do it if the date is in the future or the interest is compounded." Or it could be interpreted as (P && !Q) || (!P && Q): "Do it if the date is in the future _except if the interest is compounded_; do it if the interest is compounded as long as the date is not in the future."
Yep, they're all equivalent - unless (as someone else pointed out) P and/or Q are expressions with side-effects, in which case it's unsafe, or at least brittle, putting them in this expression anyway.
I see this one quite often, and it annoys the $excrement out of me every time. I've even seen "P OR (Q AND NOT P) OR (R AND NOT P AND NOT Q)" in a SQL SELECT before now. Probably with extra, redundant brackets. This is just just "P or Q or R" in obfuscator's clothing. Plus, at least one of the three expressions was like some_table.some_column <= to_date(:date_in_a_string, 'DD/MM/YYYY') as well. Don't ask about dates-in-a-string, it's a Pro*C thing.
I don't think it's down to bad requirements gathering, nor the history of the code. To me it looks like a bad optimisation, as if testing "P or Q" would over-do it because it sort of covers the case "P and Q" twice. Once you've tested P, you see, you don't need to test the case P and Q, so you test (Q and not P), and that's gotta be quicker, right?
I've got a whole bag of Gaaaaah!! with these people's names on it.