SlideShare a Scribd company logo
Moo in practice - App::Math::Tutor
Jens Rehsack
Niederrhein Perl Mongers
2014-2015
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 1 / 41
Introduction Motivation
Motivation
Moo and App::Math::Tutor
real world examples over far-fetched conceptuals
MooX::Cmd, MooX::Options and MooX::ConfigFromFile provide way more
features and flexibility than either
◮ App::Cmd with Getopt::Long::Descriptive
◮ MooseX::App::Cmd along with corresponding MooseX wrappers around
related stuff
2nd
generation of modern OO in Perl5
App::Math::Tutor
Allow parents help their children improving their mathematical skills
Add support for exercise types as children require
provide extensible design to allow easy augment of exercise
Goal: Improve to Web-Service, eg. by mapping MooX::Cmd to URI path and
MooX::Options to GET parameters
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 3 / 41
Introduction Audience
Audience
Audience
Developers who want to create or improve Perl5 software
Developers who want to learn how to develop modern OO with Perl5
Developers who are interested in developing mathematical exercises
Prerequisites of the Audience
Following knowledge is expected:
General knowledge about object oriented programming or concepts like
◮ classes
◮ objects
◮ polymorphism, inheritance and/or roles
◮ methods, class functions
◮ attributes, properties
slightly above basic Perl experience
ever heard of Smalltalk and its OO-concept is a strong bonus
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 4 / 41
Modules Classes and Roles
Classes in Moo
classes can be instantiated
one can inherit from classes
one can aggregate classes
distinguish naming conflicts is up to developer
{
package Natural;
use Moo;
sub _stringify { ... };
}
{
package Roman;
use Moo;
extends "Natural";
sub _stringify { ... };
}
my $natnum = Natural ->new( value => 42 ); say $natnum ->_stringify (); # 42
my $romnum = Roman ->new( value => 42 ); say $romnum ->_stringify (); # XLII
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 6 / 41
Modules Classes and Roles
Roles in Moo
roles describe a dedicated behavior (e.g. printable)
roles can be composed into classes
one can’t inherit from roles - only consume
roles cannot exist stand-alone
roles are consumed once
naming conflicts cause compile time error
{ package Printable;
use Moo:: Role; # now it’s a role - no ’is a’ relationship anymore
sub print { my $self = shift; say $self ->_stringify }
}
{ package Natural;
use Moo; # class
with "Printable"; # consumes a role
sub _stringify { ... };
}
my $natnum = Natural ->new( value => 42 ); $natnum ->print; # 42
my $romnum = Roman ->new( value => 42 ); $romnum ->print; # XLII
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 7 / 41
Attributes Attributes in Moo
Attributes in Moo
package VulFrac;
use Moo;
has nume rator => ( is => "ro", required => 1 );
has denom inator => ( is => "ro", required => 1 );
1;
use ”has” keyword to define a attribute
attributes ”numerator” and ”denominator”
attributes are immutable and required
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 8 / 41
Attributes Attribute Options
Attribute options - Selection I
is mandatory behavior description
ro defines the attribute is read-only
rw defined the attribute is read/writable
lazy defines the attribute is read-only with a lazy
initialization, implies builder => 1
required when set to a true value, attribute must be passed on instantiation
init arg Takes the name of the key to look for at instantiation time of the
object. A common use of this is to make an underscored attribute
have a non-underscored initialization name. undef means that
passing the value in on instantiation is ignored.
isa defines a subroutine (coderef) which is called to validate values to
set
coerce defines a subroutine (coderef) which forces attribute values
default subroutine (coderef) which is called to initialize an attribute
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 9 / 41
Attributes Attribute Options
Attribute options - Selection II
Following options can benefit from attribute shortcuts: the value of 1 instead of a
method name means to generate a coderef which calls the method
${option name} ${attr name}
builder takes a method name (string) which is called to initialize an
attribute (calls build ${attr name} on attribute shortcut)
trigger takes a subroutine (coderef) which is called anytime the attribute
is set (calls trigger ${attr name} on attribute shortcut)
clearer takes a method name (string) which will clear the attribute
(provides clear ${attr name} on attribute shortcut)
predicate takes a method name (string) which will return true if an
attribute has a value (provides has ${attr name} on attribute
shortcut)
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 10 / 41
Methods Method Examples
Methods in Moo I
package VulFrac;
use Moo;
use overload ’""’ => " _stringify",
’0+’ => "_numify",
’bool ’ => sub { 1 },
’<=>’ => " _num_compare";
has numerator => ( is => "ro", required => 1 );
has denominator => ( is => "ro", required => 1,
isa => sub { $_ [0] != 0 or die "Not != 0" };
sub _stringify { my $self = shift;
return sprintf(" frac {%s}{%s}",
$self ->numerator , $self -> denominator ); }
sub _numify { $_[0]-> numerator / $_[0]-> denominator ; }
...
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 11 / 41
Methods Method Examples
Methods in Moo II
package Rationale;
use Moo;
extends "VulFrac";
has digits => ( is => "ro", required => 1 );
sub _stringify {
my $digits = $_[0]-> digits;
sprintf("%.${digits}g", $_[0]-> _numify ); }
nothing like MooseX::Declare - pure Perl5 keywords are enough for plain
methods
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 12 / 41
Methods Method Modifiers
Method Modifiers
Method modifiers are a convenient feature from the CLOS (Common Lisp Object
System) world:
before before method(s) => sub { ...}
before is called before the method it is modifying. Its return value
is totally ignored.
after after method(s) => sub { ...}
after is called after the method it is modifying. Its return value is
totally ignored.
around around method(s) => sub { ...}
around is called instead of the method it is modifying. The method
you’re overriding is passed as coderef in the first argument.
- No support for super, override, inner or augment
In doubt MooX::Override provides override and super while MooX::Augment
provides augment and inner
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 13 / 41
Methods Method Modifiers
Method Modifiers - Advantages
supersedes $self->SUPER::foo(@ ) syntax
cleaner interface than SUPER
allows multiple modifiers in single namespace
also possible from within roles and not restricted to inheritance
ensures that inherited methods invocation happens right (mostly - remember
around)
no need to change packages
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 14 / 41
Methods Method Modifiers
Methods Modifiers - around avoid calling $orig
package App:: Math :: Tutor :: Role :: Roman;
use Moo:: Role;
with "App:: Math :: Tutor :: Role :: Natural";
{ package RomanNum;
use Moo;
extends "NatNum"; # derives overloading !
sub _stringify { ... } }
around " _guess_natural_number" => sub {
my $orig = shift;
my $max_val = $_[0]-> format;
my $value = int( rand( $max_val - 1 ) ) + 1;
return RomanNum ->new( value => $value );
};
captures control
receives responsibility
runtime of modified method completely eliminated
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 15 / 41
Methods Method Modifiers
Methods Modifiers - around modifying $orig return value
package App:: Math :: Tutor :: Role :: Roman;
use Moo:: Role;
with "App:: Math :: Tutor :: Role :: Natural";
{ package RomanNum;
use Moo;
extends "NatNum"; # derives overloading !
sub _stringify { ... } }
around " _guess_natural_number" => sub {
my $orig = shift;
my $num = $orig ->(@_);
return RomanNum ->new( value => $num ->value );
};
modifies only required part
leaves most responsibility in modified method
runtime of modified method added to this method’s runtime
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 16 / 41
Structure Frontend
Frontend (dictated by MooX::Cmd)
App::Math::Tutor
App::Math::Tutor::Cmd::VulFrac
App::Math::Tutor::Cmd::VulFrac::Cmd::Add
App::Math::Tutor::Cmd::VulFrac::Cmd::Mul
App::Math::Tutor::Cmd::VulFrac::Cmd::Cast
App::Math::Tutor::Cmd::Natural
App::Math::Tutor::Cmd::Natural::Cmd::Add
App::Math::Tutor::Cmd::Natural::Cmd::Mul
App::Math::Tutor::Cmd::Roman
App::Math::Tutor::Cmd::Roman::Cmd::Add
App::Math::Tutor::Cmd::Roman::Cmd::Cast
App::Math::Tutor::Cmd::Unit
App::Math::Tutor::Cmd::Unit::Cmd::Add
App::Math::Tutor::Cmd::Unit::Cmd::Mul
App::Math::Tutor::Cmd::Unit::Cmd::Cast
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 18 / 41
Structure CLI Concept
Exercise Groups
App::Math::Tutor::Cmd::VulFrac Exercises in vulgar fraction calculation
App::Math::Tutor::Cmd::Natural Exercises in calculations using natural numbers
App::Math::Tutor::Cmd::Roman Exercises in calculations using natural numbers,
but show them using roman number encoding (exercises and
solutions)
App::Math::Tutor::Cmd::Unit Exercises in calculations using units (times,
currency, . . . )
App::Math::Tutor::Cmd::Power Exercises in calculations of power mathematics
App::Math::Tutor::Cmd::Polynom Exercises for polynomial mathematics (Zero of
a function, Vertex, . . . )
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 19 / 41
Design Simple Exercise
Typical Exercise design
App::Math::Tutor::Cmd::VulFrac::Cmd::Add
build exercise() : exercise
App::Math::Tutor::Role::VulFracExercise
format
App::Math::Tutor::Role::VulFrac
check vulgar fraction() : bool
guess vulgar fraction() : VulFrac
get vulgar fractions() : [ VulFrac ]
VulFrac
num
denum
stringify() : Str
numify() : Num
num compare() : Int
euklid() : Int
gcd() : Int
reduce() : VulFrac
reciprocal() : VulFrac
App::Math::Tutor::Role::Exercise
exercise : lazy
# { section, caption, label,
# header, challenges, solutions }
output name : lazy
template filename : lazy
build exercise() = 0 : exercise
build output name() : Str
build template filename() = 0 : Str
execute()
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 20 / 41
Design Derived Exercise
Derived Exercise design
App::Math::Tutor::Cmd::Roman::Cmd::Add
build exercise() : exercise
App::Math::Tutor::Role::NaturalExercise
format
App::Math::Tutor::Role::Roman
around => guess natural number() : Roman
App::Math::Tutor::Role::Natural
check natural number() : bool
guess natural number() : Natural
get natural number() : [ Natural ]
RomanNum
stringify() : Str
Natural
value
stringify() : Str
numify() : Num
num compare() : Int
App::Math::Tutor::Role::Exercise
exercise : lazy
# { section, caption, label,
# header, challenges, solutions }
output name : lazy
template filename : lazy
build exercise() = 0 : exercise
build output name() : Str
build template filename() = 0 : Str
execute()
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 21 / 41
Improvements Design
Improving design
introduce factories
add lazy factory attribute (allowes overriding factory to use by around’ing
builder)
separate number classes (type system, but no MooseX::Types)
approval for reasonable exercise value should be part of factory
approval for valid number should be coerced (trigger?)
Design history
I started with just vulgar fraction exercises
Design covered exactly those needs
Design future
Modern Perl-OO allowes easy refactoring to apply above improvements
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 22 / 41
MooX General purpose eXtensions
MooX in general
Some Moo extensions for getting a picture - the list is neither complete nor is it
intended to be
MooX Distributions
MooX::Log::Any logging role building a very lightweight wrapper to Log::Any
MooX::Validate minimalist Data Validation for Moo
MooX::Types::MooseLike Moose like types for Moo
MooX::Override adds ”override method => sub . . . ” support to Moo
MooX::Augment adds ”augment method => sub . . . ” support to Moo
MooX::late easily translate Moose code to Moo
MooX::PrivateAttributes create attribute only usable inside your package
MooX::Singleton turn your Moo class into singleton
MooX::Aliases easy aliasing of methods and attributes in Moo
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 24 / 41
MooX CLI related eXtensions
MooX Distributions for CLI
MooX::Cmd
giving an easy Moo style way to make command organized CLI apps
support sub-commands with separated options when used together with
MooX::Options
MooX::Options
explicit Options eXtension for Object Class
no mess with composed attributes
MooX::ConfigFromFile
Moo eXtension for initializing objects from config file
RC files with structures (JSON, INI, YAML, XML, ...)
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 25 / 41
MooX CLI related eXtensions
General CLI Construction Flow
:main :MooX::Cmd :MooX::Options :MooX::ConfigFromFile :Moo
new with cmd()
buildcommand
commands()
splitargv
new with options()
parse
options
new()
BUILDARGS()
super->BUILDARGS()
buildloaded
config
helpon
exception
execute
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 26 / 41
Provided Framework Exercise Role
package App:: Math :: Tutor :: Role :: Exercise;
use strictures; # instead of strict + warnings
use Moo:: Role; use MooX :: Options;
option quantity => (
is => "ro",
doc => "Specifies number of exercises to generate",
long_doc => "Specify number of exercises to generate. "
. "In case of several kind of ...",
format => "i",
short => "n",
default => sub { 15 },
);
has output _name => ( is => "lazy" );
sub _build_output_name {
join( "", map { $_ -> command_name || "" } @{ $_[0]-> command_chain } );
}
being a role (no ”is a” relationship) and add CLI options capabilities
defining an attribute which will be initialized by command line
support MooX::Option’s --man usage feature
attribute for output file to generate — lazy to allow provide individual
name builder
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 28 / 41
Provided Framework Exercise Role
has exercises => ( is => "lazy" );
sub execute {
my $exercises = $_[0]->exercises;
my $ttcpath = File ::Spec ->catfile(
File :: ShareDir :: dist_dir("App -Math -Tutor"),
$_[0]-> template_filename . ".tt2" );
my $template = Template ->new( { ABSOLUTE => 1 });
my $rc = $template ->process( $ttcpath , {
exercises => $exercises ,
output => { format => ’pdf’ },
},
$_[0]-> output_name . ’.pdf’);
$rc or croak( $template ->error () );
return 0;
}
attribute containing the exercises definitions, exercises itself and their
solutions (depending on template) — lazy implies requires
’’ build exercises’’
method to satisfy MooX::Cmd
fetch exercises definition implies calling build exercises
build full qualified path of template file name residing in app’s share
directory, instantiate template processor and run it
force output format ”pdf” (Template::LaTeX will be instructed by template)
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 29 / 41
Provided Framework Vulgar Fraction Exercise Role
package App:: Math :: Tutor :: Role ::Vul FracExercise;
use strictures; use Moo:: Role; use MooX :: Options;
with "App:: Math :: Tutor :: Role :: Exercise", "App:: Math :: Tutor :: Role :: VulFrac";
option format => (
is => "ro",
doc => "specifies format of numerator/ denominator ",
long_doc => "Allow specifying the format of the numerator/ denominator ...",
isa => sub { defined( $_[0] ) and !ref $_[0]
and $_ [0] !~ m ,^d?n+(?:/d?n+)?$, and die("Invalid format");
},
coerce => sub { ...
my ( $fmta , $fmtb ) = ( $_[0] =~ m ,^(d?n+)(?:/(d?n+))?$, );
$fmtb //= $fmta;
my $starta = "1"; my $startb = "1";
$fmta =~ s/^(d)(.*)/ $2/ and $starta = $1;
$fmtb =~ s/^(d)(.*)/ $2/ and $startb = $1;
[ $starta . "0" x length($fmta), $startb . "0" x length($fmtb) ]
},
default => sub { return [ 100, 100 ]; }, format => "s",
);
be a nice package ˆWrole, intending to provide command line options for
instantiation
compose role behavior using Exercise and VulFrac
define option coercing option string into array ensuring the array ref as value
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 30 / 41
Create Exercise Preamble
package App:: Math :: Tutor :: Cmd:: VulFrac ::Cmd :: Add;
use strictures;
use Moo;
use MooX :: Cmd;
use MooX :: Options;
has template_filename => ( is => "ro",
default => "twocols");
with "App:: Math :: Tutor :: Role :: VulFracExercise ";
$ mtut vulfrac add
we’re of course a nice class
satisfy requirement of Exercise role: provide template filename – two column
template (for addition and substraction)
compose role ...VulFracExercise
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 31 / 41
Create Exercise Create Exercise Numbers
sub _build_exercises {
my ($self) = @_;
my (@tasks );
foreach my $i ( 1 .. $self ->amount ) {
my @line;
for ( 0 .. 1 ) { # 0: +, 1: -
my ( $a , $b ) = $self -> get_vulgar_fractions (2);
push @line , [ $a , $b ];
}
push @tasks , @line;
}
my $exercises = ...;
return $exercises;
}
exercise builder has to be provided by individual exercise
hold tasks of the exercise sheet
how many tasks per sheet? (remember the option in ...Role::Exercise)
a ”+” and a ”-” exercise per line
invoke factory per task
safe each line for processing
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 32 / 41
Create Exercise Format Challenge / Solution
my $exercises = {
section => "Vulgar fraction addition / subtraction ",
caption => ’Fractions ’,
label => ’vulgar_fractions_addition ’,
header => [ [ ’Vulgar Fraction Addition ’, ’Vulgar Fraction Su
challenges => [], solutions => [],
};
foreach my $line (@tasks) {
my ( @solution , @challenge );
foreach my $i ( 0 .. 1 ) {
my ( $a , $b , @way ) = @{ $line ->[$i] }; my $op = $i ? ’-’ : ’+’;
$op eq ’-’ and $a < $b and ( $b , $a ) = ( $a , $b );
push @challenge , sprintf( ’$ %s %s %s = $’, $a , $op , $b );
push @way , sprintf( ’%s %s %s’, $a , $op , $b );
...
}
push( @{ $exercises ->{ challenges} }, @challenge );
push( @{ $exercises ->{ solutions} }, @solution );
}
create exercise structure containing challenges and solutions
loop over created tasks and exercises per line
format challenge using operator ’""’ of VulFrac objects
same (but different) opening ”way” and remember the little thingies . . .
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 33 / 41
Create Exercise Format Solutions
sub _build_exercises {
( $a , $b ) = ( $a ->_reduce , $b = $b ->_reduce );
push @way , sprintf( ’%s %s %s’, $a , $op , $b )
if ( $a ->num != $line ->[$i]->[0]->num or $b ->num != ... );
my $gcd = VulFrac ->new( num => $a ->denum , denum => $b ->denum )->_gcd;
my ( $fa , $fb ) = ( $b ->{ denum} / $gcd , $a ->{ denum} / $gcd );
push @way , sprintf( ’frac {%d cdot %d}{%d cdot %d} %s ...’,
$a ->num , $fa , $a ->denum , $fa , $op , $b ->num , $fb , ... );
push @way , sprintf( ’frac {%d}{%d} %s frac {%d}{%d}’,
$a ->num*$fa , $a ->denum*$fa , $op , $b ->num*$fb , $b ->denum*$fb );
push @way , sprintf( ’frac {%d %s %d}{%d}’,
$a ->num * $fa , $op , $b ->num * $fb , $a ->denum * $fa );
my $s = VulFrac ->new( denum => $a ->denum * $fa ,
num => $i ? $a ->num * $fa - $b ->num * $fb : ...s/ -/+/);
push @way , "" . $s; my $c = $s ->_reduce; $c ->num != $s ->num and push @way , "
$c ->num > $c ->denum and $c ->denum > 1 and push @way , $c ->_stringify(1);
push( @solution , ’$ ’ . join( " = ", @way ) . ’ $’ );
}
try to reduce operands and add them to opening when successful
World of Handcraft: show calculation method by determine
geatest common divisor of operands denominator, format subsequent steps to
reach the solution
remark possible reducing, mixed fraction, cord it and go ahead
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 34 / 41
Created Exercise Output Challenges
Vulgar Fraction Addition Vulgar Fraction Subtraction
99
67
+ 43
84
= 45
41
− 32
48
=
19
7
+ 16
54
= 51
47
− 49
65
=
38
82
+ 38
99
= 56
33
− 30
32
=
96
80
+ 46
39
= 49
79
− 29
82
=
72
68
+ 46
99
= 42
49
− 38
59
=
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 35 / 41
Created Exercise Output Solutions
Vulgar Fraction Addition Vulgar Fraction Subtraction
99
67
+ 43
84
= 99·84
67·84
+ 43·67
84·67
= 8316
5628
+ 2881
5628
=
8316+2881
5628
= 11197
5628
= 15569
5628
45
41
− 32
48
= 45
41
− 2
3
= 45·3
41·3
− 2·41
3·41
= 135
123
− 82
123
=
135−82
123
= 53
123
19
7
+ 16
54
= 19
7
+ 8
27
= 19·27
7·27
+ 8·7
27·7
= 513
189
+
56
189
= 513+56
189
= 569
189
= 3 2
189
51
47
− 49
65
= 51
47
− 49
65
= 51·65
47·65
− 49·47
65·47
= 3315
3055
−
2303
3055
= 3315−2303
3055
= 1012
3055
38
82
+ 38
99
= 19
41
+ 38
99
= 19·99
41·99
+ 38·41
99·41
= 1881
4059
+
1558
4059
= 1881+1558
4059
= 3439
4059
56
33
− 30
32
= 56
33
− 15
16
= 56·16
33·16
− 15·33
16·33
= 896
528
−
495
528
= 896−495
528
= 401
528
96
80
+ 46
39
= 6
5
+ 46
39
= 6·39
5·39
+ 46·5
39·5
= 234
195
+ 230
195
=
234+230
195
= 464
195
= 2 74
195
49
79
− 29
82
= 49·82
79·82
− 29·79
82·79
= 4018
6478
− 2291
6478
=
4018−2291
6478
= 1727
6478
72
68
+ 46
99
= 18
17
+ 46
99
= 18·99
17·99
+ 46·17
99·17
= 1782
1683
+
782
1683
= 1782+782
1683
= 2564
1683
= 1 881
1683
42
49
− 38
59
= 6
7
− 38
59
= 6·59
7·59
− 38·7
59·7
= 354
413
− 266
413
=
354−266
413
= 88
413
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 36 / 41
Conclusion
Conclusion
lazy attributes allow designing a multi-stage initialization phase
benefit of common runtime (faster load) when using
◮ DBIx::Class
◮ Web::Simple (Jedi)
improve design by
◮ using roles for behavioral design (avoid duck typing)
◮ using explicit patterns for clear separation of concerns
◮ express intensions clearer for method overloading by using method modifiers
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 38 / 41
Resources Resources
Resources
Software
https://metacpan.org/pod/Moo/
https://github.com/moose/Moo
https://metacpan.org/search?q=MooX
https://metacpan.org/pod/MooX::Cmd
https://metacpan.org/pod/MooX::Options
https://metacpan.org/pod/MooX::ConfigFromFile
https://github.com/rehsack/App-Math-Tutor
IRC
irc://irc.perl.org/#moose
irc://irc.perl.org/#web-simple
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 39 / 41
Resources Thank you
Thank You For Contributing
Graham ”haarg” Knop Found a lot of spelling errors and first suggestions
Vincent ”celogeek” Bachelier Suggested some real examples
Fedor Babkin UML diagram improvements
Curtis ”Ovid” Poe Final review and figured out missing fundamentals
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 40 / 41
Resources Thank you
Thank You For Listening
Questions?
Jens Rehsack <rehsack@cpan.org>
Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 41 / 41

More Related Content

PPTX
Introduction to objective c
PPTX
Chapter 02 functions -class xii
DOC
CS2309 JAVA LAB MANUAL
PDF
Python Functions Tutorial | Working With Functions In Python | Python Trainin...
PPTX
Creating Objects in Python
PPTX
.NET F# Events
PPT
Functional Programming
DOC
Java programming lab assignments
Introduction to objective c
Chapter 02 functions -class xii
CS2309 JAVA LAB MANUAL
Python Functions Tutorial | Working With Functions In Python | Python Trainin...
Creating Objects in Python
.NET F# Events
Functional Programming
Java programming lab assignments

What's hot (20)

PDF
All experiment of java
PPS
Class method
PDF
Advanced Python, Part 1
PPTX
Python: Migrating from Procedural to Object-Oriented Programming
PDF
C sharp chap5
PPTX
Python - OOP Programming
PDF
C sharp chap6
PPTX
Python programming- Part IV(Functions)
PDF
Functions and modules in python
PDF
Java programming lab manual
DOCX
Java programming lab_manual_by_rohit_jaiswar
PDF
C sharp chap4
ODP
Python Modules
PDF
Functional programming in Scala
PPTX
Python programming –part 7
PPT
Operator overloading
PDF
Function overloading
PPTX
L03 Software Design
PDF
Python Modules
All experiment of java
Class method
Advanced Python, Part 1
Python: Migrating from Procedural to Object-Oriented Programming
C sharp chap5
Python - OOP Programming
C sharp chap6
Python programming- Part IV(Functions)
Functions and modules in python
Java programming lab manual
Java programming lab_manual_by_rohit_jaiswar
C sharp chap4
Python Modules
Functional programming in Scala
Python programming –part 7
Operator overloading
Function overloading
L03 Software Design
Python Modules
Ad

Similar to Moo at App::Math::Trainer (20)

PPTX
CHAPTER 01 FUNCTION in python class 12th.pptx
PDF
Moo at System::Image::Update
PPTX
Oops in php
DOCX
JLK Chapter 5 – Methods and ModularityDRAFT January 2015 Edition.docx
PPT
Basic Oops concept of PHP
PPT
Introduction Php
PDF
Dutch PHP Conference 2013: Distilled
PPTX
OOP Is More Than Cars and Dogs
PPTX
Functions2.pptx
PDF
20180904-object-oriented-programming-in-java.pdf
PDF
Object Oriented Programming Short Notes for Preperation of Exams
PPTX
Coming to Terms with OOP In Drupal - php[world] 2016
PDF
Functions2.pdf
PPTX
2 Functions2.pptx
PPTX
Ch8(oop)
PDF
Design patterns revisited with PHP 5.3
PDF
Lecture 8.pdf
PPTX
cbse class 12 Python Functions2 for class 12 .pptx
PPT
Oops in PHP
PPTX
McMullen_ProgwPython_1e_mod15_PowerPoint_Methods_Present.pptx
CHAPTER 01 FUNCTION in python class 12th.pptx
Moo at System::Image::Update
Oops in php
JLK Chapter 5 – Methods and ModularityDRAFT January 2015 Edition.docx
Basic Oops concept of PHP
Introduction Php
Dutch PHP Conference 2013: Distilled
OOP Is More Than Cars and Dogs
Functions2.pptx
20180904-object-oriented-programming-in-java.pdf
Object Oriented Programming Short Notes for Preperation of Exams
Coming to Terms with OOP In Drupal - php[world] 2016
Functions2.pdf
2 Functions2.pptx
Ch8(oop)
Design patterns revisited with PHP 5.3
Lecture 8.pdf
cbse class 12 Python Functions2 for class 12 .pptx
Oops in PHP
McMullen_ProgwPython_1e_mod15_PowerPoint_Methods_Present.pptx
Ad

More from Jens Rehsack (7)

PDF
System Monitoring with Unix::Statgrab and Perl
PDF
Perl6 for-beginners
PDF
Unix::Statgrab
PDF
A CMDB Driven by Perl
PDF
PkgSrc in Five Minutes
PDF
Cross Compiling for Perl Hackers
PDF
Perl on-embedded-devices
System Monitoring with Unix::Statgrab and Perl
Perl6 for-beginners
Unix::Statgrab
A CMDB Driven by Perl
PkgSrc in Five Minutes
Cross Compiling for Perl Hackers
Perl on-embedded-devices

Recently uploaded (20)

PDF
Softaken Excel to vCard Converter Software.pdf
PPTX
Reimagine Home Health with the Power of Agentic AI​
PDF
Upgrade and Innovation Strategies for SAP ERP Customers
PPTX
Essential Infomation Tech presentation.pptx
PPTX
history of c programming in notes for students .pptx
PDF
Odoo Companies in India – Driving Business Transformation.pdf
PPTX
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
PDF
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf
PPTX
Operating system designcfffgfgggggggvggggggggg
PDF
medical staffing services at VALiNTRY
PDF
How to Choose the Right IT Partner for Your Business in Malaysia
PDF
top salesforce developer skills in 2025.pdf
PPTX
L1 - Introduction to python Backend.pptx
PPTX
ai tools demonstartion for schools and inter college
PPTX
Transform Your Business with a Software ERP System
PPTX
VVF-Customer-Presentation2025-Ver1.9.pptx
PDF
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
PDF
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
PPTX
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
PDF
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
Softaken Excel to vCard Converter Software.pdf
Reimagine Home Health with the Power of Agentic AI​
Upgrade and Innovation Strategies for SAP ERP Customers
Essential Infomation Tech presentation.pptx
history of c programming in notes for students .pptx
Odoo Companies in India – Driving Business Transformation.pdf
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf
Operating system designcfffgfgggggggvggggggggg
medical staffing services at VALiNTRY
How to Choose the Right IT Partner for Your Business in Malaysia
top salesforce developer skills in 2025.pdf
L1 - Introduction to python Backend.pptx
ai tools demonstartion for schools and inter college
Transform Your Business with a Software ERP System
VVF-Customer-Presentation2025-Ver1.9.pptx
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus

Moo at App::Math::Trainer

  • 1. Moo in practice - App::Math::Tutor Jens Rehsack Niederrhein Perl Mongers 2014-2015 Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 1 / 41
  • 2. Introduction Motivation Motivation Moo and App::Math::Tutor real world examples over far-fetched conceptuals MooX::Cmd, MooX::Options and MooX::ConfigFromFile provide way more features and flexibility than either ◮ App::Cmd with Getopt::Long::Descriptive ◮ MooseX::App::Cmd along with corresponding MooseX wrappers around related stuff 2nd generation of modern OO in Perl5 App::Math::Tutor Allow parents help their children improving their mathematical skills Add support for exercise types as children require provide extensible design to allow easy augment of exercise Goal: Improve to Web-Service, eg. by mapping MooX::Cmd to URI path and MooX::Options to GET parameters Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 3 / 41
  • 3. Introduction Audience Audience Audience Developers who want to create or improve Perl5 software Developers who want to learn how to develop modern OO with Perl5 Developers who are interested in developing mathematical exercises Prerequisites of the Audience Following knowledge is expected: General knowledge about object oriented programming or concepts like ◮ classes ◮ objects ◮ polymorphism, inheritance and/or roles ◮ methods, class functions ◮ attributes, properties slightly above basic Perl experience ever heard of Smalltalk and its OO-concept is a strong bonus Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 4 / 41
  • 4. Modules Classes and Roles Classes in Moo classes can be instantiated one can inherit from classes one can aggregate classes distinguish naming conflicts is up to developer { package Natural; use Moo; sub _stringify { ... }; } { package Roman; use Moo; extends "Natural"; sub _stringify { ... }; } my $natnum = Natural ->new( value => 42 ); say $natnum ->_stringify (); # 42 my $romnum = Roman ->new( value => 42 ); say $romnum ->_stringify (); # XLII Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 6 / 41
  • 5. Modules Classes and Roles Roles in Moo roles describe a dedicated behavior (e.g. printable) roles can be composed into classes one can’t inherit from roles - only consume roles cannot exist stand-alone roles are consumed once naming conflicts cause compile time error { package Printable; use Moo:: Role; # now it’s a role - no ’is a’ relationship anymore sub print { my $self = shift; say $self ->_stringify } } { package Natural; use Moo; # class with "Printable"; # consumes a role sub _stringify { ... }; } my $natnum = Natural ->new( value => 42 ); $natnum ->print; # 42 my $romnum = Roman ->new( value => 42 ); $romnum ->print; # XLII Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 7 / 41
  • 6. Attributes Attributes in Moo Attributes in Moo package VulFrac; use Moo; has nume rator => ( is => "ro", required => 1 ); has denom inator => ( is => "ro", required => 1 ); 1; use ”has” keyword to define a attribute attributes ”numerator” and ”denominator” attributes are immutable and required Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 8 / 41
  • 7. Attributes Attribute Options Attribute options - Selection I is mandatory behavior description ro defines the attribute is read-only rw defined the attribute is read/writable lazy defines the attribute is read-only with a lazy initialization, implies builder => 1 required when set to a true value, attribute must be passed on instantiation init arg Takes the name of the key to look for at instantiation time of the object. A common use of this is to make an underscored attribute have a non-underscored initialization name. undef means that passing the value in on instantiation is ignored. isa defines a subroutine (coderef) which is called to validate values to set coerce defines a subroutine (coderef) which forces attribute values default subroutine (coderef) which is called to initialize an attribute Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 9 / 41
  • 8. Attributes Attribute Options Attribute options - Selection II Following options can benefit from attribute shortcuts: the value of 1 instead of a method name means to generate a coderef which calls the method ${option name} ${attr name} builder takes a method name (string) which is called to initialize an attribute (calls build ${attr name} on attribute shortcut) trigger takes a subroutine (coderef) which is called anytime the attribute is set (calls trigger ${attr name} on attribute shortcut) clearer takes a method name (string) which will clear the attribute (provides clear ${attr name} on attribute shortcut) predicate takes a method name (string) which will return true if an attribute has a value (provides has ${attr name} on attribute shortcut) Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 10 / 41
  • 9. Methods Method Examples Methods in Moo I package VulFrac; use Moo; use overload ’""’ => " _stringify", ’0+’ => "_numify", ’bool ’ => sub { 1 }, ’<=>’ => " _num_compare"; has numerator => ( is => "ro", required => 1 ); has denominator => ( is => "ro", required => 1, isa => sub { $_ [0] != 0 or die "Not != 0" }; sub _stringify { my $self = shift; return sprintf(" frac {%s}{%s}", $self ->numerator , $self -> denominator ); } sub _numify { $_[0]-> numerator / $_[0]-> denominator ; } ... Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 11 / 41
  • 10. Methods Method Examples Methods in Moo II package Rationale; use Moo; extends "VulFrac"; has digits => ( is => "ro", required => 1 ); sub _stringify { my $digits = $_[0]-> digits; sprintf("%.${digits}g", $_[0]-> _numify ); } nothing like MooseX::Declare - pure Perl5 keywords are enough for plain methods Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 12 / 41
  • 11. Methods Method Modifiers Method Modifiers Method modifiers are a convenient feature from the CLOS (Common Lisp Object System) world: before before method(s) => sub { ...} before is called before the method it is modifying. Its return value is totally ignored. after after method(s) => sub { ...} after is called after the method it is modifying. Its return value is totally ignored. around around method(s) => sub { ...} around is called instead of the method it is modifying. The method you’re overriding is passed as coderef in the first argument. - No support for super, override, inner or augment In doubt MooX::Override provides override and super while MooX::Augment provides augment and inner Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 13 / 41
  • 12. Methods Method Modifiers Method Modifiers - Advantages supersedes $self->SUPER::foo(@ ) syntax cleaner interface than SUPER allows multiple modifiers in single namespace also possible from within roles and not restricted to inheritance ensures that inherited methods invocation happens right (mostly - remember around) no need to change packages Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 14 / 41
  • 13. Methods Method Modifiers Methods Modifiers - around avoid calling $orig package App:: Math :: Tutor :: Role :: Roman; use Moo:: Role; with "App:: Math :: Tutor :: Role :: Natural"; { package RomanNum; use Moo; extends "NatNum"; # derives overloading ! sub _stringify { ... } } around " _guess_natural_number" => sub { my $orig = shift; my $max_val = $_[0]-> format; my $value = int( rand( $max_val - 1 ) ) + 1; return RomanNum ->new( value => $value ); }; captures control receives responsibility runtime of modified method completely eliminated Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 15 / 41
  • 14. Methods Method Modifiers Methods Modifiers - around modifying $orig return value package App:: Math :: Tutor :: Role :: Roman; use Moo:: Role; with "App:: Math :: Tutor :: Role :: Natural"; { package RomanNum; use Moo; extends "NatNum"; # derives overloading ! sub _stringify { ... } } around " _guess_natural_number" => sub { my $orig = shift; my $num = $orig ->(@_); return RomanNum ->new( value => $num ->value ); }; modifies only required part leaves most responsibility in modified method runtime of modified method added to this method’s runtime Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 16 / 41
  • 15. Structure Frontend Frontend (dictated by MooX::Cmd) App::Math::Tutor App::Math::Tutor::Cmd::VulFrac App::Math::Tutor::Cmd::VulFrac::Cmd::Add App::Math::Tutor::Cmd::VulFrac::Cmd::Mul App::Math::Tutor::Cmd::VulFrac::Cmd::Cast App::Math::Tutor::Cmd::Natural App::Math::Tutor::Cmd::Natural::Cmd::Add App::Math::Tutor::Cmd::Natural::Cmd::Mul App::Math::Tutor::Cmd::Roman App::Math::Tutor::Cmd::Roman::Cmd::Add App::Math::Tutor::Cmd::Roman::Cmd::Cast App::Math::Tutor::Cmd::Unit App::Math::Tutor::Cmd::Unit::Cmd::Add App::Math::Tutor::Cmd::Unit::Cmd::Mul App::Math::Tutor::Cmd::Unit::Cmd::Cast Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 18 / 41
  • 16. Structure CLI Concept Exercise Groups App::Math::Tutor::Cmd::VulFrac Exercises in vulgar fraction calculation App::Math::Tutor::Cmd::Natural Exercises in calculations using natural numbers App::Math::Tutor::Cmd::Roman Exercises in calculations using natural numbers, but show them using roman number encoding (exercises and solutions) App::Math::Tutor::Cmd::Unit Exercises in calculations using units (times, currency, . . . ) App::Math::Tutor::Cmd::Power Exercises in calculations of power mathematics App::Math::Tutor::Cmd::Polynom Exercises for polynomial mathematics (Zero of a function, Vertex, . . . ) Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 19 / 41
  • 17. Design Simple Exercise Typical Exercise design App::Math::Tutor::Cmd::VulFrac::Cmd::Add build exercise() : exercise App::Math::Tutor::Role::VulFracExercise format App::Math::Tutor::Role::VulFrac check vulgar fraction() : bool guess vulgar fraction() : VulFrac get vulgar fractions() : [ VulFrac ] VulFrac num denum stringify() : Str numify() : Num num compare() : Int euklid() : Int gcd() : Int reduce() : VulFrac reciprocal() : VulFrac App::Math::Tutor::Role::Exercise exercise : lazy # { section, caption, label, # header, challenges, solutions } output name : lazy template filename : lazy build exercise() = 0 : exercise build output name() : Str build template filename() = 0 : Str execute() Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 20 / 41
  • 18. Design Derived Exercise Derived Exercise design App::Math::Tutor::Cmd::Roman::Cmd::Add build exercise() : exercise App::Math::Tutor::Role::NaturalExercise format App::Math::Tutor::Role::Roman around => guess natural number() : Roman App::Math::Tutor::Role::Natural check natural number() : bool guess natural number() : Natural get natural number() : [ Natural ] RomanNum stringify() : Str Natural value stringify() : Str numify() : Num num compare() : Int App::Math::Tutor::Role::Exercise exercise : lazy # { section, caption, label, # header, challenges, solutions } output name : lazy template filename : lazy build exercise() = 0 : exercise build output name() : Str build template filename() = 0 : Str execute() Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 21 / 41
  • 19. Improvements Design Improving design introduce factories add lazy factory attribute (allowes overriding factory to use by around’ing builder) separate number classes (type system, but no MooseX::Types) approval for reasonable exercise value should be part of factory approval for valid number should be coerced (trigger?) Design history I started with just vulgar fraction exercises Design covered exactly those needs Design future Modern Perl-OO allowes easy refactoring to apply above improvements Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 22 / 41
  • 20. MooX General purpose eXtensions MooX in general Some Moo extensions for getting a picture - the list is neither complete nor is it intended to be MooX Distributions MooX::Log::Any logging role building a very lightweight wrapper to Log::Any MooX::Validate minimalist Data Validation for Moo MooX::Types::MooseLike Moose like types for Moo MooX::Override adds ”override method => sub . . . ” support to Moo MooX::Augment adds ”augment method => sub . . . ” support to Moo MooX::late easily translate Moose code to Moo MooX::PrivateAttributes create attribute only usable inside your package MooX::Singleton turn your Moo class into singleton MooX::Aliases easy aliasing of methods and attributes in Moo Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 24 / 41
  • 21. MooX CLI related eXtensions MooX Distributions for CLI MooX::Cmd giving an easy Moo style way to make command organized CLI apps support sub-commands with separated options when used together with MooX::Options MooX::Options explicit Options eXtension for Object Class no mess with composed attributes MooX::ConfigFromFile Moo eXtension for initializing objects from config file RC files with structures (JSON, INI, YAML, XML, ...) Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 25 / 41
  • 22. MooX CLI related eXtensions General CLI Construction Flow :main :MooX::Cmd :MooX::Options :MooX::ConfigFromFile :Moo new with cmd() buildcommand commands() splitargv new with options() parse options new() BUILDARGS() super->BUILDARGS() buildloaded config helpon exception execute Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 26 / 41
  • 23. Provided Framework Exercise Role package App:: Math :: Tutor :: Role :: Exercise; use strictures; # instead of strict + warnings use Moo:: Role; use MooX :: Options; option quantity => ( is => "ro", doc => "Specifies number of exercises to generate", long_doc => "Specify number of exercises to generate. " . "In case of several kind of ...", format => "i", short => "n", default => sub { 15 }, ); has output _name => ( is => "lazy" ); sub _build_output_name { join( "", map { $_ -> command_name || "" } @{ $_[0]-> command_chain } ); } being a role (no ”is a” relationship) and add CLI options capabilities defining an attribute which will be initialized by command line support MooX::Option’s --man usage feature attribute for output file to generate — lazy to allow provide individual name builder Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 28 / 41
  • 24. Provided Framework Exercise Role has exercises => ( is => "lazy" ); sub execute { my $exercises = $_[0]->exercises; my $ttcpath = File ::Spec ->catfile( File :: ShareDir :: dist_dir("App -Math -Tutor"), $_[0]-> template_filename . ".tt2" ); my $template = Template ->new( { ABSOLUTE => 1 }); my $rc = $template ->process( $ttcpath , { exercises => $exercises , output => { format => ’pdf’ }, }, $_[0]-> output_name . ’.pdf’); $rc or croak( $template ->error () ); return 0; } attribute containing the exercises definitions, exercises itself and their solutions (depending on template) — lazy implies requires ’’ build exercises’’ method to satisfy MooX::Cmd fetch exercises definition implies calling build exercises build full qualified path of template file name residing in app’s share directory, instantiate template processor and run it force output format ”pdf” (Template::LaTeX will be instructed by template) Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 29 / 41
  • 25. Provided Framework Vulgar Fraction Exercise Role package App:: Math :: Tutor :: Role ::Vul FracExercise; use strictures; use Moo:: Role; use MooX :: Options; with "App:: Math :: Tutor :: Role :: Exercise", "App:: Math :: Tutor :: Role :: VulFrac"; option format => ( is => "ro", doc => "specifies format of numerator/ denominator ", long_doc => "Allow specifying the format of the numerator/ denominator ...", isa => sub { defined( $_[0] ) and !ref $_[0] and $_ [0] !~ m ,^d?n+(?:/d?n+)?$, and die("Invalid format"); }, coerce => sub { ... my ( $fmta , $fmtb ) = ( $_[0] =~ m ,^(d?n+)(?:/(d?n+))?$, ); $fmtb //= $fmta; my $starta = "1"; my $startb = "1"; $fmta =~ s/^(d)(.*)/ $2/ and $starta = $1; $fmtb =~ s/^(d)(.*)/ $2/ and $startb = $1; [ $starta . "0" x length($fmta), $startb . "0" x length($fmtb) ] }, default => sub { return [ 100, 100 ]; }, format => "s", ); be a nice package ˆWrole, intending to provide command line options for instantiation compose role behavior using Exercise and VulFrac define option coercing option string into array ensuring the array ref as value Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 30 / 41
  • 26. Create Exercise Preamble package App:: Math :: Tutor :: Cmd:: VulFrac ::Cmd :: Add; use strictures; use Moo; use MooX :: Cmd; use MooX :: Options; has template_filename => ( is => "ro", default => "twocols"); with "App:: Math :: Tutor :: Role :: VulFracExercise "; $ mtut vulfrac add we’re of course a nice class satisfy requirement of Exercise role: provide template filename – two column template (for addition and substraction) compose role ...VulFracExercise Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 31 / 41
  • 27. Create Exercise Create Exercise Numbers sub _build_exercises { my ($self) = @_; my (@tasks ); foreach my $i ( 1 .. $self ->amount ) { my @line; for ( 0 .. 1 ) { # 0: +, 1: - my ( $a , $b ) = $self -> get_vulgar_fractions (2); push @line , [ $a , $b ]; } push @tasks , @line; } my $exercises = ...; return $exercises; } exercise builder has to be provided by individual exercise hold tasks of the exercise sheet how many tasks per sheet? (remember the option in ...Role::Exercise) a ”+” and a ”-” exercise per line invoke factory per task safe each line for processing Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 32 / 41
  • 28. Create Exercise Format Challenge / Solution my $exercises = { section => "Vulgar fraction addition / subtraction ", caption => ’Fractions ’, label => ’vulgar_fractions_addition ’, header => [ [ ’Vulgar Fraction Addition ’, ’Vulgar Fraction Su challenges => [], solutions => [], }; foreach my $line (@tasks) { my ( @solution , @challenge ); foreach my $i ( 0 .. 1 ) { my ( $a , $b , @way ) = @{ $line ->[$i] }; my $op = $i ? ’-’ : ’+’; $op eq ’-’ and $a < $b and ( $b , $a ) = ( $a , $b ); push @challenge , sprintf( ’$ %s %s %s = $’, $a , $op , $b ); push @way , sprintf( ’%s %s %s’, $a , $op , $b ); ... } push( @{ $exercises ->{ challenges} }, @challenge ); push( @{ $exercises ->{ solutions} }, @solution ); } create exercise structure containing challenges and solutions loop over created tasks and exercises per line format challenge using operator ’""’ of VulFrac objects same (but different) opening ”way” and remember the little thingies . . . Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 33 / 41
  • 29. Create Exercise Format Solutions sub _build_exercises { ( $a , $b ) = ( $a ->_reduce , $b = $b ->_reduce ); push @way , sprintf( ’%s %s %s’, $a , $op , $b ) if ( $a ->num != $line ->[$i]->[0]->num or $b ->num != ... ); my $gcd = VulFrac ->new( num => $a ->denum , denum => $b ->denum )->_gcd; my ( $fa , $fb ) = ( $b ->{ denum} / $gcd , $a ->{ denum} / $gcd ); push @way , sprintf( ’frac {%d cdot %d}{%d cdot %d} %s ...’, $a ->num , $fa , $a ->denum , $fa , $op , $b ->num , $fb , ... ); push @way , sprintf( ’frac {%d}{%d} %s frac {%d}{%d}’, $a ->num*$fa , $a ->denum*$fa , $op , $b ->num*$fb , $b ->denum*$fb ); push @way , sprintf( ’frac {%d %s %d}{%d}’, $a ->num * $fa , $op , $b ->num * $fb , $a ->denum * $fa ); my $s = VulFrac ->new( denum => $a ->denum * $fa , num => $i ? $a ->num * $fa - $b ->num * $fb : ...s/ -/+/); push @way , "" . $s; my $c = $s ->_reduce; $c ->num != $s ->num and push @way , " $c ->num > $c ->denum and $c ->denum > 1 and push @way , $c ->_stringify(1); push( @solution , ’$ ’ . join( " = ", @way ) . ’ $’ ); } try to reduce operands and add them to opening when successful World of Handcraft: show calculation method by determine geatest common divisor of operands denominator, format subsequent steps to reach the solution remark possible reducing, mixed fraction, cord it and go ahead Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 34 / 41
  • 30. Created Exercise Output Challenges Vulgar Fraction Addition Vulgar Fraction Subtraction 99 67 + 43 84 = 45 41 − 32 48 = 19 7 + 16 54 = 51 47 − 49 65 = 38 82 + 38 99 = 56 33 − 30 32 = 96 80 + 46 39 = 49 79 − 29 82 = 72 68 + 46 99 = 42 49 − 38 59 = Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 35 / 41
  • 31. Created Exercise Output Solutions Vulgar Fraction Addition Vulgar Fraction Subtraction 99 67 + 43 84 = 99·84 67·84 + 43·67 84·67 = 8316 5628 + 2881 5628 = 8316+2881 5628 = 11197 5628 = 15569 5628 45 41 − 32 48 = 45 41 − 2 3 = 45·3 41·3 − 2·41 3·41 = 135 123 − 82 123 = 135−82 123 = 53 123 19 7 + 16 54 = 19 7 + 8 27 = 19·27 7·27 + 8·7 27·7 = 513 189 + 56 189 = 513+56 189 = 569 189 = 3 2 189 51 47 − 49 65 = 51 47 − 49 65 = 51·65 47·65 − 49·47 65·47 = 3315 3055 − 2303 3055 = 3315−2303 3055 = 1012 3055 38 82 + 38 99 = 19 41 + 38 99 = 19·99 41·99 + 38·41 99·41 = 1881 4059 + 1558 4059 = 1881+1558 4059 = 3439 4059 56 33 − 30 32 = 56 33 − 15 16 = 56·16 33·16 − 15·33 16·33 = 896 528 − 495 528 = 896−495 528 = 401 528 96 80 + 46 39 = 6 5 + 46 39 = 6·39 5·39 + 46·5 39·5 = 234 195 + 230 195 = 234+230 195 = 464 195 = 2 74 195 49 79 − 29 82 = 49·82 79·82 − 29·79 82·79 = 4018 6478 − 2291 6478 = 4018−2291 6478 = 1727 6478 72 68 + 46 99 = 18 17 + 46 99 = 18·99 17·99 + 46·17 99·17 = 1782 1683 + 782 1683 = 1782+782 1683 = 2564 1683 = 1 881 1683 42 49 − 38 59 = 6 7 − 38 59 = 6·59 7·59 − 38·7 59·7 = 354 413 − 266 413 = 354−266 413 = 88 413 Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 36 / 41
  • 32. Conclusion Conclusion lazy attributes allow designing a multi-stage initialization phase benefit of common runtime (faster load) when using ◮ DBIx::Class ◮ Web::Simple (Jedi) improve design by ◮ using roles for behavioral design (avoid duck typing) ◮ using explicit patterns for clear separation of concerns ◮ express intensions clearer for method overloading by using method modifiers Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 38 / 41
  • 34. Resources Thank you Thank You For Contributing Graham ”haarg” Knop Found a lot of spelling errors and first suggestions Vincent ”celogeek” Bachelier Suggested some real examples Fedor Babkin UML diagram improvements Curtis ”Ovid” Poe Final review and figured out missing fundamentals Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 40 / 41
  • 35. Resources Thank you Thank You For Listening Questions? Jens Rehsack <rehsack@cpan.org> Jens Rehsack (Niederrhein.PM) Moo in practice - App::Math::Tutor 2014-2015 41 / 41