Monday, November 30, 2009

The Lazy Moose - Finale!


When Laziness is a Virtue - Part 03 of 03

Target Audience: This series is pitched at developers interested in Object Oriented Design Patterns using the Moose framework in Perl.

My implementation consists of three class. Four, if you consider inheritance. The main class is EarnedValue - I call it main as this class exposes the application API. That's the main point.

The two other classes manage the work, divided along the lines of schedule and cost - handling and processing. The class for schedule is Schedule and cost is Cost. Schedule works off the Gantt chart whereas Cost works off the time-log. (Both of these are described in Part 02.)

So where would you expect to find the basic functionality for pulling data out of a spreadsheet? In Cost and Schedule, right?

My implementation actually deposits this functionality in EarnedValue - the main class. Why do I do that? Partly, to avoid duplication of code. I know that both Cost and Schedule require this functionality - so I put it in a third place, and give both these clients hooks into that functionality by passing a reference. So whenever data is to be pulled off a spreadsheet, the client object delegates the fetching operation to the main class.

If you've been following my other presentations in this series, you would think that I need to use Roles, no? Well, that's exactly what I have done here. I haven't used Roles in the purist, didactic sense, of course - which is why you don't see 'Moose::Role' anywhere. Remember, like much of everything else in the Object-oriented way of going about life, Roles are about the concept rather than a specific, narrowly-defined implementation.

The Japanese have a saying "Bolt what you can weld, tape what you can bolt, hold what you can tape." When you see a concept, free yourself from any particular implementation of it. That way, you can do much more. Even though it may not look like you are doing much at all.

So here's the output:

And the code the EarnedValue class that generates it - it's a bunch of code, an eyeful, and please follow it with the handy 10-step guide below :o)

[1.]
First the business, as usual. 'use Moose' and all that. Par for the course. The exception handling is based on object-oriented Exception::Class. Following best-practices (documented in this blog), the $SIG{__DIE__} event-handler is overloaded.

package EarnedValue;
use Moose;
use OLE;
use Win32::OLE::Const "Microsoft Excel";
use File::Spec;
use Moose::Util::TypeConstraints;
use Params::Coerce ();
use Data::Dumper;

use Exception::Class (
'EV::Exception::Base' => {
description => 'Base Exception Class',
},
'EV::Exception::Base::Logger' => {
isa => 'EV::Exception::Base',
description => 'Simply logging!',
},
'EV::Exception::Base::InvalidState' => {
isa => 'EV::Exception::Base',
fields => [ 'EV', 'PV', 'AC'],
description => 'Invalid state',
},
'EV::Exception::Base::MissingData' => {
isa => 'EV::Exception::Base',
fields => [ 'EV', 'PV', 'AC'],
description => 'Incomplete information',
},
);

local $SIG{__DIE__} = sub {
my $err = shift;
if ($err->isa('EV::Exception::Base')) {
die $err;
} elsif ($err->isa('Cost::Exception::Base')) {
die $err;
} elsif ($err->isa('Schedule::Exception::Base')) {
die $err;
} else {
EV::Exception::Base->throw($@);
}
print $@;
};

[2.]
Data - Sources of information: (a.) Spreadsheet_Schedule, (b.) Spreadsheet_Cost, and (c.) activeSpreadsheet.
The results are generated by scraping these two spreadsheets. Naturally, these need to be supplied by the user. Note that a constraint is set on the slot via subtype, to enforce that the user-supplied document exists on disk. If not, exception is thrown.

subtype 'extantFile'
=> as Str
=> where {
( -e $_ );
};

has 'activeSpreadsheet' => (
is => 'rw',
isa => 'extantFile',
predicate => 'has_activeSpreadsheet',
# trigger => \&timeStamped_copy
);

has 'Spreadsheet_Schedule' => (
is => 'rw',
isa => 'extantFile',
predicate => 'has_spreadsheetSchedule',
default => \&evGantt,
);

has 'Spreadsheet_Cost' => (
is => 'rw',
isa => 'extantFile',
predicate => 'has_spreadsheetCost',
default => \&evBasecamp,
);

[3.]
Data - Results-on-demand: EV, PV, AC, SPI, CPI
The meat! These slots hold the results of scraping spreadsheets and other skulldruggery. The mother-lode, if you will. Note that each has attribute 'lazy' set to '1', implementing lazy-loading. The 'default' attribute of each variable is set to a method that - this is how the chain of events is triggered when a value is demanded.

has 'EV' => (
is => 'rw',
isa => 'Num',
default => \&calculateEV,
lazy => 1,
);

has 'PV' => (
is => 'rw',
isa => 'Num',
default => \&calculatePV,
lazy => 1,
);

has 'AC' => (
is => 'rw',
isa => 'Num',
default => \&calculateAC,
lazy => 1,
);

has 'SPI' => (
is => 'rw',
isa => 'Num',
default => \&calculateSPI,
lazy => 1,
);

has 'CPI' => (
is => 'rw',
isa => 'Num',
default => \&calculateCPI,
lazy => 1,
);

[4.]
Objects - MySchedule, MyCost
These are slots for objects encapsulating the requisite functionality for handling and processing time and cost information. Information is parceled into neat intermediate components here for assembly in the final step by main (EarnedValue) class.

has 'MySchedule' => (
is => 'rw',
isa => 'Schedule',
);

has 'MyCost' => (
is => 'rw',
isa => 'Cost',
);

[5.]
Data - Diary
This is an interesting one. It goes with an associated method 'log_Me', which is the exception handler for the application. Any planned exceptions are handled here and a log of key events with time-date stamp is maintained. The slot is for the log-file that 'log_Me' utilizes.

has 'Diary' => (
is => 'rw',
isa => 'Str',
default => \&evLog,
predicate => 'has_Diary',
clearer => 'clear_Diary',
);

[6.]
Data - Other
Note the use of subtype to enforce a constraint. The specification of cell range is constrained by subtype that checks by a regular expression. The range of cells associated with an Excel spreadsheet query is stashed away here for use by querying methods.

subtype 'CellRange'
=> as Str
=> where {
( /^[a-zA-Z]{1,2}\d+$/ || /^[a-zA-Z]{1,2}\d+?:[a-zA-Z]{1,2}\d+$/);
};

has 'Range' => (
is => 'rw',
# isa => 'CellRange',
isa => 'Str',
predicate => 'has_Range',
clearer => 'clear_Range',
);

has 'multiplying_factor' => (
is => 'rw',
isa => 'Num',
default => 1000,
);

[7.]
Methods - calculateEV, calculatePV, calculateAC, calculateSPI, calculateCPI
The high-level methods recruit these middle-level methods. The structure set-up by these methods is critical. As mention in [3.], each method implements a 'default' attribute set upon a lazy variable. What does that mumbo-jumbo mean? Only that the method is fired automatically when the slot is accessed the first time.
Note the exception handling mechanism. The 'log_Me' method is invoked both for logging and handling any exception originating from the invocation of a high-level method.

sub calculateEV {
my $self = shift;
my $EV;
eval {
$EV = $self->MySchedule->tally_EVnumbers->[0] * $self->multiplying_factor;
};
my $e;
if ($e = Schedule::Exception::Base->caught) {
$self->log_Me($e);
} else {
$self->log_Me if $self->has_Diary;
}

return $EV;
};

sub calculatePV {
my $self = shift;
my $PV;
eval {
$PV = $self->MySchedule->tally_PVnumbers->[0] * $self->multiplying_factor;
};
my $e;
if ($e = Schedule::Exception::Base->caught) {
$self->log_Me($e);
} else {
$self->log_Me if $self->has_Diary;
}

return $PV;
};

sub calculateAC {
my $self = shift;
my $AC;

eval {
$AC = $self->MyCost->tally_ACnumbers;
};
my $e;
if ($e = Cost::Exception::Base->caught) {
$self->log_Me($e);
} else {
$self->log_Me if $self->has_Diary;
};

return $AC;
};

sub calculateSPI {
my $self = shift;
my ($netEV,$netPV);
my $SPI;
eval {
$netEV = $self->EV;
$netPV = $self->PV;
};
my $e;
if ( ($e = Cost::Exception::Base->caught)
|| ($e = Schedule::Exception::Base->caught)) {
$self->log_Me($e);
} else {
$self->log_Me if $self->has_Diary;
$SPI = $netEV/$netPV;
};

return $SPI;
};

sub calculateCPI {
my $self = shift;
my ($netEV,$netAC);
my $CPI;
eval {
$netEV = $self->EV;
$netAC = $self->AC;
};
my $e;
if ( ($e = Cost::Exception::Base->caught)
|| ($e = Schedule::Exception::Base->caught)) {
$self->log_Me($e);
} else {
$self->log_Me if $self->has_Diary;
$CPI = $netEV/$netAC;
};

return $CPI;
};

[8.]
Methods - printExecutiveSummary, printCostStructure
The high-level methods - for formatted reporting. The output generated is a report with a very simple structure. It is easy to see how this can be pumped up with all the bling from Google visualization API and other JavaScript/Ajay frameworks.
 
