While working on some business code involving a number of modules from CPAN, I came across a quandary with regard to the behaviour of functions from one of the more well-known and widely used of CPAN modules. The role of the function in question was to validate an argument and return a value based upon the result of the validation tests - As such, as the unwitting user of this module and function I may be forgiven for expecting that the function would simply return a true or false value based upon the passed arguments.

The guilty module? Date::Calc ... This is where, as the classics say, the plot thickens ...

As a result of user interaction (from the command line arguments passed to the script), the argument which is passed to this validation function can quite correctly be null; At this point, I should clarify that the passed argument in this scenario is defined but null, not undefined - For an explanation of this definition, have a look at What is truth? (Curiosity corner) by robin. The expected result from this validation function in this scenario is false, that is, the passed argument does not pass validation tests. The result however was a die statement with suggested function usage and arguments.

The code which caused the problem ...

use Date::Calc qw/ check_date Localtime /; my $date = shift @ARGV; my @date = split '-', $date; unless (check_date(@date)) { carp( 'Invalid date supplied from command line - Overriding with c +urrent date' ); @date = (Localtime)[0..2]; $date = join '-', @date; }

The aim of the code above is to assign the variables $date and @date with either the current date or that supplied by the user from the command line (and to warn the user of the overriding of the supplied date value when this occurs). Working defensively, the check_date method of Date::Calc is called for the validation of the user supplied date string and this is where the problem arises. It appears that calling the check_date method with anything other than three arguments, such as the case when the @date array above is empty, the module dies with the suggested function usage and arguments.

Usage: Date::Calc::check_date(year,month,day) at -e line 17

Is this rational behaviour to expect from the check_date method from the Date::Calc module? Well, to my mind, yes and no - While, suggested function usage and arguments are welcomed and appreciated whenever and wherever documented, I was less than enthralled when I found my script dying when no command line arguments were supplied. To my mind, the expected result from the validation function when no command line arguments were supplied was false, that is, an invalid date was supplied. Is this unreasonable? Perhaps, but when passing such arguments to a validation function, what would you expect to be returned?

The content of this meditation is to call for a smarter approach to the writing of validation functions and alike such that a defensive approach is taken and only expected and documented values are returned from your code. From this experience, I certainly know that I will be revising some of my validation functions and modules.

In short, please make the functions in your code "dumber" ... but be smart about doing it.

 

Addendum

The following code represents the revised code which takes this behaviour of Date::Calc into consideration and supplies a "dummy" and invalid date when none is supplied from the command line:

use Date::Calc qw/ check_date Localtime /; my $date = shift @ARGV; my @date = split '-', ( $date || '2002-02-31' ); # Naturally, this dat +e is invalid unless (check_date(@date)) { carp( 'Invalid date supplied from command line - Overriding with c +urrent date' ) if $date; @date = (Localtime)[0..2]; $date = join '-', @date; }

Your comments and experiences are welcomed.

 


In reply to Write "Dumber" Functions by rob_au

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.