This is an expanded version of my "Refactoring with Roles" talk. People don't ask me how to use roles. They're easy to use. They ask me why to use roles. That's pretty easy to, so long as you understand what's wrong with inheritance. This talk covers that.
A paper for this talk is at http://www.slideshare.net/Ovid/inheritance-versus-roles-1799996
Axa Assurance Maroc - Insurer Innovation Award 2024
Inheritance Versus Roles
1. OO Systems and Roles
Curtis “Ovid” Poe
Senior Software Engineer
Copyright 2009 by Curtis “Ovid” Poe.
This presentation is free and you may redistribute it and/or
modify it under the terms of the GNU Free Documentation
License.
Template Copyright 2009 by BBC.
Future Media & Technology BBC MMIX
2. Not a Tutorial
• #ovidfail
• “How” is easy
• “Why” is not
Future Media & Technology BBC MMIX
3. The Problem Domain
• 5,613 Brands
• 6,755 Series
• 386,943 Episodes
• 394,540 Versions
• 1,106,246 Broadcasts
• 1,701,309 On Demands
July 2, 2009
Future Media & Technology BBC MMIX
4. A Brief History of Pain
•Simula 67
–Classes
–Polymorphism
–Encapsulation
–Inheritance
Future Media & Technology BBC MMIX
11. A Closer Look
• Multiple Inheritance
Future Media & Technology BBC MMIX
12. B::PVIV Pseudo-Code
• B::PVIV Internals
bless => {
pv => 'three',
iv => 3,
} => 'B::PVIV';
Future Media & Technology BBC MMIX
13. Printing Numbers?
• Perl
my $number = 3;
$number += 2;
print "I have $number apples";
• Java
int number = 3;
number += 2;
System.out.println(
"I have " + number + " apples"
);
Future Media & Technology BBC MMIX
14. Class Details
• More pseudo-code
package B::PVIV;
use parent qw( B::PV B::IV );
sub B::PV::as_string { $_[0]->{pv} }
sub B::IV::as_string { $_[0]->{iv} }
• Printing:
print $pviv->as_string; # Str
print $pviv->B::IV::as_string; # Int
Future Media & Technology BBC MMIX
26. Shared Behavior
Method Description
✓ Bomb::fuse() Deterministic
Spouse::fuse() Non-deterministic
Bomb::explode() Lethal
✓ Spouse::explode() Wish it was lethal
Future Media & Technology BBC MMIX
27. Ruby Mixins
module Bomb
def explode
puts "Bomb explode"
end
def fuse
puts "Bomb fuse"
end
end
module Spouse
def explode
puts "Spouse explode"
end
def fuse
puts "Spouse fuse"
end
end
Future Media & Technology BBC MMIX
28. Ruby Mixins
class PracticalJoke
include Spouse
include Bomb
end
joke = PracticalJoke.new()
joke.fuse
joke.explode
Prints out:
Future Media & Technology BBC MMIX
29. Ruby Mixins
class PracticalJoke
include Spouse
include Bomb
end
joke = PracticalJoke.new()
joke.fuse
joke.explode
Prints out:
Bomb fuse
Bomb explode
Future Media & Technology BBC MMIX
30. Moose Roles
{
package Bomb;
use Moose::Role;
sub fuse { say "Bomb explode" }
sub explode { say "Bomb fuse" }
}
{
package Spouse;
use Moose::Role;
sub fuse { say "Spouse explode" }
sub explode { say "Spouse fuse" }
}
Future Media & Technology BBC MMIX
31. Moose Roles
{
package PracticalJoke;
use Moose;
with qw(Bomb Spouse);
}
my $joke = PracticalJoke->new();
$joke->fuse();
$joke->explode();
Prints out:
Future Media & Technology BBC MMIX
32. Moose Roles
{
package PracticalJoke;
use Moose;
with qw(Bomb Spouse);
}
my $joke = PracticalJoke->new();
$joke->fuse();
$joke->explode();
Prints out:
Due to a method name conflict in roles 'Bomb' and
'Spouse', the method 'fuse' must be implemented
or excluded by 'PracticalJoke'
Future Media & Technology BBC MMIX
33. Moose Roles
{
package PracticalJoke;
use Moose;
with 'Bomb' => { excludes => 'explode' },
'Spouse' => { excludes => 'fuse' };
}
my $joke = PracticalJoke->new();
$joke->fuse();
$joke->explode();
Prints out:
Spouse fuse
Bomb explode
Future Media & Technology BBC MMIX
34. Moose Roles
package PracticalJoke;
use Moose;
with 'Bomb' => { excludes => 'explode' },
'Spouse' => { excludes => 'fuse',
alias =>
{ fuse => 'random_fuse' }
};
And in your actual code:
$joke->fuse(14); # timed fuse
# or
$joke->random_fuse(); # who knows?
Future Media & Technology BBC MMIX
35. Role Example
package Does::Serialize::YAML
use Moose::Role;
use YAML::Syck;
requires 'as_hash';
sub serialize {
my $self = shift;
return Dump($self->as_hash);
}
1;
And in your actual code:
package My::Object;
use Moose;
with 'Does::Serialize::YAML';
Future Media & Technology BBC MMIX
41. Work + Roles
package BBC::Programme::Episode;
use Moose;
extends 'BBC::ResultSet';
with qw(
DoesSearch::Broadcasts
DoesSearch::Tags
DoesSearch::Titles
DoesSearch::Promotions
DoesIdentifier::Universal
);
Future Media & Technology BBC MMIX