sub printExecutiveSummary {
my $self = shift;
printf("%10s %12s\n", 'ITEM', 'INR Value');
printf("%10s-%12s\n", '----------', '------------');
printf("%10s %12.2f\n", 'EV', $self->EV);
printf("%10s %12.2f\n", 'PV', $self->PV);
printf("%10s %12.2f\n", 'AC', $self->AC);
printf("%10s-%12s\n", '----------', '------------');
printf("%10s %12.2f\n", 'SPI', $self->SPI);
printf("%10s %12.2f\n", 'CPI', $self->CPI);
printf("%10s-%12s\n", '----------', '------------');
print "\n";
$self->log_Me if $self->has_Diary;
};

sub printCostStructure {
my $self = shift;
my $dashboard;
return unless $self->MyCost->can('ActivityCost');
$dashboard = $self->MyCost->ActivityCost;

printf(" %10s %12s\n", 'ACTIVITY', 'INR Value');
printf(" %10s-%12s\n", '----------', '------------');
my @theItems = sort(keys(%{$dashboard}));
foreach my $thisItem (@theItems) {
printf(" %-10s %12.2f\n", $thisItem, $dashboard->{$thisItem});
};
printf(" %10s-%12s\n", '----------', '------------');
return $dashboard;
}

[9.]
Methods - queryMe, _querySpreadsheet_singleCell, _querySpreadsheet_Range
The are querying methods that use Win32 automation (Win32::OLE) to work with Microsoft Excel data. The wrapper method 'queryMe' is invoked with the value stashed in 'Range' and returns the content as a data-structure (reference). It deploys the internal 'helper' functions (name beginning with an underscore) where the spreadsheet operations actually take place. The wrapper determines what is the appropriate functionality to use based on the arguments passed.
 
sub queryMe {
# method returns contents of a cell or the cells in a specified range as 2D array.
my $self = shift; my $sheet = shift;
return unless $self->has_Range;
$sheet = 1 unless $sheet;

my $myRange = $self->Range;
if ($myRange =~ /:/ ) {
$self->_querySpreadsheet_Range($myRange, $sheet);
} else {
$self->_querySpreadsheet_singleCell($myRange, $sheet);
};

};

sub _querySpreadsheet_singleCell {
# method returns contents of a single cell.
my $self = shift;
my $cell = shift;
my $sheet = shift;
$sheet = 1 unless $sheet;

my $excel = OLE->CreateObject("Excel.Application");
my $source = $self->activeSpreadsheet;

my $workbook = $excel->Workbooks->Open($source) || die "Unable to open!";
my $evSheet_namu = $workbook->Worksheets($sheet)->{Name};
my $evSheet = $workbook->Worksheets($evSheet_namu);

my $data = $evSheet->Range($cell); my $dataValue = $data->{Value};
# print '| ' . $evSheet_namu . ' | ' . $cell . ' | ' . $dataValue . ' |';
$workbook->Close;

return $dataValue;
};

sub _querySpreadsheet_Range {
# method returns contents of a range of cells (2D array).
my $self = shift;
my $range = shift;
my $sheet = shift;
$sheet = 1 unless $sheet;

my $excel = OLE->CreateObject("Excel.Application");
my $source = $self->activeSpreadsheet;

my $workbook = $excel->Workbooks->Open($source) || die "Unable to open ($source)!";
my $evSheet_namu = $workbook->Worksheets($sheet)->{Name};
my $evSheet = $workbook->Worksheets($evSheet_namu);

my $data = $evSheet->Range($range); my $dataValue = $data->{Value};
# print '| ' . $evSheet_namu . ' | ' . $range . ' |';
$workbook->Close;

return $dataValue;
};

[10.]
Methods - log_Me
This is an Exception Central - uses Exception::Class stack-trace functionality to record logs and (of course) to imprint the stack trace upon the logs when exceptions occur and the code breaks. Did you notice 'EV::Exception::Base::Logger' in Exception::Class? That's what this is about.
 
sub log_Me {
my $self = shift;
my $e = shift;
my $diary = $self->Diary;
my $eMsg = '';

open(INFO, ">>$diary");
unless ($e) {
print INFO &timeStamp, " OK ";
eval {
EV::Exception::Base::Logger->throw;
};
my $e;
if ($e = EV::Exception::Base::Logger->caught) {
my @lines = ();
foreach my $thisLine (split("\n", $e->trace)) {
push @lines, $thisLine if ($thisLine =~ 'EarnedValue::');
}
print INFO join(' | ', @lines);
} #fi
} elsif ($e->isa('Cost::Exception::Base')) {
$eMsg = Cost::Exception::Base->description . " -> ";
$eMsg .= Cost::Exception::Base::MissingData->description
if $e->isa('Cost::Exception::Base::MissingData');
print INFO &timeStamp, " ERROR ";
print INFO $e->error;
print INFO $e->trace;
print INFO $eMsg;
} elsif ($e->isa('Schedule::Exception::Base')) {
$eMsg = Schedule::Exception::Base->description . " ";
$eMsg .= Schedule::Exception::Base::InvalidState->description
if $e->isa('Schedule::Exception::Base::InvalidState');
print INFO &timeStamp, " ERROR ";
print INFO $e->error;
print INFO $e->trace;
print INFO $eMsg;
}
close INFO;
}


So how did laziness become a virtue in these 10 simple steps? The complete code is provided below, and may also be downloaded from the site. We have seen how all computation is triggered by access - Just In Time (JIT). No computational resources are wasted loading data that is not required. No inventory is maintained, unless required. Let's reinforce this with a scenario:

1. A request for SPI (EarnedValue::SPI)..
2. triggers a JIT request for EV, PV (EarnedValue::EV, EarnedValue::PV) ..
3. setting off Schedule accessors: Schedule::EVnumbers, Schedule::PVnumbers
4. that consume Roles defined in the main EarnedValue class: EarnedValue::queryMe
5. to pull data off spreadsheet into Object slots:
Schedule::EVnumbers, Schedule::PVnumbers
6. for processing into interim results via Schedule methods:
Schedule::tally_EVnumbers, Schedule::tally_PVnumbers
7. which are then stuffed into slots in the main EarnedValue class:
EarnedValue::EV, EarnedValue::PV
8. thus stuffing the slot EarnedValue::SPI
9. and producing the desired result.

The complete class-def for EarnedValue is reproduced below. For Schedule and Cost implementation, please refer the code posted on the Google site (link at the end of page).

Here is what the complete EarnedValue module looks like:

package EarnedValue;
use Moose;
use OLE;
use Win32::OLE::Const "Microsoft Excel";
use File::Spec;
use Moose::Util::TypeConstraints;
use Params::Coerce ();
use Data::Dumper;

use Exception::Class (
'EV::Exception::Base' => {
description => 'Base Exception Class',
},
'EV::Exception::Base::Logger' => {
isa => 'EV::Exception::Base',
description => 'Simply logging!',
},
'EV::Exception::Base::InvalidState' => {
isa => 'EV::Exception::Base',
fields => [ 'EV', 'PV', 'AC'],
description => 'Invalid state',
},
'EV::Exception::Base::MissingData' => {
isa => 'EV::Exception::Base',
fields => [ 'EV', 'PV', 'AC'],
description => 'Incomplete information',
},
);

local $SIG{__DIE__} = sub {
my $err = shift;
if ($err->isa('EV::Exception::Base')) {
die $err;
} elsif ($err->isa('Cost::Exception::Base')) {
die $err;
} elsif ($err->isa('Schedule::Exception::Base')) {
die $err;
} else {
EV::Exception::Base->throw($@);
}
print $@;
};

subtype 'extantFile'
=> as Str
=> where {
( -e $_ );
};

has 'activeSpreadsheet' => (
is => 'rw',
isa => 'extantFile',
predicate => 'has_activeSpreadsheet',
# trigger => \&timeStamped_copy
);

has 'Spreadsheet_Schedule' => (
is => 'rw',
isa => 'extantFile',
predicate => 'has_spreadsheetSchedule',
default => \&evGantt,
);

has 'Spreadsheet_Cost' => (
is => 'rw',
isa => 'extantFile',
predicate => 'has_spreadsheetCost',
default => \&evBasecamp,
);

has 'Diary' => (
is => 'rw',
isa => 'Str',
default => \&evLog,
predicate => 'has_Diary',
clearer => 'clear_Diary',
);

has 'EV' => (
is => 'rw',
isa => 'Num',
default => \&calculateEV,
lazy => 1,
);

has 'PV' => (
is => 'rw',
isa => 'Num',
default => \&calculatePV,
lazy => 1,
);

has 'AC' => (
is => 'rw',
isa => 'Num',
default => \&calculateAC,
lazy => 1,
);

has 'SPI' => (
is => 'rw',
isa => 'Num',
default => \&calculateSPI,
lazy => 1,
);

has 'CPI' => (
is => 'rw',
isa => 'Num',
default => \&calculateCPI,
lazy => 1,
);

has 'MySchedule' => (
is => 'rw',
isa => 'Schedule',
);

has 'MyCost' => (
is => 'rw',
isa => 'Cost',
);

has 'multiplying_factor' => (
is => 'rw',
isa => 'Num',
default => 1000,
);

subtype 'CellRange'
=> as Str
=> where {
( /^[a-zA-Z]{1,2}\d+$/ || /^[a-zA-Z]{1,2}\d+?:[a-zA-Z]{1,2}\d+$/);
};

