Thursday, April 19, 2012

I"m about to use a goto statement


Save me from raptor death - is there any better way to handle this kind of structure?




while(condition) {
$this->phase1();
$this->phase2();
$this->phase3();
$this->phase4();
}



Throughout either one of those methods, the condition could be met. IMMEDIATELY after the condition is met, the loop MUST exit. If I could call break; inside of phase2(); for example, I wouldn't need a goto statement (but of course, that would throw an error).


Source: Tips4all

8 comments:

  1. Return a boolean to execute each stage until successful.

    while (condition) {
    if ($this->phase1() || $this->phase2() || $this->phase3() || $this->phase4()) {
    // Success!
    }
    }

    ReplyDelete
  2. Or you could use the State pattern!

    In summary, instead of having a goto statement, change the internal state of $this such that methods phase1, phase2, phase3 and phase4 have no effect and are empty functions. Since they will be empty functions, you'll fly right through 'em and exit the loop!

    You'll probably also need a pinch of events or the Observer pattern, to know when to change state.

    ReplyDelete
  3. Return a boolean from the different phases. I would return false if it didn't succeed, then check for that and break.

    ReplyDelete
  4. Throw an exception... sounds exceptional...

    try {
    while(condition) {
    $this->phase1();
    $this->phase2();
    $this->phase3();
    $this->phase4();
    }
    } catch (Exception $e) { }

    ReplyDelete
  5. One way might be to use if() statements to check for a return value from each phase*() and break the while loop.

    Something like this:

    while (condition) {
    if ($this->phase1()) { break; }
    }

    ReplyDelete
  6. How about wrapping each of the phases in an if:

    while(condition)
    {
    if(condition)
    {
    $this->phase1();
    }

    if(condition)
    {
    $this->phase2();
    }

    if(condition)
    {
    $this->phase3();
    }

    if(condition)
    {
    $this->phase4();
    }
    }


    Of course, this could probably be made more compact with a bit of planning and a loop.

    ReplyDelete
  7. Please don't use a goto statement, think to the coder who will herit your code base

    if your condition it's not too much of overhead, you could

    while(*condition*){
    $this->phase1();
    if (*condition*){
    $this->phase2();
    }

    ...

    }

    ReplyDelete
  8. $phases=array('phase1','phase2','phase3','phase4');
    foreach($phases as $phase){
    $this->$phase();
    if(condition)break;
    }


    Also , you can use exceptions if you want to break out from inside of the function.

    ReplyDelete