Monday, October 12, 2009

Insanity of Anti-If Campaign

I noticed the Anti-If Campaign on Hacker News this morning. This is other one of my pet peeves about received OO wisdom. Essentially, a lot of these people take the extremely useful virtual function approach to handling object logic and try to stretch it far too far.

So on the one hand, we have something like Perl 6's .Str function. Trying to implement that any way other than a virtual method calling mechanism would be insanity, because you want code to be able to call that function from anywhere and get the proper result no matter what kind of object you are calling it on. You want to be able to say "The answer is $a" without using some obscene string of ifs based on the type of $a. That's a no brainer.

But on the other hand, consider converting a surface object from a nice surface class hierarchy into another surface format which the original class hierarchy can't know anything about. "Aha," the anti-if zealot says, "an opportunity for the Visitor pattern!"

I went through a phase of heavy Visitor pattern usage back around 1997 or so. And in retrospect, I'm pretty sure nine out of ten times I used it, the code would have been better had I just used an if statement; frequently much better.

Here's a quick example: suppose I'm processing a $surface, and I'd like to use exact calculations if it's a (dead simple) plane surface, and approximate calculations otherwise. So I'm looking to set $use_exact_calculations as appropriate. Here's my best attempt (untested!) to capture the Visitor pattern in Perl 6:

If you think this is wordy, you should see the C++ version! Perl 6 is very good at this sort of thing. But still you're creating an entire class just for one usage, and in the process moving critical logic away from the place the logic is actually used.

But would you really rather have that in your code just so you can get rid of this:

Okay, technically that doesn't actually have an if statement, but it does have the dreaded direct examination of the type of $surface, which is what they would like to eliminate the ifs to avoid.

Okay, now. Does anyone seriously think the former code is better than the latter?

4 comments:

  1. The point of the Anti-If Campaign it not to never use if:s, it is to think twice before using them. Or as their web page says it;

    "The primary purpose of our campaign is to become aware of the design consequences of using IFs and of control structures in general, applied by following the path of the procedural paradigm in Object Oriented contexts. This greater awareness will enable you to understand how to achieve more effective results in terms of flexibility, comprehensibility, testability, and ability to evolve."

    ReplyDelete
  2. The problem with the if-elses are that you can't define a concept using them, I'm a human not a machine, machines are very good on understanding if-else-elseif-switch etc but as a human I need something different: this object model this concept and send a message to this other obj that models..and so on... This doesn't mean that you never write if-elses, that is impossible because if-elses are at the heart of computer processing but as a human you must model the world by expressing concepts not using machine language.

    ReplyDelete
  3. Ok, maybe it's the fact that I'm out of practice with Perl, or maybe I'm misunderstanding your example, but why would you even consider using a Visitor here? Visitor is intended to simulate double-dispatch in languagdes that don't provide it out-of-the-box. I fail to see why you'd need that capability here.

    Why not just:

    my $use_exact_calculations = $surface.uses_exact_calculatons

    Usually, when I see control code based on the type of an argument, it indicates to me that there may be a misallocation of responsibility. In this case, I'd probably want to ask the plane to supply a calculation algorithm.

    ReplyDelete
  4. Hi, the point of the Anti-IF campaign is to suggest that changing code is not the only way to cope with changing requirements. I can tell you that the average programmer in the field does not even *suspect* that, in principle, you should get to a point where new requirements are met by adding code, not changing it.

    Pattern-happy programmers have a different problem, but the goal is the same for every programmer, to get to a design that's robust wrt requirement changes and simple at the same time.

    ReplyDelete