
Get to No as fast as possible - tswicegood
http://geekswithblogs.net/thibbard/archive/2010/06/17/get-to-no-as-fast-as-possible.aspx
======
oakenshield
I remember back in a Paradigms of Programming class in uni, our professor who
lived by Dijkstra's "Gotos considered harmful" mantra tried to get us all to
write programs with a single exit point from each function. I argued that
short-circuiting errors before going to the logic made sense both nesting-wise
and maintainability-wise, but was ridiculed. I wish I'd known about coding
styles in the Linux/BSD kernels back then so I could throw it back at him.

~~~
scott_s
But the coding styles in the Linux kernel usually maintain a single exit point
from the function. The format they generally have is:

    
    
      syscall(params)
      {
        if (easy check on params fails)
          goto done;
    
        allocate data for work
        if (further check on params and data fails)
          goto cleanup;
    
        perform real work
    
      cleanup:
        deallocate data
      done:
        set return value
      }
    

There's often still a single exit, but it does use gotos to implement simple
exceptions. The only times when there are multiple exits is before any data
has been allocated and there's no cleanup to be done.

------
iamwil
I much prefer this style too.

Every time you have to go into a nest, you have to maintain state in your head
of what the condition is. So by the time you're nested 9 or 10 levels deep
(I've seen this before), I can't remember what all the conditions are that got
me there.

I remember reading the single-exit mantra was the result of hardware and speed
optimization, rather than readability and maintainability optimization, but I
could be remembering wrong.

------
pragmatic
Coding Horror discusses this:
[http://www.codinghorror.com/blog/2006/01/flattening-arrow-
co...](http://www.codinghorror.com/blog/2006/01/flattening-arrow-code.html)

Worth another look. I've found this style much more readalbe and maintainable
down the road and it prevents the "arrow code" in the link above.

------
GFischer
Whenever I see code that asks for conditions that might vary according to the
business rules, I ask myself if there's a better way.

Has anyone had any success with business rule engines? What's your approach to
these kind of constraints?

I'm faced with code like this at work all the time (I mostly maintain
corporate apps, and get requirements like "law XYZ asks for a minimum of
150.000 oddunits for ABC, we need to change all our apps to support that")
Edit: or the far simpler, "we can't sell ABC to people under 21" or "people
from Iran"

~~~
dkimball
Alex Papadimoulis of the Daily WTF has an article on this -- it's his opinion
that the simple, "bone-headed" approach is the best one for constraints like
this, and homegrown business rule engines are dangerous:

[http://thedailywtf.com/Articles/Programming-Sucks!-Or-At-
Lea...](http://thedailywtf.com/Articles/Programming-Sucks!-Or-At-Least,-It-
Ought-To-.aspx)

However, commercial business rule engines might work out better, provided they
stick to XML or known formats of I/O in general.

~~~
GFischer
Thanks for the link.

IMO Alex doesn't give the best advice sometimes (not to wonder, he sees so
much boneheadedness!!!), but he's quite right there... but I don't see the
advice -against- business rule engines there.

I totally agree with your own advice about sticking to commercial business
rule engines. In fact, I'll give Drools.net a try (any other suggestions?).

If any company -needs- a rules engine, it's the one I work for (there's a
"developer" whose main reason for having work is that the business rules
change a lot every freaking month)

PD: I like his linking to Yourdon's book :) - and I have a degree in
"Information Systems" myself

~~~
dkimball
You know, on considering, I think you're right -- he doesn't advise against
rules engines, just the Greenspun's Rule version. (Greenspun's Rule is that
"any sufficiently long-running project includes a slow, buggy, and ad-hoc
implementation of half of Common Lisp.")

I don't have much experience with rules engines, and I don't know what your
budget is like; so I can't really make recommendations. That doesn't stop me
from trying, though...

You might be interested in Intersystems' Ensemble. If you're anything like
Alex, you'll run screaming for the hills at this point, since it's built on
MUMPS (it's an extension of Caché, "postmodern MUMPS," which comes with
everything from a web server to a blindingly fast SQL frontend). If you're not
-- if you realize that it all compiles down to object code anyways, and what's
important is programmer skill and code maintainability, not the presence of
curly braces and variable declarations -- you'll keep reading. (Actually,
Caché's version of MUMPS has both curly braces and variable declarations,
although both are optional.)

Ensemble was designed to translate messages between incompatible healthcare
databases, applying business rules in the process. It can be used for more
than that; part of the training I had in the product (see below for my full
disclosure) was using it to implement a simple loan acceptance protocol.

I think that its "flowchart mode" of execution might be very well suited to
frequently-changing business rules. There's a video at
<http://www.maddash.net/videos/intersystems/ensemble/vehr/> which demonstrates
this -- look at 7:15 for the flowchart (each element in it is programmable as
necessary), and at 2:15 for the related flow through processing modules when
something comes in.

You may be able to get a proof-of-concept demonstration -- see
<http://www.intersystems.com/ensemble/pilot/index.html> for details. Even if
not, if this looks interesting, it wouldn't hurt to get in touch with
Intersystems Sales.

Full disclosure: I work at Intersystems, but I'm not associated with Sales,
and I really should be getting back to work. :)

~~~
GFischer
Thanks for the suggestion. My first instinct is indeed to run for the hills :)

I'm watching the video and the first point is that you should fire the graphic
designer :P (I suspect there isn't any, if a programmer did it, at least the
screens are very clear - heck, maybe a graphics designer would murk it).

PD: after watching the video it's very clear that it's not what I need at all,
but thanks for the suggestion.

Greenspun's rule is something I'm painfully aware of (the main enterprise app
I work with has an ad-hoc implementation of... assembler :P ), but thanks for
the reminder.

~~~
dkimball
Thanks for the update, and for giving it a chance. I agree that the production
values are pretty bad...

Good luck in your search. I've never heard of an ad-hoc implementation of
assembly language before, but while we're talking about wanting to head for
the hills... :)

~~~
GFischer
Heh.. you don't say... it's built with Sun ONE's UDS FORTE development
environment (on a language called TOOL), which stopped being supported years
ago.

Fortunately I don't maintain that one very much, but yes, it's "run-for-the-
hills" worthy - sadly, the current job offers job security and pays above
average for my country.

I'm keeping an eye open, but I haven't found an adequate niche for me yet - my
skills don't translate well to a remote environment, I'll probably try my hand
at consulting.

------
wfjackson3
This methodology is commonly taught for designing discrete logic in
electronics. Make a Karnaugh map to show your true and false states, and pick
to implement the minimized logic for true or false cases only.

------
albertzeyer
I'm always using this style because of much better readability.

If I need some shared cleanup code when the function returns, I'm using some
of the C++ scope-exit trick. Or in most cases, some of the predefined scope-
exit handlers do just what I want. Like:

    
    
      std::auto_ptr or boost::scoped_ptr
      boost::shared_ptr
      boost::interprocess::scoped_lock (or I have my own mutex scopedlock class)

------
emehrkay
I much prefer one return per mehtod/func. Of course there are cases where that
isn't possible, but I feel that if it were structured the right way, the code
would be easier to read.

    
    
        func(){
            val = true
            resp = 'whatever'
    
            if(condition){
                resp = 'new'
            }
    
            return resp
        }

~~~
nihilocrat
What do you do if in between if(condition) and return, there are a bunch of
actions that modify state outside the function that, if condition is true,
you'd never ever want to do?

~~~
emehrkay
else ?