has 'Range' => (
is => 'rw',
# isa => 'CellRange',
isa => 'Str',
predicate => 'has_Range',
clearer => 'clear_Range',
);

sub calculateEV {
my $self = shift;
my $EV;
eval {
$EV = $self->MySchedule->tally_EVnumbers->[0] * $self->multiplying_factor;
};
my $e;
if ($e = Schedule::Exception::Base->caught) {
$self->log_Me($e);
} else {
$self->log_Me if $self->has_Diary;
}

return $EV;
};

sub calculatePV {
my $self = shift;
my $PV;
eval {
$PV = $self->MySchedule->tally_PVnumbers->[0] * $self->multiplying_factor;
};
my $e;
if ($e = Schedule::Exception::Base->caught) {
$self->log_Me($e);
} else {
$self->log_Me if $self->has_Diary;
}

return $PV;
};

sub calculateAC {
my $self = shift;
my $AC;

eval {
$AC = $self->MyCost->tally_ACnumbers;
};
my $e;
if ($e = Cost::Exception::Base->caught) {
$self->log_Me($e);
} else {
$self->log_Me if $self->has_Diary;
};

return $AC;
};

sub calculateSPI {
my $self = shift;
my ($netEV,$netPV);
my $SPI;
eval {
$netEV = $self->EV;
$netPV = $self->PV;
};
my $e;
if ( ($e = Cost::Exception::Base->caught)
|| ($e = Schedule::Exception::Base->caught)) {
$self->log_Me($e);
} else {
$self->log_Me if $self->has_Diary;
$SPI = $netEV/$netPV;
};

return $SPI;
};

sub calculateCPI {
my $self = shift;
my ($netEV,$netAC);
my $CPI;
eval {
$netEV = $self->EV;
$netAC = $self->AC;
};
my $e;
if (($e = Cost::Exception::Base->caught)
|| ($e = Schedule::Exception::Base->caught)) {
$self->log_Me($e);
} else {
$self->log_Me if $self->has_Diary;
$CPI = $netEV/$netAC;
};

return $CPI;
};

sub printExecutiveSummary {
my $self = shift;
printf("%10s %12s\n", 'ITEM', 'INR Value');
printf("%10s-%12s\n", '----------', '------------');
printf("%10s %12.2f\n", 'EV', $self->EV);
printf("%10s %12.2f\n", 'PV', $self->PV);
printf("%10s %12.2f\n", 'AC', $self->AC);
printf("%10s-%12s\n", '----------', '------------');
printf("%10s %12.2f\n", 'SPI', $self->SPI);
printf("%10s %12.2f\n", 'CPI', $self->CPI);
printf("%10s-%12s\n", '----------', '------------');
print "\n";
$self->log_Me if $self->has_Diary;
};

sub printCostStructure {
my $self = shift;
my $dashboard;
return unless $self->MyCost->can('ActivityCost');
$dashboard = $self->MyCost->ActivityCost;

printf(" %10s %12s\n", 'ACTIVITY', 'INR Value');
printf(" %10s-%12s\n", '----------', '------------');
my @theItems = sort(keys(%{$dashboard}));
foreach my $thisItem (@theItems) {
printf(" %-10s %12.2f\n", $thisItem, $dashboard->{$thisItem});
};
printf(" %10s-%12s\n", '----------', '------------');
return $dashboard;
}

sub evGantt {
my $folder = File::Spec->curdir();
my $file = q{Dashboard.xls};
return File::Spec->rel2abs(File::Spec->catfile($folder, $file));
};

sub evBasecamp {
my $folder = File::Spec->curdir();
my $file = q{time-export.csv};
return File::Spec->rel2abs(File::Spec->catfile($folder, $file));
}

sub evLog {
my $folder = File::Spec->curdir();
my $file = q{main.log};
return File::Spec->rel2abs(File::Spec->catfile($folder, $file));
};

sub timeStamped_copy {
# for safety, make a time-stamped copy before the spreadsheet is accessed.
my $self = shift;
};

sub queryMe {
# method returns contents of a cell or the cells in a specified range as 2D array.
my $self = shift; my $sheet = shift;
return unless $self->has_Range;
$sheet = 1 unless $sheet;


my $myRange = $self->Range;
if ($myRange =~ /:/ ) {
$self->_querySpreadsheet_Range($myRange, $sheet);
} else {
$self->_querySpreadsheet_singleCell($myRange, $sheet);
};

};

sub _querySpreadsheet_singleCell {
# method returns contents of a single cell.
my $self = shift;
my $cell = shift;
my $sheet = shift;
$sheet = 1 unless $sheet;

my $excel = OLE->CreateObject("Excel.Application");
my $source = $self->activeSpreadsheet;

my $workbook = $excel->Workbooks->Open($source) || die "Unable to open!";
my $evSheet_namu = $workbook->Worksheets($sheet)->{Name};
my $evSheet = $workbook->Worksheets($evSheet_namu);

my $data = $evSheet->Range($cell); my $dataValue = $data->{Value};
# print '| ' . $evSheet_namu . ' | ' . $cell . ' | ' . $dataValue . ' |';
$workbook->Close;

return $dataValue;
};

sub _querySpreadsheet_Range {
# method returns contents of a range of cells (2D array).
my $self = shift;
my $range = shift;
my $sheet = shift;
$sheet = 1 unless $sheet;

my $excel = OLE->CreateObject("Excel.Application");
my $source = $self->activeSpreadsheet;

my $workbook = $excel->Workbooks->Open($source) || die "Unable to open ($source)!";
my $evSheet_namu = $workbook->Worksheets($sheet)->{Name};
my $evSheet = $workbook->Worksheets($evSheet_namu);

my $data = $evSheet->Range($range); my $dataValue = $data->{Value};
# print '| ' . $evSheet_namu . ' | ' . $range . ' |';
$workbook->Close;

return $dataValue;
};

sub log_Me {
my $self = shift;
my $e = shift;
my $diary = $self->Diary;
my $eMsg = '';

open(INFO, ">>$diary");
unless ($e) {
print INFO &timeStamp, " OK ";
eval {
EV::Exception::Base::Logger->throw;
};
my $e;
if ($e = EV::Exception::Base::Logger->caught) {
my @lines = ();
foreach my $thisLine (split("\n", $e->trace)) {
push @lines, $thisLine if ($thisLine =~ 'EarnedValue::');
}
print INFO join(' | ', @lines);
} #fi
} elsif ($e->isa('Cost::Exception::Base')) {
$eMsg = Cost::Exception::Base->description . " -> ";
$eMsg .= Cost::Exception::Base::MissingData->description
if $e->isa('Cost::Exception::Base::MissingData');
print INFO &timeStamp, " ERROR ";
print INFO $e->error;
print INFO $e->trace;
print INFO $eMsg;
} elsif ($e->isa('Schedule::Exception::Base')) {
$eMsg = Schedule::Exception::Base->description . " ";
$eMsg .= Schedule::Exception::Base::InvalidState->description
if $e->isa('Schedule::Exception::Base::InvalidState');
print INFO &timeStamp, " ERROR ";
print INFO $e->error;
print INFO $e->trace;
print INFO $eMsg;
}
close INFO;
}

sub timeStamp {
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst);
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
my $tstamp = sprintf
"\[%02d\-%02d\-%4d : %02d\-%02d\-%02d\]",
mon+1,$mday,$year+1900,$hour,$min,$sec;
return $tstamp;
}

All code in this series may be downloaded from:
http://sites.google.com/site/sanjaybhatikar/codeunquote/designpatterns-1

The Lazy Moose - Part 02 of 03

When Laziness is a Virtue - Part 02 of 03

Target Audience: This series is pitched at developers interested in Object Oriented Design Patterns using the Moose framework in Perl.

For Earned Value Analysis, my data resides in two spreadsheets. The first one is 'Dashboard.xls' - an important-looking spreadsheet with a bevy of beautiful numbers housed in multicolored cells and even the solid gray bars have a blue overlay .. in short, everything calculated to impress the bosses. It is variously known as Gantt Chart or Bar Chart and is basically a schedule with workdays along the X-axis and project activities organized into packages along the Y-axis. So the gray bars tell about the time-lines for each activity under each work package and the blue overlay tells how much (%-age wise) has been accomplished out of the total in the gray. That piece of information (%-age complete) goes in the red column (H) and the spreadsheet automatically updates itself, blue bars and all - savvy?

