top | item 1439240

Get to No as fast as possible

31 points| tswicegood | 16 years ago |geekswithblogs.net | reply

18 comments

order
[+] oakenshield|16 years ago|reply
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|16 years ago|reply
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.
[+] walkon|16 years ago|reply
I agree with your preference, but just curious - is a return considered a goto? I've not thought so, but I could be wrong.
[+] iamwil|16 years ago|reply
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.

[+] GFischer|16 years ago|reply
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|16 years ago|reply
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...

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

[+] wfjackson3|16 years ago|reply
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|16 years ago|reply
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|16 years ago|reply
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|16 years ago|reply
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?
[+] fleitz|16 years ago|reply
It's generally pretty easy to do if you write your code in a functional/tail recursive style. Instead of modifying your variables and returning, create new variables and pass them back into your function, in that way whatever you create will have to go back through all the sanity checks. Yes you can get infinite loops this way, but it alerts you to having coded your function incorrectly instead of returning the wrong data.

func(condition,resp){ val = true if(!condition){ return func(!condition,'new'); }) return resp } func(false,'whatever');