rootcho has asked for the wisdom of the Perl Monks concerning the following question:

hi,
I have one app in wich to do my job i have to make alot of if/unless-else chained checks and in most of the cases the actions after that are no more than 3, not everytime but ..!!
Because after a while they become very ugly I want to find a way to simplify the things and make the code more strightforward/non-hairy ;).
But let me show u simple example
$o->check(...); unless ($o->state) { action.. } else { $o->check(...); unless ($o->state) { action.... $o->blah() if ($o->state) { actions..check.. unless($r->state) { and so on...deeper and deeper... } } } }
Most of the checks are on $object->state(), but not nececerily.
For the sake of it things become more underadable when I add alot of comments to clarify the things ;))
I'm looking for an idea how to make this easier for the users of my module. So if the idea adds more complex code/behavior on the Class i'm building it is doable. My main goal is to simplify the task of the other programmers.
I was thinking something on the line of prolog like syntax or I see some lang have 'assert', (cant figure out the idea exactly) !!. But it has to stay perl, not something parsable, 'cause sometimes there is very convulved logic to be added.


10x alot in advance

Replies are listed 'Best First'.
Re: deep usage of if-else!!
by GrandFather (Saint) on May 01, 2006 at 19:42 UTC

    In this situation I try if possible to take advantage of early exits:

    If this is inside a while or for loop use last as the final statement in any block preceeding an else and omit the else. If it is inside a sub and there are no statements following the topmost if, use return in place of last in a similar fashion.

    If need be change the sense of the test to take advantage of this technique. For example, assuming a sub:

    $o->check(...); unless ($o->state) { action.. return; } $o->check(...); return if $o->state; action.... $o->blah() return unless $o->state; actions..check.. return if $r->state; and so on... at the same level


    DWIM is Perl's answer to Gödel
Re: deep usage of if-else!!
by davidrw (Prior) on May 01, 2006 at 18:06 UTC
    Not sure i really like this, but it's logicaly equivalent and cleans it up a little ..
    if( do{$o->check(...); ! $o->state} ){ action.. }elsif( do{$o->check(...); ! $o->state} ){ action.... $o->blah() if ($o->state) { actions..check.. unless($r->state) { and so on...deeper and deeper... } } }
    It's hard to say w/o knowing what the check() and state() methods do and their return values.. In general, I would say to push things off into methods ..
    $o->check(...); unless ($o->state) { $o->actionSet1; } else { $o->check(...); unless ($o->state) { $o->actionSet1; } }
    So what does the check() method return? if it did return $this->state then things simplify alot:
    unless ( $o->check(...) ) { action.. } else { unless ( $o->check(...) ) { action.... $o->blah() if ($o->state) { actions.. unless( $o->check(...) ) { and so on...deeper and deeper... } } } }
      yes $o->check() returns 0 or 1, but in most of the cases it is too long i.e. parameter passed to it, that is why i'm using $o->state.
      But yes as u and Hue-Bond said I can see which are the most frequently combination of checks and actions and separate them into methods, this way I will shorten things abit.(before i read your replies i figured out to shorten one of them).
      But then, i can do this for just several of them, otherwise i will go into the trap of too-many-methods ;)
      That is why i was wondering that probably someone already invented something along these lines ;))
      thanx for your replies
        yes $o->check() returns 0 or 1, but in most of the cases it is too long i.e. parameter passed to it
        too long? so? that's fine, or bundle the params into a hash, or store in the object:
        if( ! $obj->check( blah => 1, stuff => 2, foo => 'bar', ... )){ ... } my %params = ( blah => 1, stuff => 2, foo => 'bar', ... ) if( ! $obj->check(%params) ){ ... } $obj->blah(1); $obj->stuff(2); $obj->foo('bar'); ... if( ! $obj->check() ){ ... }
      if( do{$o->check(...); ! $o->state} ){ action.. }
      Why the do block instead of a comma?
      if($o->check(...), ! $o->state} ){ action.. }
      ...not that I think that putting multiple things inside the conditional of an if is a good idea.
Re: deep usage of if-else!!
by Hue-Bond (Priest) on May 01, 2006 at 17:51 UTC

    You should try to divide that piece of code in logical, reusable parts that can be abstracted into functions. That way, the nesting won't go very deep and your program will gain in readability and maintainability.

    --
    David Serrano