(Making such a spreadsheet is an interesting story in itself involving utilization of the full date-time capabilities of MS-Excel and a neat little trick called Conditional Formatting - which has been pushed to the envelope. But that's another story for another day.)


That's all very well for time, (she says, slipping into a diaphanous negligee,) but where is the information upon costs? Sharp! There's one more spreadsheet that has those numbers, and for faint of heart it ain't.



Actually, all it is is my operators and how they have charged time to the project, on the basis of which I estimate costs. Samuel Jackson, for example, has been working his butt off whereas Morgan Freeman has been idly sitting on his.

If you're keeping up with me so far, super! On the other hand if not, don't let it bother you. Seppukku is an acceptable option. (Unless your designation says "Project Manager", in which case you ought to be ashamed!)

All you need to know is we're goin to be scraping numbers off these spreadsheets to generate other numbers that are interesting, insightful and irresistible.

Onward, into the code!

All code in this series may be downloaded from:
http://sites.google.com/site/sanjaybhatikar/codeunquote/designpatterns-1

The Lazy Moose - Part 01 of 03

When Laziness is a Virtue - Part 01 of 03

Target Audience: This series is pitched at developers interested in Object Oriented Design Patterns using the Moose framework in Perl.

There are times when laziness is a virtue. There are places where when hubris is laudable. The time has come and let me show you the place.

Remember attributes? This whole piece centers around two attributes - lazy and default. Specifically, lazy-loading - which is when data magically appears when requested, and not until then. The default attribute supplies the magic wand that produces data.

Why is this useful? Suppose one has a chain of events arranged whereby a few high-level events recruit many middle-level events which in turn recruit myriad low-level events in order to achieve a high-level objective. Sort of like feudal Japan where the peasantry bowed to Samurai (Warrior Class) and Samurai bowed to Daimyo (Knights) and Daimyo to bigger Daimyo (Lords) who all bowed to the Shogun (Dictator) - who sometimes put the dick in dictator but more often than not, was a highly skilled leader and administrator. Can you think of such a hierarchy in the computational world, where low-level functions harvest information from databases or web-services and supply them on-request to pre-processors which in turn pass up clean, formatted data to persnickety middle-level processing functions that successively distill value until something interesting and useful comes out at the very top?

Ordinarily, such an application is designed as a 'push' system where data is pushed from one level to the next. Since the system has no way of knowing what will be requested next, it can only push information upwards until pre-fabricated goods sit on the shelves waiting to be picked off - whether required immediately or not. An "all or nothing" approach.

That is not an enlightened way to go about it. Would it not be better if components could be fabricated on demand - only when required? A 'pull' system where, once fabricated, a component remains available for the next request. What's not available is filled-in only when a request comes in.

Come to think of it, this is not unlike a "Just In Time" system for computer applications. Watch, how laziness becomes virtue.

The example I have chosen is a pragmatic one of Earned Value Analysis - a technique deployed by professional project managers for Monitoring and Control. It consists of three entities:
EV - Earned Value, representing how much value is earned from effort expended to-date.
PV - Planned Value, representing how much value the project planners thought would be earned to-date.
AC - Actual Costs, representing how much money has actually been spent to-date to generate the EV.

This helps monitor the project in terms of -
- Schedule Performance Index (SPI) - how we doin on time (baby)?
- Cost Performance Index (CPI) - how we doin on cost (dude)?

And the rest of this fascinating story of time, costs, sexual escapades, intrigue and as many as three of the 7 deadly sins unfolds in Part 2.


All code in this series may be downloaded from:
http://sites.google.com/site/sanjaybhatikar/codeunquote/designpatterns-1

Thursday, November 12, 2009

Observe this!

Ch. 2 from HFDP - Part 03 of 03

Target Audience: This series is pitched at developers interested in Object Oriented Design Patterns using the Moose framework in Perl. I cover the examples from the Head First Design Patterns book, replicating Java implementation in Moose. You need to obtain a copy of the book, which is not hard to come by.

Don't mess with the Moose! (Notes so you don't.)

An object, as the old saying goes, has data and methods. Data are stuffed in various slots and, to make a long story short, Moose provides 'attributes' to qualify a slot. Qualify - how? Well, for starters, what if you want a 'read-only' slot? That is achieved by setting the 'is' attribute to 'ro' - thus ensuring that Moose generates a getter (or accessor) for the method and omits the setter (or mutator).

Attributes are one cool feature of the Moose. They are the muscle and sinew. And the case-studies below illustrate some of the power.

Case of the Trigger-Happy Moose

The 'trigger' is a subroutine reference set upon a slot, so that the subroutine is invoked whenever the slot is set. This can happen both during object construction or later by passing a new object to the attribute's accessor method. However, it is not called when a value is provided via a 'default' or 'builder'.

The Moose Defaults

You do not need a constructor for a Moose class. Instead, use the 'default' attibute set upon each slot. The 'default' attribute holds a subroutine reference, the return of which is stuffed into the slot.
For self-reference in 'default', use $_[0] in the sub. When the sub is executed, it is invoked as a method on the object.
And therein lies the rub! Remember, remember (the 5th of November) .. it is the returned object or value that is stuffed into the slot. Be sure that what the sub returns is indeed what you want stuffed in the slot! There's many a slip twixt cup and lip (or slot and sub) .. many a Moose has been waylaid trying to set the slot explicitly in the definition of the default sub. The object is, after all, a hashref and the slots merely hash-keys. That is not how 'default' is used. Just have the sub return what you need in the slot and you will come to no grief.

The Lazy Moose

