Perl Module(s) Of The Week - 2019 Week 06 - SMS::ClickSend

This week Perl module, SMS::ClickSend was chosen because after reviewing the source code, I personally felt that this module embodies what I consider the Perl 5 way of simple coding style. Regardless Perl's notorious TMTOWTDI, as I observed, there exists a standard coding style which includes (1) Use minimum dependencies for speed and simplicity, (2) Prefer plain old Object-Oriented (OO) using blessed instead of Moose or Moo, (3) Snake case subroutine naming convention, (4) lack and little validation, and (5) Brevity without overly verbose. Even through the module was written in 2014 (5 years ago), I've seen new CPAN module that was written in such style even in 2019. There are some CPAN modules which were written in such over-engineered way that spans multiple modules. But that is a discussion for another day.

As usual, Installation is simple.
$ cpanm SMS::ClickSend

Sample usage of the API based on the synopsis.
use SMS::ClickSend;
 
my $sms = SMS::ClickSend->new(
    username => 'username',
    api_key  => 'API_KEY...',
);
 
my $res = $sms->send(
    to => '+61411111111',
    message => 'This is the message',
);
print Dumper(\$res); use Data::Dumper;

Let us look at the constructor. The constructor, `new` accept an array of values that needs to be converted to a hash. Hence, the number of items in the array should be even, hence the modulo by 2 to detect any odd number of items passed. Converting an array to a hash is quite straight forward, just `%hash = @array` should be sufficient;
sub new {
    my $class = shift;
    my %args = @_ % 2 ? %{$_[0]} : @_;

Check whether the required parameters exists without using the `exists`. Just use short-circuit evaluation through logical or operator. Read more on logical disjunction.
    $args{username} or croak 'username is required.';
    $args{api_key}  or croak 'api_key is required.';

Use default user agent if nothing was set or defined through the logical-or assignment.
    $args{ua} ||= LWP::UserAgent->new;

Lastly, just make sure or bless the hash arguments to be part of an object in the `SMS::ClickSend` package.
    return bless \%args, $class;
}

To fully understand how the constructor works, we need to show how the constructor was being called by the calling code.
# We are passing an array of four elements
my $sms = SMS::ClickSend->new(username => $username, api_key => $api_key);

# We are passing a hash and this can be obtained from first element from the argument, `$_[0]`.
my $sms = SMS::ClickSend->new({username => $username, api_key => $api_key});

# This will not work and `$args` will become an empty hash.
my $sms = SMS::ClickSend->new($username);

# This will work partially as `api_key` argument is missing and trigger the `croak`.
my $sms = SMS::ClickSend->new(username => $username);

Instead of catering for all possible inputs, perhaps we can just stick to one way of an array instead of hash to accept arguments to the constructor.
sub new {
    my ($class, %args) = @_;

    $args{username} or croak "username os required";
    $args{api_key} or croak "api_key is required";

    return bless \%args, $class;
}

Another interesting module found within the code. Basically, `var` is "Perl pragma to predeclare global variable names". Basically a global variable within the scope of the package. Superseded by `our` function which is a "lexical alias to a package (i.e. global) variable".
use vars qw/$errstr/;
 
sub errstr { $errstr }

No comments:

Post a Comment