Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Re: Why I Hate Nested If-Else blocks

by mstone (Deacon)
on Jan 04, 2002 at 02:30 UTC ( [id://136124]=note: print w/replies, xml ) Need Help??


in reply to Why I Hate Nested If-Else blocks

I use two general solutions, depending on how complex the problem is.

The first option is to use a table of function pointers:

%FLUT = ( 'condition_1' => \&func_1, 'condition_2' => \&func_2, 'condition_3' => \&func_3, ); $condition = ## reduce the input to a known condition $FLUT{$condition}->(@args);

and since I happen to like object syntax, I have a simple little class that wraps function pointers up as objects:

package Command; sub new { my $type = shift; my $O = shift; bless $O, $type; return ($O); } sub execute { my $O = shift; return ($O->( @_ )); }

Naturally, it helps to make sure all the functions/objects in a table take the same list of arguments. That restriction appeals to me, because it helps me write code that ends in a known state no matter what. Nested if-else statements make it a little too easy to set one set of globals in one branch, and another set of globals in another, IMO. That makes it really difficult to decide what state the program is in when it leaves the outermost statement.

If a project involves serious branching, I'll occasionally roll my own linear state machine:

package Machine; ## new (nil) : Machine_ref # # trivial constructor # sub new { my $self = bless {}, shift; return ($self); } ## execute # # run through the list of commands, halting when one of them fails # sub execute { my $self = shift; my $model = shift; for $cmd (@{ $self->_get_commands() }) { # [1] last if ( 0 == $cmd->execute ($model) ); # [2] } return(); } ### # [1] iterate over the list of Command objects that belongs to the # specific Machine, executing each one in turn. # [2] drop out of the loop if any Command in the sequence returns # a zero. # # in practice, this is equivalent to executing a set of # short-circuit conditionals: # # if (<condition 1>) { return ('value 1') } # if (<condition 2>) { return ('value 2') } # if (<condition 3>) { return ('value 3') } # # but it's cleaner, and you can make each Command much more complex # than the body of a sensible conditional. ### ## STATE-SPECIFIC OPERATIONS ## _get_commands (nil) : listref # # each Machine has its own list of Commands that should be # executed in response to the user's input. this routine returns # a reference to that list. # sub _get_commands { return ([]); } 1;

This code comes from a larger project, where the parameter $model was itself an object. The Model was responsible for all the data in the program, and the Commands simply called sets of Model methods.

Replies are listed 'Best First'.
(podmaster: Why I hate too many #)Re^2: Why I Hate Nested If-Else blocks
by PodMaster (Abbot) on Jan 04, 2002 at 13:30 UTC
    Can you please explain the following to me?
    ## _get_commands (nil) : listref # # each Machine has its own list of Commands that should be # executed in response to the user's input. this routine returns # a reference to that list. #
    What prompted you to do that? What I expect is the following?
    =head1 FUNCTIONS .... =head2 C<_get_commands (nil) : listref> each Machine has its own list of Commands that should be executed in response to the user's input. this routine returns a reference to that list. =cut
    If you're going to bother writing more than two lines of documentation, please make it POD, that is what it is for.
     

    ____________________________________________________
    ** The Third rule of perl club is a statement of fact: pod is sexy.

Re(2): Why I Hate Nested If-Else blocks
by dmmiller2k (Chaplain) on Jan 04, 2002 at 21:58 UTC

    Bravo! Another proponent of data-driven dispatch.

    "... in practice, this is equivalent to executing a set of short-circuit conditionals ... but it's cleaner, and you can make each Command much more complex than the body of a sensible conditional."

    This approach has the tendency to scare off some programmers, since the state machine engine's code is completely independent from the data which defines the state-machine, but once you have your hands around the concept, the ease with which fundamental changes to the logic may be made justifies the learning curve.

    If one is not careful with this approach, it is easy to end up with Write-Only code, however.

    dmm

    You can give a man a fish and feed him for a day ...
    Or, you can
    teach him to fish and feed him for a lifetime

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://136124]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (6)
As of 2024-03-29 01:09 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found