in reply to The -w switch on a web application

Below I posted two pieces of the code. The first one is checking for defines, the second - doesn't. The second one is more nicer, because if we don't check for undef values, we can delegate function calls to each other without having intermediate variables. If I start checking for defines, my code becomes full of if and unless sentences.

The code is creating a menu object and setting the active menu for it, which it has to display say in a different color. Of course, the checking for the active menu could be done inside the Menu object, but in my design it's outside. So, my code has to check for the undef value from the CGI param() function and from my get_active_menu_id() functions as well, because they don't always return a defined value.

I lose the flexibility of perl and I worry pretty much about it. What should you do in such a situation?

The checks for defined version:

my $main_menu = new Menu("main"); my $menu_item = param('menu_item'); if(defined($menu_item)) { my $active_menu_id = get_active_menu($menu_item); $main_menu->active_menu_id($active_menu_id) unless !$active_menu_id; } $main_menu->output;

No checks for defined version:

my $main_menu = new Menu("main"); $main_menu->active_menu_id(get_active_menu(param('menu_item'))); $main_menu->output;

So what do you think, is it worth checking for defines on such a code or not?

Replies are listed 'Best First'.
Re^2: The -w switch on a web application
by Aristotle (Chancellor) on Jan 31, 2003 at 14:08 UTC
    Depends on which of these is realistically going to make a difference. I'd write something like this:
    my $main_menu = Menu->new("main"); my $active_menu_id = get_active_menu(param('menu_item')||''); $main_menu->active_menu_id($active_menu_id) if defined $active_menu_id; $main_menu->output;

    The distinction between the user selecting no menu item or submitting an invalid selection is not likely to matter, so I just default that case to a defined but invalid value. Whether or not he has select a valid menu item however definitely is important, so I check that case appropriately.

    Btw, indirect object syntax looks neat but has a bunch of caveats. Use the arrow notation instead.

    Makeshifts last the longest.

Re^2: The -w switch on a web application
by diotalevi (Canon) on Jan 31, 2003 at 14:26 UTC

    And this is part of where perl6 will be very nice. It is an important thing though to provide default values especially for web programming since if you port to mod_perl then you are required to provide default values regardless.

    # Provide an empty string as the default value if the # menu item value isn't provided. my $menu_item = param('menu_item') // '';

    In perl5 I write this as:

    # Provide an empty string as the default value if the # menu item value isn't provided. my $menu_item = param('menu_item'); $menu_item = '' unless defined $menu_item; # OR to be brief local $_; # As you enter the block $_ = param('menu_item'); my $menu_item = defined() ? $_ : '';

    Or if you feel like being cute (and slightly obfuscatory)

    $menu_item = defined() ? $_ : '' for (param('menu_item');

    I think you also meant to write unless ! as if but that's separate.


    Seeking Green geeks in Minnesota

Re: Re: The -w switch on a web application
by l2kashe (Deacon) on Jan 31, 2003 at 14:09 UTC
    Test, test, test. Yes the second snippet is straight forward, but im sure there would be all sorts of ways to mess with it. How about something like the following..
    # # I split the code, but I dont think it would need to be on # a new line in an 80 char window # my $main_menu = new Menu("main") || &some_error_routine("Failed to create menu obj! $main_menu->err\ +n"); my $menu_item = param('menu_item') || &some_error_routine("No menu_item passed to cgi!"); my $active_menu_id = get_active_menu($menu_item) || &some_error_routine("Cant collect menu_id!!\n"); # # There should probably be a test here as well # $main_menu->active_menu_id($active_menu_id); $main_menu->output;
    If the sub routines return 0, nothing, or undef the second half of a line will be executed. Also when attempting to debug later, you can do a couple of things. Within the some_error_routine, you can watch for say a global $DEBUG, and depending on what the value of it is, you can determine what types of messages to send out to the log file, if debug isnt defined and you receive messages to be logged, you can still trim down your output, but you dont need to spend X amount of time adding debug statements to the rest of your code. You simply go to main, define 1 scalar, and then run the code again. Once your done with testing, you whack the scalar and everything goes back to normal.

    I find it best for myself, that once a app reaches a certain point in either complexity or frequence of run time, I add a simple error logging sub. But hey its just works for me :)

    Edit: Post morning coffee, I realize I didn't really stress what I wanted to. Basically you can control the behaviour of your code in terms of logging and dieing from a single sub. Also with logging this way, and parsing the error log, you should be able to quickly figure out where in the code you failed and for what reason. You could get this done via croak/warn/die, but if the app is getting as big as you say, its easier for me to control it all from a single point, as opposed to multiple source files and libs.

    /* And the Creator, against his better judgement, wrote man.c */