The lazy and default options options are linked. In fact, you cannot have a lazy attribute unless it has a default (or a builder, but we'll cover that later). If you try to make an attribute lazy without a default, class creation will fail with an exception.
What lazy means is that the slot is stuffed by the 'default' only upon request via accessor and not until then. This feature is so powerful and ingenious - certain applications may simply be impossible without it. Take for example a classical data structure in computer science - the binary tree. Without lazy loading, it leads to an implementation that consumes all of the computer's available memory. Now you wouldn't want that to happen to you, would you?

http://search.cpan.org/~drolsky/Moose-0.88/lib/Moose/Cookbook/Basics/Recipe3.pod

To Cook a Moose


(With apologies to a certain gun-toting Governor of Alaska.)
The 'BUILD' method is called after an object is created.
There are several ways to use a BUILD method. One of the most common is to check that the object state is valid. While we can validate individual attributes through the use of types, we can't validate the state of a whole object that way.

Why did the Moose weaken her reference?

Attribute 'weak_ref' assigned 1 ensures that the reference is weakened when it is set. So this reference will be ignored by Garbage Cleaning when handling the referred object. A weak reference will not prevent the referred object from being cleaned by garbage collector.

The Moose Modifies Her Methods


Method Modifiers are a Moose feature that allows hooking into code. One can alter class behavior by hooking into code before, after and even around. Basically, that means using the qualifiers 'before', 'after' and 'around' respectively.
Basically, a snippet of code encapsulated in a sub is executed before the modified method. (Or after, or around.)
Invoking the method that a method modifier hooks into in the definition of the method modifier leads to deep recursion.
That may sound obvious until one starts hooking into accessor/mutator methods to impose constraints, for example. This is a common occurrence when a slot is a container - such as an array (array-ref) or a hash (hash-ref). Then, usage of a method modifier to constrain the size of the container (for example) leads to disaster. Because to constrain the size of the container, you will need to access the slot .. get it?

The following DOs and DON'Ts for the methods 'before', 'after' should help one stay out of trouble -
DO
use Method Modification to add behavior to methods that Moose generates, such as accessor/mutator methods.
DON'T
however attempt to pre-process the arguments passed to the method thus modified. That will have no effect - changes to the argument list made in the method modifier are discarded when the said modifier exits. Speaking of which, return values are simply ignored.
DO
use method modification to execute logical checks that don't make sense as type constraints.
DON'T
however abuse this notion by attempting to rectify the input arguments. The correct action when checks fail is to raise an exception. In other words, die. Die! Or in the immortal words of the dying Creedy in "V for Vendetta", "Why won't you die?!" (To which, the masked character called "V" replies "Beneath this mask, there is no flesh, Mr. Creedy. Beneath this mask, is an Idea. And Ideas are bulletproof.")

Roundabout Moose

And just when you though method modification makes sense ..

.. Moose cruelly exposes your naivete!

The method modifier 'around', despite appearances, is fundamentally different from 'before' and 'after' - with 'around', you can modify the arguments being passed to the original method. You can even call the orginal method - as a matter of fact, you are required to. Unless you don't want to, that is. In which case, you need not call the original method at all.

Last, but not the least, you can modify the return value with 'around'. That is, if you want to. Wakarimasu ka?

As my martial arts instructor says, "Try it! You'll know." And that's enough for one day.


All code in this series may be downloaded from:
http://sites.google.com/site/sanjaybhatikar/codeunquote/designpatterns-1

Monday, November 9, 2009

Observe this! (Cont'd)

Ch. 2 from HFDP - Part 02 of 03

Target Audience: This series is pitched at developers interested in Object Oriented Design Patterns using the Moose framework in Perl. I cover the examples from the Head First Design Patterns book, replicating Java implementation in Moose. You need to obtain a copy of the book, which is not hard to come by.

When I was at the University of Colorado, I spent a chunk of my life driving a trusty Toyota truck in the Rockies. In the winter, it was not unusual to encounter a snow-storm that dumped enough snow to block the mountain passes. In those climes during those climbs, one would benefit from tuning into an AM radio channel that broadcast information upon the weather and road conditions.

So, how about a display that plugs-in the Weather Station to show current Temperature, Pressure and Humidity? That's just what 'currentConditionsDisplay' does.


package currentConditionsDisplay;
use Moose;

extends 'Observer', 'DisplayElement';

has 'temperature' => (
is => 'rw',
isa => 'Value',
);

has 'humidity' => (
is => 'rw',
isa => 'Num',
);

has 'weatherData' => (
is => 'rw',
isa => 'WeatherData',
trigger => \®isterMe,
predicate => 'has_Subject',
clearer => 'clear_Subject',
);

sub registerMe {
my ($self, $weatherData) = @_;
$weatherData->_registerObserver($self) if $self->has_Subject;
};

after 'update' => sub {
my $self = shift;
my ($temperature, $pressure, $humidity) = @_;
$self->temperature($temperature);
$self->humidity($humidity);
$self->display;
};

after 'display' => sub {
my $self = shift;
print ">> NOW conditions >>";
printf " TEM <%10.2f>\n HUM <%10.2f>\n", $self->temperature, $self->humidity;
print "<< ----- ROGEROUT <<";
};


See how the 'Observer' and 'DisplayElement' roles are composed into this display? There can be any number of plug-in classes developed for the Weather Station API. This allows the 'Observer' role to be mixed-in a plug-in class, leaving the developers of that class free to pimp their ride.

Notice that the Observer holds a copy of (i.e. reference to) the Subject. The 'predicate' method 'has_Subject' checks that such a relationship exists. The 'clearer' method 'clear_Subject' severs it.

What about the 'trigger'? When the 'weatherData' slot is set, the trigger ensures that the display is registered with Weather Station as an observer by invoking the Weather Station's '_registerObserver' method. What is the significance of the underscore in '_registerObserver'? That indicates this is a private method, not exposed for public consumption.

Let's roll this out now.

First, a Weather Station as an object of 'WeatherData' class:

my $weatherData = WeatherData->new;

Add an observer:

my $myDisplay = currentConditionsDisplay->new(weatherData => $weatherData);

And Lights, Camera, Action!

$weatherData->setMeasurements(107, 64, 27.5);

Et voila! Gentlemen, we got ourselves a Weather Station!

Now how about one that does things a little differently? Shows the average of the last five readings, perhaps? Here we go - Gentlemen, Ladies and Larry - I give you: 'averageConditionsDisplay'.


package averageConditionsDisplay;
use Moose;

extends 'Observer', 'DisplayElement';

has 'temperature' => (
is => 'rw',
isa => 'ArrayRef[Value]',
default => sub { [] },
);

has 'pressure' => (
is => 'rw',
isa => 'ArrayRef[Num]',
default => sub { [] },
);

has 'humidity' => (
is => 'rw',
isa => 'ArrayRef[Num]',
default => sub { [] },
);

has 'weatherData' => (
is => 'rw',
isa => 'WeatherData',
trigger => \®isterMe,
predicate => 'has_Subject',
clearer => 'clear_Subject',
);

sub registerMe {
my ($self, $weatherData) = @_;
$weatherData->_registerObserver($self) if $self->has_Subject;
};

before 'update' => sub {
my $self = shift;
shift(@{$self->temperature}) if (scalar(@{$self->temperature}) == 5);
shift(@{$self->pressure}) if (scalar(@{$self->pressure}) == 5);
shift(@{$self->humidity}) if (scalar(@{$self->humidity}) == 5);
};

after 'update' => sub {
my $self = shift;
my ($temperature, $pressure, $humidity) = @_;
push @{$self->temperature} , $temperature;
push @{$self->humidity} , $humidity;
push @{$self->pressure} , $pressure;
$self->display;
};

after 'display' => sub {
my $self = shift;
my $tallies = $self->total_me;
print ">> MEAN conditions >>";
printf " TEM <%10.2f>\n PRE <%10.2f>\n HUM <%10.2f>\n",
$tallies->{temperature}/5,
$tallies->{pressure}/5,
$tallies->{humidity}/5;
print "<< ------ ROGEROUT <<";
};

sub total_me {
my $self = shift;
my %netValues = ();
my $index = 0;
foreach my $thisTemperature (@{$self->temperature}) {
$netValues{'temperature'} += $self->temperature->[$index];
$netValues{'pressure'} += $self->pressure->[$index];
$netValues{'humidity'} += $self->humidity->[$index];
$index++;
};
return \%netValues;
}

What does this do differently? Let's see..

Firstly, temperature, pressure, humidity are stored in containers - arrays. That's nice because it allows averaging over a moving window. How is this moving window achieved? Enter Method Modifiers - a Moose special! If you ask a passing Moose, he (or she) will tell you that a Method Modifier is a way of hooking into methods. On prodding further, the Moose may reveal that Method Modification is closely aligned with inheritance and enables behavior-modification so that a child class can develop specialized behavior to focus on a problem-solving task.

In the instance at hand, for example, the 'update' behavior is altered with 'before' and 'after' modifiers. There is nothing special about 'after' which, after all, only implements a definition left out in the abstract 'Observer' parent class. The usage of 'before' is interesting though, because this is where the size of the 'window' is controlled. Take a look and convince yourself.

Could we not simple have achieved this with Method Modifiers on the get/set methods of 'temperature', 'pressure' and 'humidity' slots? (These are 'temperature', 'pressure' and 'humidity' respectively.) One could define a 'before' method modifier upon each of these and check the size of the array, resetting it using 'shift' on the 'size equals 5' condition. Right?

Right?

Wrong!

Remember that Method Modifiers - 'before', 'after' - are called whenever the method is called. So if you call the method in its modifier, you end up with deep recursion. That makes nobody happy and the God-Father mad! Just kidding about the God-Father.

If this seems obvious - good! If not, work through it. This is important. The last part of this monograph in 3 parts upon the Observer pattern notes some handy Moose-isms, lest the novice Moose enthusiast be struck down with Moose-itis.



All code in this series may be downloaded from:
http://sites.google.com/site/sanjaybhatikar/codeunquote/designpatterns-1

Friday, October 23, 2009

Observe this!

Ch. 2 from HFDP - Part 01 of 03

Target Audience: This series is pitched at developers interested in Object Oriented Design Patterns using the Moose framework in Perl. I cover the examples from the Head First Design Patterns book, replicating Java implementation in Moose. You need to obtain a copy of the book, which is not hard to come by.


When I was a kid, my dad would tell me that what keen observation powers are what makes a person excel in analysis. That is borne out by Arthur Conan Doyle's prodigious creation, Sherlock Holmes.

The Observer pattern thus starts with much going for it!

It is one of my favorite patterns. Chiefly because dynamic interplay of objects that send and receive messages is a very powerful paradigm for making things happen. And the Observer pattern achieves just that!

The folks at HFDP present this as a one-many relationship between a 'Subject' that upon changing state sends notification to 'Observers' that have subscribed to listen-in. Think of a many-many relationship. It is just a collection of one-many relationships. Now think of an Observer that also implements the Subject interface. (We'll come to interfaces in a minute. Just pretend it means an Observer can behave like a Subject.) Now you have Object-Oriented Utopia. Or at least, a democracy where empowered objects send, receive and cascade messages to each other, subscribing or unsubscribing at will.

At HFDP, the story starts with a Weather Station API. The Weather Station captures 3 variables: temperature, pressure and humidity. Any time the measurements change, various Display Classes that plug-in to the Weather Station API are notified so as to render the latest information on the weather. The business model is the Weather Station company charges for Display Elements that plug-in to their API.

(Sounds familiar? Think of the Facebook API.)

For the rubber hitting road, this means the Observer pattern is in business!

A draft Weather Station can be sketched as follows:

package WeatherData;
use Moose;

has 'temperature' => (
is => 'rw',
isa => 'Value',
);

has 'humidity' => (
is => 'rw',
isa => 'Num',
);

has 'pressure' => (
is => 'rw',
isa => 'Num',
);

sub measurementsChanged {
# plug-in API
}

This bit is self-explanatory.

The principle underlying the Observer pattern is that the Subject holds copies of (references to) registered Observers. The Subject's responsibility is to provide methods for registration and un-registration. The Observer's responsibility is to make available an 'update' method that the Subject can invoke on all registered Observers. Simple?

Here then, is the abstract Subject:

package Subject;
use Moose;

sub _registerObserver {};
sub removeObserver {};
sub notifyObservers {};

and the prototypical (i.e. abstract) Observer

package Observer;
use Moose;

sub update {};

Think of these prototypes as 'roles' - little packets of functionality which allow re-use of code. Classes can be composed with them - or in Moose parlance, Classes consume roles. Do you see how this differs from conventional inheritance? The leitmotif is flexibility in terms of code re-use, regardless of the specifics of implementation. As you shall see, I do indeed use multiple inheritance to achieve composition.

That is because Perl (and Moose) support multiple inheritance. Java doesn't, and there composition with roles (the Java term is 'interfaces') needs to follow a stricter syntactic demarcation from inheritance.

The last prototype (or role, or interface, or abstract class) is:

package DisplayElement;
use Moose;

sub display {};

You got to love how easy that was!

Let's compose the Subject role into the Weather Station. Note the use of the Method Modifier 'after' to hook into the methods of the abstract implementation.

package WeatherData;
use Moose;

extends 'Subject';

has 'observers' => (
is => 'ro',
isa => 'ArrayRef[Observer]',
default => sub {[]},
predicate => 'has_observers',
);

has 'temperature' => (
is => 'rw',
isa => 'Value',
);

has 'humidity' => (
is => 'rw',
isa => 'Num',
);

has 'pressure' => (
is => 'rw',
isa => 'Num',
);

after '_registerObserver' => sub {
my $self = shift;
my $thisObserver = shift;
push @{ $self->observers }, $thisObserver;
print "Now has: ", scalar @{ $self->observers }, " observers.";
};

after 'removeObserver' => sub {
my $self = shift;
my $deletionIndex = shift;
my $cutObserver = splice @{ $self->observers }, $deletionIndex, 1;
$cutObserver->clear_Subject;
print "Now has: ", scalar @{ $self->observers }, " observers.";
};

after 'notifyObservers' => sub {
my $self = shift;
foreach my $thisObserver (@{ $self->observers }) {
$thisObserver->update($self->temperature,
$self->pressure,
$self->humidity);
}
};

sub measurementsChanged {
my $self = shift;
$self->notifyObservers;
}

sub setMeasurements {
my $self = shift;
my ($temperature, $pressure, $humidity) = @_;
$self->temperature($temperature);
$self->pressure($pressure);
$self->humidity($humidity);
$self->measurementsChanged;
}

What have we achieved? We have composed the 'Subject' role into the'WeatherData' class and added a slot that lends this class a container for subscribers. Note how the notification is applied by iterating over contents of 'observers'. Note also that notification is initiated by the method 'setMeasurements' of the Weather Station, the chain of command being: 'setMeasurments' to 'measurementsChanges' to 'notifyObservers'. Now it remains to define the display. And that's coming up in Part 2.
~ * ~

All code in this series may be downloaded from:
http://sites.google.com/site/sanjaybhatikar/codeunquote/designpatterns-1

Wednesday, October 21, 2009

The State of Moose.

Ch. 10 from HFDP

Target Audience: This series is pitched at developers interested in Object Oriented Design Patterns using the Moose framework in Perl. I cover the examples from the Head First Design Patterns book, replicating Java implementation in Moose. You need to obtain a copy of the book, which is not hard to come by.


Target Audience: This series is pitched at developers interested in Object Oriented Design Patterns using the Moose framework in Perl. I cover the examples from the Head First Design Patterns book, replicating Java implementation in Moose. You need to obtain a copy of the book, which is not hard to come by.

I like to talk of State Machines. Because they are so natural. I like to think about interesting elements the world about me in terms of State Machines. Take girlfriend or spouse, for instance, their behavior depends so much on their state..

Jokes apart, what I've hinted at is the essence of a State Machine. Behavior that is regulated by State. Or stated in Object-Oriented parlance, the implementation of a method varies according to the state of the object.

Obviously, that leaves us but one choice for dealing with these Jekyl-Hydesque objects - to encapsulate behavior in 'State' classes. And that's all about to make sense.

The brains at Head First cite the example of Gumball Machine which has various methods like 'insert quarter', 'turn crank', 'dispense gumball', etc., which all depend on the state of the machine, i.e. if the machine has a quarter in the slot then turning the crank delivers a gumball. To illustrate this, the folks at HFDP show a state diagram. The states are circles and the arrows are actions (methods) that typically produce a change of state. Neato!

(Now if I could do this with the women in my life... sigh!)

The implementation consists of encapsulating behavior in an abstract class 'State' and providing method definitions in concrete classes corresponding to each of various possible States. For example, 'turning crank' when the machine state is 'has quarter' leads to dispensation of a gumball but when there is 'no quarter' or the machine is 'sold out' doesn't produce the same result.

Here then is the State class:

package State;
use Moose;
has 'gumballMachine' => (
is => 'rw',
isa => 'GumballMachine',
predicate => 'has_gumballMachine',
);

sub insertQuarter {};
sub ejectQuarter {};
sub turnCrank {};
sub dispense {};

When the machine has a quarter, the state is 'HasQuarterState'.

package HasQuarterState;
use Moose;
use GumballMachine;

extends 'State';

sub insertQuarter {
print qq{You cannot insert a quarter now.};
};

sub ejectQuarter {
my $self = shift;
print qq{Here's your quarter back.};
$self->gumballMachine->currentState($self->gumballMachine->noQuarterState);
};

sub turnCrank {
my $self = shift;
print qq{You turned...};
$self->gumballMachine->currentState($self->gumballMachine->soldState);
};

sub dispense {
print qq{No gumball dispensation.};
};


Notice - the action only happens upon two events: turning the crank and eject. The rest of the methods just mumble on standard output.

Now here's the thing! The Machine (which we are about to see) delegates behavior to an object of the State class for implementation, according to current state. That means the Machine has got to hold objects of State class, one for each state. And each of these objects in turn own a copy of (i.e. reference to) the Machine. At any time, one (and only one) among the State objects of a Machine is set to the current state.

That's so something like this makes sense:

$self->gumballMachine->currentState($self->gumballMachine->soldState);

Notice how this action changes the current State of the Gumball Machine to a new State.

The underlying principle is Composition. It's something Beethoven did a lot of, before he started decomposing. The Machine is composed of States. Savvy?

Here then, is the Machine class:

package GumballMachine;
use Moose;

use State;

has 'hasQuarterState' => (
is => 'rw',
isa => 'State',
default => sub { HasQuarterState->new(gumballMachine => $_[0]); }
);

has 'soldState' => (
is => 'rw',
isa => 'State',
default => sub { SoldState->new(gumballMachine => $_[0]); }
);

has 'noQuarterState' => (
is => 'rw',
isa => 'State',
default => sub { NoQuarterState->new(gumballMachine => $_[0]); }
);

has 'soldOutState' => (
is => 'rw',
isa => 'State',
default => sub { SoldOutState->new(gumballMachine => $_[0]); }
);

has 'count' => (
is => 'rw',
isa => 'Num',
default => 0,
);

has 'currentState' => (
is => 'rw',
isa => 'State',
default => sub { $_[0]->{noQuarterState} },
);

sub releaseBall {
my $self = shift;
print qq{"Releasing a gumball.."};
$self->count($self->count - 1);
print $self->count." remaining.";
}

sub insertQuarter {
my $self = shift;
$self->currentState->insertQuarter;
}

sub ejectQuarter {
my $self = shift;
$self->currentState->ejectQuarter;
}

sub turnCrank {
my $self = shift;
$self->currentState->turnCrank;
}

sub dispense {
my $self = shift;
$self->currentState->dispense;
}

1;


A few notes on Moose:
1.
Note the keyword 'extends' for inheritance. The abstract class is simply implemented with empty methods.
2.
Note the use of default attribute to populate slots. The default holds a sub reference. For reference to self in the default definition, $_[0] applies.
3.
Note the use of delegation and composition. The Machine is composed of States and delegates actions to the object of State class representing its current state. These are extremely powerful concepts.
One area where I have found it useful to deploy these concepts is inter-operable document standards - when converting between standard XML namespaces. My target data-structure delegates parsing to a streaming SAX parser which packages information from the source file into neat parcels. The delegatee then ships out ready parcels to the target data-structure's container classes.
4.
I have used an abstract class instead of a role. Though roles, in general, are more strongly associated with composition, I believe this is largely a matter of semantics. Notice, I could have used the Method Modifier 'after' instead of over-riding methods from the abstract class. You will find Method Modifiers used in my latest code.

~ * ~

All code in this series may be downloaded from:
http://sites.google.com/site/sanjaybhatikar/codeunquote/designpatterns-1

Tuesday, October 20, 2009

Design Patterns in Moose

These days, design patterns are everywhere. And why not? Exposure is what shapes raw developer-material into greatness! And what better way to get exposure than through condensed experience in the form of Design Patterns - well-formulated problems and the pragmatic programmatic patterns that solve them!

Mind you, Design Patterns are a double-edged sword. The strength is also the weakness - too many patterns and one faces the classic problem known as over-fitting in the predictive modeling community, to wit, one becomes useless at doing anything that differs from what one has seen before.

The trick to design patterns is building this castle on a solid foundation of systems engineering. That is, knowledge of software systems and their interacting components. Practical knowledge of software systems. One has really got to be at a point, like Beethoven poised to write the 9th symphony, where all past work seems vaguely dissatisfying. Yes, work got done, but it could have been done better! Perhaps, the people maintaining that code-base you contributed to are complaining. Or there are faint but audible murmurs about how they wish they could just throw away that code-base and start from scratch.

You have got to base knowledge of Design Patterns on experience.

Thus forewarned, pardner, let me now roll-out before you my plan. You see, Design Patterns have been popularized in the Java world by a nifty book called "Head First Design Patterns" that features a hot chick on the cover at a flattering angle. And, about the same time, the Perl world is abuzz with Moose - a swanky post-modern object-oriented framework. Need I say more?

What this is about is implementing the Design Patterns - fully a Baker's dozen of them - in Moose-Perl. Now whaddya say to that?

The idea is not a one-one mapping between concepts in the Java and Moose worlds, but to demonstrate the effectiveness of the Moose framework. Or possibly the lack thereof, for this blog is objective. See, there is a lot of talk lately of how Perl is falling behind newer entrants like Python and Ruby. There is talk of how companies with an eagle eye on the bottom-line are moving away from Perl. And how, very soon, the only programmers in the Perl world are likely to be legacy coders.

That disturbs me. Because I really like Perl. Deep down, I feel a sense of well-being coding in Perl that I don't feel elsewhere. It is like Perl is my native tongue, aligned with my thought patterns. When I code in Perl, code seems to flow out of my fingers from the thoughts abuzz in my mind.

And that is fun! Fun that I would like to share with others in the world. Anyone have a pic of Larry's daughter? I hear she is hot! Just kidding folks, testing to see that you are still with me.

This series isn't going to be spoon-feeding. Neither is it an introduction to object-oriented programming. Where it seems appropriate, I shall point out certain object-oriented features to rave about. Or rant at abuse of the principles underlying these features. The idea, as always with this blog, is that you - the intelligent, handsome, sexy reader - try out stuff. And have fun doing it. I'll give you enough to keep you going.

Watch out for the Moose!

~ * ~

All code in this series may be downloaded from:
http://sites.google.com/site/sanjaybhatikar/codeunquote/designpatterns-1

Notes on Syntax Highlighting

http://pleasemakeanote.blogspot.com/2008/06/posting-source-code-in-blogger.html

Has very clear instructions.

Exception Handling: Part 05 of 05

Part 5: Exception Handling Best Practices

Target Audience: This pitch would interest a developer interested in the Exception Handling Best Practices in Perl. This series starts with basic exception handling and adds complexity, ending with pragmatic Best Practices recommendation.

You have put up with a lot so far and here is where it all becomes worthwhile. Best Practices, in a numbered list. Now, how much is that worth to you? (I accept checks.)

  • Use Exception::Class. Enuf said!
  • Use Fatal.pm for core perl functions:
eval { open(FH, "/non-existent/file") };
warn($@) if $@;
eval { close(FH) };
warn($@) if $@;
eval { chdir("gobbledegook") };
warn($@) if $@;
eval { unlink("/etc/password") };
warn($@) if $@;
eval { socket(SOCK, AF_INET, SOCK_STREAM, getprotobyname('tcp')) };
warn($@) if $@;
  • Define a $SIG{__DIE__} to turn string exceptions into objects
  • Trap exceptions using the 'eval' block and conditions set on the special variable $@
  • ALLOW EXCEPTIONS TO PROPAGATE!
  • Handle only an exception of an expected type.
  • To log all exceptions, use main() wrapped in exception handler.
  • Use Fatal qw(:void) in Perl 5.6+
~ * ~

All code in this series may be downloaded from:
http://sites.google.com/site/sanjaybhatikar/codeunquote/exceptionhandling-1

Exception Handling: Part 04 of 05

Part 4: Tying up loose ends with the $SIG{__DIE__}

Target Audience: This pitch would interest a developer interested in the Exception Handling Best Practices in Perl. This series starts with basic exception handling and adds complexity, ending with pragmatic Best Practices recommendation.

local $SIG{__DIE__} = sub {
my $e = shift;
if ($e->isa('My::Exception::Base')) {
die $e;
} else {
die My::Exception::Base->new($e);
}
};

All this does is cast an exception into an Exception::Class type. If already that, then simply thrown as exception with 'die'.

Clever, huh? This works because $SIG{__DIE__} is called invisibly FIRST, BEFORE ANYTHING ELSE when an exception is thrown, and the program continues to 'die' upon the handler's return. (Hence, DO NOT trap exceptions with $SIG{__DIE__} !)

Why is the $SIG{__DIE__} handler declared local?

Sunday, October 4, 2009

Barbershop Wisdom

"But the problem with y'all cats today, is that you got no skill. No sense of history. And then, with a straight face, got the nerve to want to be somebody. Want somebody to respect you. But it takes respect to get respect. Understand? See, I'm old. But, Lord willing, I'd be spared the sight of seeing everything that we worked for flushed down the drain by someone who don't know no better or care."

I like to reflect on how well that applies to software development. Candidate interviews particularly give food for thought.

Monday, September 21, 2009

Exception Handling: Part 03 of 05

Part 3: Post-Modern Exception Handling with Classes

Target Audience: This pitch would interest a developer interested in the Exception Handling Best Practices in Perl. This series starts with basic exception handling and adds complexity, ending with pragmatic Best Practices recommendation.

I have never met Larry Wall, the inventor of Perl. I don't know what he is like as a person. However, I like the approach he brings to the programming world. Specifically, I like that his approach is to lighten up programming in areas where there is no reason to be grim. While sharpening focus on that which really deserves the attention of a creative developer.

In a sense, Larry's Perl is like English - a bitch that isn't faithful to any one narrowly-defined culture, religion, nation or community but goes around mixing promiscuously, taking attractive elements from here and there, whatever works, to become more agreeable and less strait-laced. There are people who find English a terrible language. Those are the kind of people who probably don't find Perl endearing. Those are also probably the kind of guys (and girls) who take notes in hard-bound books in neat handwriting with pagination and time-date stamps. As for me, Perl is my kind of bitch.

The post-modern approach isn't hide-bound. It doesn't prize originality over all else and is accepting of human foibles. One can be rather ingenious in putting together ideas freely and flexibly. And that is where I'd rather invest my time than spend a lot of it reinventing the wheel and unimaginative book-keeping.

Onward, onto Exception Classes, with this code-snippet.



use Exception::Class (
'My::Exception::Base',
'My::Exception::Base::Outer' => {
isa => 'My::Exception::Base',
description => 'Error outside',
},
'My::Exception::Base::Outer::Inner' => {
isa => 'My::Exception::Base::Outer',
description => 'Error inside',
},
);

What if I needn't write the 'throw' sub each time? What if I could leave it to .. say a Class. I could then dervive other classes from the base class to customize behavior. These specialized classes would inherit all methods of the base class, including the handy 'throw' method.

Hmm, all the goodness of object-orientated programming, at the finger-tips..

That is exactly what Exception::Class does! Now are you convinced?

What I've done is I have defined a hierarchy of exception-handling classes from the base class. In case you still need convincing, now I can query an exception's class and handle the exception accordingly.

An exception is thrown as:

My::Exception::Base->throw ("Unable to fopen $fname");

and handled as:

eval {
$secret = outer($fname);
};
if ($@) {
print $@->trace;
}

for obtaining a stack-trace.

Want to dispatch handlers based on the class type? You can do that now! Follow the simple querying patter illustrated in the snippet:

eval {
$secret = outer($fname);
};
if ($@->isa('My::Exception::Base::Outer::Inner')) {
print $@->trace;
}

Note how easy stack-tracing is with the 'trace' method. There are other methods of the base Exception::Class which are just as useful.

But hang on before you break out that bottle of bubbly! All your exception-handling woes are fast disappearing.. but there is still one niggling little problem. That problem comes from classes. Can you guess?

Remember, while your code is now (nearly) fit for exhibition in any museum of post-modern art, not everyone else's code is so! Particularly, I direct your attention to all those modules from CPAN, judging by all the 'use' directives your code is liberally peppered with. What about those modules? - if any one of those doesn't implement exception-handling based on 'Exception::Class', that breaks our model. Can you see why?

That little bit takes us to $SIG{__DIE__} in the penultimate part of this series. Here, now, is the complete code. What is the handler of all 'die' calls upto? That answer is coming Part 4.

use strict;
$, = "\t", $\ = "\n";
use Exception::Class (
'My::Exception::Base',
'My::Exception::Base::Outer' => {
isa => 'My::Exception::Base',
description => 'Error outside',
},
'My::Exception::Base::Outer::Inner' => {
isa => 'My::Exception::Base::Outer',
description => 'Error inside',
},
);

sub main {
my $fname = 'secret.dat';
my $secret;

$secret = outer($fname);

print $secret;
};

eval {
main();
};
if ($@) {
print $@->trace;
}

sub outer {
my $fname = shift;
my $secret;
$secret = inner1($fname);
return $secret;
}

sub inner1 {
my $fname = shift;
my $secret;
$secret = inner2($fname);
return $secret;
}

sub inner2 {
my $fname = shift;
my $secret;
$secret = inner3($fname);
return $secret;
}

sub inner3 {
#My::Exception::Base->throw ("junk");
my $fname = shift;
my $secret;
open(SECRET, "<$fname")
|| My::Exception::Base->throw ("Unable to fopen $fname");
$secret = < SECRET >;
close(SECRET);

return $secret;
}

local $SIG{__DIE__} = sub {
my $e = shift;
if ($e->isa('My::Exception::Base')) {
die $e;
} else {
die My::Exception::Base->new($e);
}
};

Exception Handling: Part 02 of 05

Part 2: Stack-tracing with a custom 'throw' sub.

Target Audience: This pitch would interest a developer interested in the Exception Handling Best Practices in Perl. This series starts with basic exception handling and adds complexity, ending with pragmatic Best Practices recommendation.


So you've come back wanting to put a stack-trace in your code. Here's the code, before we start deconstructing. Add this sub throw to your code and call it 'myLittleException01.pl'.


sub throw {
my $mess = shift;
my $i = 1;
package DB;
while (my @parts = caller($i++)) {
print "$parts[3](@DB::args), $parts[1], $parts[2]";
};
die $mess;
}


Modify sub 'inner3' to 'throw' instead of 'die' as illustrated:


sub inner3 {
# throw ("junk");
my $fname = shift;
my $secret;
open(SECRET, "<$fname") || throw ("Unable to fopen $fname");
$secret = < SECRET >;
close(SECRET);

return $secret;
}


Note, you can 'throw' just as well as 'die' anywhere in your code.

Before go any further, proof of the pudding is in the eating. Here's what a stack-trace looks like.



There are actually three stack-traces here - did you notice? That's because my main package executes the functions as follows:


# F i r s t #
eval {
$secret = outer($fname, "1");
};
if ($@) {
print $@;
}

# S e c o n d #
eval {
$secret = inner2($fname);
};
if ($@) {
print $@;
}

# T h i r d #
$secret = inner1($fname);


Why am I doing this? To demonstrate that this is indeed genuine stack-tracing. Bear with me if it seems redundant.

Now for the catechism.

Follow me! (Cont'd)

8.
STACK TRACE
What is it? How does it benefit?
Run the script.
Track the programmatic flow via stack-trace.
10.
sub 'throw' - what is the minimum definition? ('die', with message)

sub throw {
my $mess = shift;
die $mess;
}

11.
use 'caller' for STACK TRACE
What is the frame-stack? (Code executes in frames. Like shooting pictures with a camera in rapid succession to execute a movie.)
Is a function in Perl self-aware? (Can it introspect?)
Does a function know what frames were executed before it?
How to obtain a frame-stack?
perldoc caller
Try the following: put in sub 'caller' and observe behavior.
What do you see?

sub throw {
my $mess = shift;
my $i = 1;
while (my @parts = caller($i++)) {
print "$parts[1], $parts[2], $parts[3]";
};
die $mess;
}

12.
Use 'caller' for STACK TRACE (cont'd).
perldoc caller - in case you missed it first time! :o)
Try the following: refine 'caller' behavior.
What do you see?

sub throw {
my $mess = shift;
my $i = 1;
while (my @parts = caller($i++)) {
print "$parts[3](), $parts[1], $parts[2]";
};
die $mess;
}

13.
Try the following:
Uncomment in 'inner3' - throw("junk")
Call 'inner3' in main without the 'eval' block;
What do you see?
14.
To see the arguments of a function call.
perldoc DB
package DB

sub throw {
my $mess = shift;
my $i = 1;
package DB;
while (my @parts = caller($i++)) {
print "$parts[3](@DB::args), $parts[1], $parts[2]";
};
die $mess;
}

15.
The final script is provided below.

use strict;
$, = "\t", $\ = "\n";

my $fname = 'secret1.dat';
my $secret;

eval {
$secret = outer($fname, "1");
};

if ($@) {
print $@;
}
eval {
$secret = inner2($fname);
};
if ($@) {
print $@;
}
$secret = inner1($fname);

print $secret;

sub outer {
my $fname = shift;
my $secret;
$secret = inner1($fname);
return $secret;
}

sub inner1 {
my $fname = shift;
my $secret;
$secret = inner2($fname);
return $secret;
}

sub inner2 {
my $fname = shift;
my $secret;
$secret = inner3($fname);
return $secret;
}

sub inner3 {
# throw ("junk");
my $fname = shift;
my $secret;
open(SECRET, "<$fname") || throw ("Unable to fopen $fname");
$secret = < SECRET >;
close(SECRET);

return $secret;
}

sub throw {
my $mess = shift;
my $i = 1;
package DB;
while (my @parts = caller($i++)) {
print "$parts[3](@DB::args), $parts[1], $parts[2]";
};
die $mess;
}


What have we achieved? Quite a bit, actually! We are able to attain a stack-trace and that itself is of enormous value in debugging. But before we get too excited, what are some the potential drawbacks?

Aha! I still depend on strings for error-handling. How would you like to improve the world a little bit further? Did I hear you say "Exception Classes?" That's right. Ladies and Gentlemen, I give you, Exception::Class (Sound of furious clapping and oohs and aahs as the public goes wild in anticipation.)

That's what's coming up in Part-03.

Exception Handling: Part 01 of 05

Part 1: Exception Handing Basics

Prelude

What better place to begin than one of the hottest areas of software development - exception handling! Just kidding, folks :o)

When I was a novice writing software, my supervisors had to force us newbies to put in exception handling. We thought of them as old fogies, with nothing better to do than make life miserable for us young people brimming with creativity and talent.

Life goes by and pretty soon one becomes an old fogey oneself. I haven't quite gotten there myself (yet), but I recently had the opportunity to revisit exception handling when some expensive code died without a stack-trace and I couldn't leave for the day until I got to the bottom of it. Unfortunately the entire application, developed by an out-sourcing firm, had been designed by some brilliant programmers who paid only a cursory nod to exception handling. That pretty much meant looking for a needle in a haystack everytime the code broke. Hacking into code. Putting in print statements. Uggh! (Now I realize why we need a a team of full-time experts dedicated exclusively to code maintenance.)

Thus begins the Exception Handling saga. In these 4 parts, I shall cover Exception handling in Perl from basic to best practices. Although this is a perl tutorial, you may find the concepts map to Java or any other programming language designed to make life interesting.

We'll start with the script (below). It opens a file 'secret.dat' which has but one word - the secret word. To read this secret word, the (default) main package has function 'outer' which calls 'inner1' which calls 'inner2' which calls 'inner3' where the file is opened with the native 'open' function.

Copy-Paste the script below into a file, say 'myLittleException01.pl'. The way this works is, you work through the catechism using the accompanying script in each of the parts 1 through 4 (See: "Follow me!" below). There, you're all set.


use strict;
$, = "\t", $\ = "\n";

my $fname = 'secret.dat';
my $secret;
eval {
$secret = outer($fname);
};
if ($@) {
print "Got e: $@";
}

print $secret;

sub outer {
my $fname = shift;
my $secret;
$secret = inner1($fname);
return $secret;
}

sub inner1 {
my $fname = shift;
my $secret;
$secret = inner2($fname);
return $secret;
}

sub inner2 {
my $fname = shift;
my $secret;
$secret = inner3($fname);
return $secret;
}

sub inner3 {
die ("junk");
my $fname = shift;
my $secret;
open(SECRET, "<$fname") || die ("Unable to open $fname");
$secret = < SECRET >;
close(SECRET);
return $secret;
}



Follow me!

1.
No exception handling:
Run the script without any exception handling;
Modify 'inner3' - remove 'die'.
2.
How to throw an exception?
In perl, 'die'; See 'inner3'.
3.
Now with 'die' in sub 'inner3' - run-time error, script exits with error message
4.
How to trap the exception for handling?
'eval' block and special variable '$@'
The error is trapped and message displayed (i.e. exception handled).
Note the use of special variable '$@'.
5.
What happens with two instances of 'die'?
Only the 1st exception is handled. Obvious?
7.
Drawbacks?
- In any software application, 'die' will be thrown from many places.
- STACK TRACE: How to trace through the maze of callers?
- - The application is a tree data-structure (DAG)
- - $@ - string-based exception-handling scheme
- - Exception handling by 'eval' block and $@ is limited.

You can see what basic facilities Perl offers for exception handling. And also how string-based exception handling is limited when it comes to software applications with a maze of interacting packages and external dependencies. There is no stack tracing which makes debugging a hit-and-miss. The sort of thing that keeps developers away from the arms of pretty girls (or boys, depending on gender and sexual orientation) and hastens the onset of burn-out.

Now let's make the world a little better place by putting in stack tracing. And since, ladies and gentlemen, we are fine programmers, let us first devise this stack-tracing contrivance ourselves.

The woods are lovely dark and deep ..

A few introductory words are in order.

This blog presents live examples with a practical flavor from the deep, dark and lovely woods of the software world.

Programming is a form of self-expression. I believe this to be the correct attitude to software development at all levels from scripting and architecture to project management and business development in the software world. As one develops in this path, one finds oneself using a programming language as a tool to express increasingly powerful ideas encapsulating growing sophistication. One naturally relies on increasingly sophisticated programming constructs - advancing from shaky scripts with patchy logic glued together with basic control structures to rock-solid organization and reusability with packages and namespaces and finally composite design patterns in object-oriented idioms deploying all the worldly goodness of abstraction, encapsulation, composition and inheritance.

It is thrilling to find programming languages on an evolutionary path leading to greater flexibility and fluent expression of ideas in code.

Thus C++ has evolved smart-pointers, templated classes and the awesome goodness of the Standard Template Library (STL).

Perl, my favorite linguistic programming language, evolves with a suave and post-modern framework - Moose, making Object-Oriented Programming a Zen experience. Zen, as in natural and intuitive. Or Catalyst - a thoroughly contemporary, industrial-strength Model-View-Controller Framework.

Life, just gets better!

In this blog, I share some of my experiences in programming in the Linux-Apache-MySQL-Perl and R (LAMP-R) as best-practices. It is a damn shame that India is still overwhelmingly biased towards expensive, closed-source technologies whereas the rich West has absorbed the economical benefits and effectiveness of open-source. Not unlike the mother from a slum feeding her child Nestle Cerelac baby-food because it comes in a tin whereas the rich mother breast-feeds her baby because she is better-informed about child-care.

Well, as a wise old man said, we must be the change we hope to see :)