You are on page 1of 67

Designing and Programming

with Personalities

Luis Blando
lblando@gte.com
Copyright 1998

Outline

Modeling behavior
Personalities
Dynamic Personalities
Synergy with Frameworks
Personalities/J language
Q&A
2

Modeling Behavior - Outline

The functional nature of software systems


Functional decomposition and Structured
Programming
Data Decomposition and Object Oriented
Programming
Finding objects and behavior
When behavior misbehaves
Popular functions and their mapping
3

The functional nature


of software systems
a well-organized software system may
be viewed as an operational model of
some aspect of the world. Operational
because it is used to generate practical
results and sometimes to feed these
results back into the world; model
because any useful system must be
based on a certain interpretation of
some world phenomenon. Bertrand Meyer, 4

Functional Decomposition and


Smaller scope
Bigger scope
Structured Programming
rtt_init()
it! r?
rtt_newpack()
a
W a lle
c
rtt_start()
h
c
?
i
n
h
e
h
W rtt_stop()
w
d
An
rtt_timeout()
/* can be set nonzero by caller */
int rtt_d_flag = 0;
...
rtt_init(rtt_struct *ptr) {...}
rtt_newpack(rtt_struct *ptr) {...}
rtt_start(rtt_struct *ptr) {...}
rtt_stop(rtt_struct *ptr) {...}
rtt_timeout(rtt_struct *ptr) {...}
...

What if in here
I mess with
rtt_info?

dgsendrecv()

struct rtt_struct rtt_info;


...
dgsendrecv(...) {
...
rtt_init( &rtt_info );
rtt_newpack( &rtt_info );
...
}
...

Excerpts extracted from: UNIX Network Programming, Richard Stevens, 1990, pp.406-414

Data Decomposition and


Object Oriented Programming

This used to
be rtt_struct

These are the


accessors to
regulate
object state
changes !

RTT
float rtt_rtt;
float rtt_srtt;
float rtt_rttdev;
short rtt_nrexmt;
short rtt_currto;
short rtt_nxtrto;
int rtt_d_flag;
+
+
+
+
+
+
+

rtt_init()
rtt_newpack()
rtt_start()
rtt_stop()
rtt_timeout()
setX()
getX()

ReliableDGRAM
int rttfirst;
int tout_flag;
RTT myrtt;
+ sendrecv(){
myrtt.setX();
myrtt.init();
...
}

Weve encapsulated
data and functions
together. The users
keep an instance of
both

Finding Objects and Behavior - 1


This is why object-oriented designers usually
do not spend their time in academic
discussions of methods to find the objects: in
the physical or abstract reality being modeled,
the objects are just there for the picking.
Bertrand Meyer, Object-Oriented Software
The
objects operations come naturally
Construction, 1988.

when

we consider and objects interface. The


operations can also be identified directly from
the application, when we consider what can be
done
with
the items
Ivar Jacobson et.
What
actions
must we
getmodel.
accomplished,
and
al., Object-Oriented Software Engineering, 1992.

which object will accomplish them, are


questions that we must answer right at the
start. Rebecca Wirfs-Brock et.al., Designing Object-

Finding Objects and Behavior - 2


normal behavior

(one-domain, accessors)

When in doubt
Follow the data!
(anonymous :)

CRC, use-cases

The 3 amigos

intrinsic behavior.
Harrison & Ossher, SubjectOriented Programming,
1993
Wait a minute!
I know, lets just
Whats normal for me
concentrate on the basic
might not be so
behavior only for now...
for Grady or James!
8

When Behavior Misbehaves - 1


Mammal

Lion

Animal

Oviparous

Use their reproductive


What about using
really
behavior, ofNonsense!
course! Whatstheir
eating habits?
important is their
intelligence!

Veterinary

Trainer

Feeder

ZooSys

The name of a class


should reflect its
intrinsic nature and not
a role that it plays in an
association. James
9
Rumbaugh et.al. Object-

When Behavior Misbehaves - 2


The intrinsic stuff
is easy to do! :-)

The vets got


their way

But what about the trainers and


the feeders ???

10

When Behavior Misbehaves - 3

A possible Trainer requirement


Hey! Im sure I can find some
The show shall start with the pink pelicans and the
commonality in all these functions!
flying across the stage. They are to land at one end
After all, how many ways can you
then walk towards a small door on the side. At the s
actually walk!
killer whale should swim in circles and jump just as t
by. After the jump, the sea lion should swim past the
out of the pool, and walk towards the center stage w
announcer is waiting for him.

11

Popular Functions
The popular functions in ZooSys
Fly() popular function

Fly

Takeoff
Ascend
ThereYet
FlapTowards
Descend
Land

// (x,y)
is the target landing spot
JumpInTheWater
void Fly(intSubmerge
x, int y, int altitude) {
MoveFin
Swim
resetMetersFlown();
Rise
Encapsulate
Takeoff();
JumpOutOfTheWater
this sequence.
Prepare
for (int a=0; a < altitude; a++) Ascend();
MoveFoot
Always the
Walk
while( !ThereYet(x, y) ) FlapTowards(x,
y);
Stabilize
same for any
for(int a=altitude; a > 0; a--) Descend();
AtEase
class...
Land();
CheckDistance
}
SprintTo
LiftOff
Land

Jump

and their sub-functions

12

Mapping Popular Functions

Swim()

Fly()

Walk()

13

Alternatives for Mapping

Pushing functions up the hierarchy


Design errors

Duplicate function implementation


Maintenance nightmare

Multiple inheritance
Ambiguous/not understood
Not supported by some languages
Roles are unconstrained (I.e. are full-fledged
classes)

14

Personalities - Outline

Designing with roles


Personalities
Concept, Architecture, Components,
Syntax, Usage

The law of personalities

15

The show shall start with the pink pelicans and the Af
flying across the stage. They are to land at one end of
then walk towards a small door on the side. At the sam
killer whale should swim in circles and jump just as th
by. After the jump, the sea lion should swim past the w
Eureka!
outofSome
the Remember
pool,
and this
walk
requirements
towards thestatement?
center
stage whe
OOA/D
methodologies
are
Maybe Flier is
announcer
is
waiting
for
him.
conducive to the discovery
ofofroles
a role of a lot
Wirfs-Brock et. al. animals here?

Designing with Roles

Andersen et. al.

The show shall start with every flying animal in


ourzoo
flyingare
across
the stage. They
areby
to land at
Roles
nevertheless
found
one end
of the arena
then walk
towards
inspecting
theand
dynamic
views
of a a small
door
on the
side.
At the same
time, a killer whale
It
couldve
been
something
like
this...
sufficiently
complex
system.
should
swim in circles
and jump
just as the birds fly
by. After the jump, the sea lion should swim past
the whale, jump out of the pool, and walk towards
the center stage where the announcer is waiting 16

Personality - Concept

Encapsulate popular functions independent


of any specific class hierarchy
Template Method Pattern++
micro-framework

Not abstract classes


Embody one, and only one role

Not interfaces (a-la Java)


More constrained
Contain behavior implementation

17

Personality - Architecture
Users of the object only
deal with the Personalitys
Upstream Interface

The role behavior is


encapsulated here...
and defined in terms
of the Downstream
Interface, which classes
in the hierarchy must
implement.

r)
e
n
i
a
(Tr

r
e
i
l
(F

n
a
c
i
(Pel

18

Personality - Components

Upstream interface
popular functions go here

Downstream interface
functions to be implemented by personifying class

Private functions
no visibility either upstream or downstream

Role-specific attributes
to keep the roles state

Constructor
to initialize the role-specific attributes

19

Personality - Definition Syntax


// Flier.pj
personality Flier {
// upstream interface. Must implement here.
public
void Fly(int x, int y, int altitude) {
resetMetersFlown();
Takeoff();
for (int a=0; a < altitude; a++) Ascend();
while( !ThereYet(x, y) ) FlapTowards(x, y);
for(a = altitude; a > 0; a--) Descend();
Land();
}
// downstream interface. Dont impl here.
di void Takeoff();
di void Ascend();
di boolean ThereYet(int x, int y);
di void FlapTowards(int x, int y);
di void Descend();
di void Land();
// private functions. Must implement here.
private void resetMetersFlown() { meters_flown = 0; }
// attributes (specific to the role)
private float meters_flown;
// constructor (optional)
Flier() { resetMetersFlown(); }
}

tic
c
a
t
Sy n
r
a
g
u
S

Each method in the


UI is declared and
defined.
Each method in the
DI is declared but
not defined.

Constructor

Private aux.
functions and
attributes.
20

Personality - Usage Syntax


// Bat.pj
public class Bat extends Mammal personifies Flier
{
// intrinsic properties and methods of the Bat class
boolean inDraculaMode;
void UpdateMode(Time time) {
if (time > SUNLIGHTOUT) inDraculaMode = true;
else
inDraculaMode = false;
}
Bat() { inDraculaMode = false; }
Boolean BiteBeautifulLady(Lady lady) {
if ( inDraculaMode ) lady.BittenBy( this );
return inDraculaMode;
}
// since a Bat flies, use the Flier personality with
// the following implementations of the DI
Compass _compass = new Compass();
void waitUntilInDracula() {
// sleep until
while( !inDraculaMode ) {
// we can go to
UpdateMode( new Date() );
// Dracula mode
Thread.sleep( 5000 );
// since thats
}
// when we fly.
}
void Takeoff() { waitUntilInDracula(); }
void Ascend() { /* not shown */ }
boolean ThereYet(int x, int y) {
return _compass.where().x() == x &&
_compass.where().y() == y;
}
void FlapTowards(int x, int y) {
if ( _compass.unitialized() )
_compass.set_target(x, y);
// do whatever I need to move...
_compass.updateposition();
}
void Descend() { /* not shown */ }
void Land() { /* not shown */ }
}

Declare intent...

Implementation
of the Bat class.
Nothing to do
with the Flier
personality here...

The Bat class


implements the DI
of the Flier
personality
21

Law of Personalities Hooray!


(LoP) - 1

No default implementation
only abstract functions in DI

Basic types

Karl

only language-defined types allowed in method signatures

ed
t
o
m
e
Behavioral buffer ate, we d
to
b

e
n
d
o
i
e
t
users of
m communicate
the
only
dathrough UI
n
soobject
e
r
m
e
t
m
f
A
ut
eco
b
r
(

d
o
e
t
t
ra
s.
Fixed
behavior
one
g
e
i
e
t
t
i
l
n
i
a
this popular
on
re functions) ispefinal
s
o
r
m
r
implementation
o
of
popular
allow f y deployable
sil
a
e
Implementation
separation
s
s
le

popular functions implementation can only use DI to talk to the personifying


class

Luis

22

LoP - No default implementation

Default implementation does not make


// compute and return todays date
sense
Easy to check s

e
k
a
m
String
Today();
nt
automatically
e
since we can use personality
m
in
many
m
co
he
t
l
l
n
a
i
m
his s ifference
different domains!
T
VS.
e d
h
t
l
l
a
Expected semantics rof
! must be clear
DI
d
l
o
w
// compute and return todays date
so
the behavior
of the Cant
personalitys
check
// that
in the
format YYYYMMDD
popular
guaranteed
automatically!
String functions
Today();is somewhat

23

LoP - Basic Types (recommendation)


s
y
a
w
l
personality Foo {
o a
t
o
o
F
th
i
s
w
e
c
No user-defined typesfin
d
r
o the signatures
of
l o ye
p
...
e
This
d
be
o
t
e
either DI or UI methods
!
av
s
h
s
a
l
// return today
te C
a
D
y
M
using only language-defined
types guarantees
MyDateClass
Today();
Easy
to
check automatically.
deployability
everywhere
since its a
However, its tooHowever,
constraining
recommendation,
Personalities/J
VS.
too many translations
basic syntax
types when
has a switchto/from
for strong
deploying
a component
(a-la ANSI C) :-)
// return
today
thus,
java.util.Date
Today(); required only
recommended everywhere,
...deployment boundaries
at the
}
24

LoP - Behavioral Buffer


// SeaWorldShow() is a client

Clients
call UI
methods
// ofonly
Swimmer
personality
Design
reuse at the personality
void SeaWorldShow(Swimmer
s) level
{
the popular
functions
are
totally
s.Swim(10,10);
ok,
UI defined
used
Easy//
to check

automatically.
s.Submerge();
//
error,
Semantic
guarantees
(sort
of)

DI used

} popular functions are final, (though


the
based on the DI implementations)

25

LoP - Fixed Popular Behavior


// LazyPelican.pj
class
LazyPelican extends Oviparous
Popular
functions
implementations are
personifies Flier
{ final
...implementation of downstream interface
we
//
shouldnt
redefine
help
provide
someFly(...)!
kind of semantic
Easy
to check
public void Fly(int x, int
y, int
altitude) {
guarantee
to
users
of
the
personality
Takeoff();
automatically.
a =the
0; apersonality
< altitude/2;narrow
a++) Ascend();
for(int
it keeps
while( !ThereYet(x, y) ) FlapTowards(x, y);
ng
i
Subfunctions
for(int a = altitude
a > 0; a++)
Descend();
o
g
are; easier
to
implement
s
i
n
a
to
c
i
l
Land();
s
e
n
P
e
y
p
z
ap smaller
h
t
} since theirTscope
hopefully
a
his La is
ie r
h
l
F
W
!
e
sh
th
a
}
f
r
o
c
o
ts

t
en
i
l
c
e
all th lity now?
a
n
o
s
r
pe

26

LoP - Implementation Separation

Popular functions implementation can


only use DI methods to access the
personifying class
helps make sure that the DI is complete for the intended
semantics of the personality
keeps the personality encapsulated

However, requiring behavior impedance


is too constraining
that is, pass-through UI methods are sometimes needed (and
healthy)

27

I can talk to the


animals as Mammal
and Oviparous.

Keeping everybody happy


Vets

And to me they are just


Fliers, Swimmers,
Walkers, and Jumpers!
(personifies relationship)
Trainers
28

Dynamic Personalities

Why bother?
Workarounds for object migration

Shortcomings of static personalities


What wed like
Partially-dynamic personalities (a.k.a.
indecisive personalities)
Fully-dynamic personalities
29

But wait!
Whats wrong here???

MedSys {
addPatient(Person p) {}
doSomething() {
if (p.age() > 80)
}
}

Why Bother with DynPers?

Roles are very much dynamic


Object migration problem
Person john = new Person();
Medsys.addPatient(john);
// john joins a company. Need
// to use the Employee
// interface, but:
john.yellToBoss(); // => undef!
// so we need to do:
Employee tmp = new Employee();
// copy all the state from john to tmp
// and get rid of john
delete john;
tmp.yellToBoss(); // now it works

30

Workarounds for the Object


Migration problem

Using personalities (even the static version)


Reclassification
helps,
since:
need to update every single client that is using the old
instance
// Person
will (someday) be Employee and,
//
with any luck, also a Manager
class Person personifies Employee, Manager
... counterintuitive since john is one entity
Person
john = state
new when
Person();
duplicated
overlapping semantics
not the same object instance for all clients (typing)
Whoever
has
the john
instance,
problem
of triggering
state changes
up can still use

Delegation

methods from Manager and/or Employees


upstream interface without any reclassification!
31

Shortcomings
of static
class Person
personifies Employee, Manager
Personalities

need tohere,
know at class-creation
If However,
you forgetyou
something
time,
all to
therecompile
personalities
you might need in
youll
have
your class
andthe
refresh
futurethe instances later!

tough to do

But wait! John


And,
theres no way
access
to
// personality
code for controlling
is still not even an
class
Person
the personalities for a class Employee, much
personifies Employee, Manager
similar to always instantiating aless
Manager
object if
a Manager!
using
inheritance
//
client
code
Person john = new Person();
No
common protocol among personalities
((Manager)john).yellToBoss();

32

What We Would Like

Runtime personality attachment and


detachment
Preservation of object identity
Preservation of typing properties
Common interface for all personalities
Ubiquitous personification
Reasonable performance
33

Runtime attachment and


detachment of personalities
(client acting as third party)

Indecisive Personalities - 1

// client code (acts as third party)


Person john = new Person();
// born
personifies
semantics change to mean
...
john.personify( Employee ); // hired
can
instead of does
...
john.personify(
Manager
);
// promoted
Third-party
instructs
the
class
to
activate
...
and
deactivate
the personality
john.forget(
Manager
);
// fired
Employee
john.forget(
security concerns
are ignored );

Still need to declare all potential


// class Person definition
personalities
class Person at class-creation time
personifies Employee, Manager {...}
Very fast implementation

Still need to declare all potential personalities...

34

Indecisive Personalities -2
Report Card

Runtime attachment and detachment


Preservation of object identity

Hey!
Preservation of Typing properties
Five out
Common interface among personalities
of Six isnt
Reasonable performance
that
bad!
Ubiquitous personification
same framework as static personalities

compile-time strong typing


possibility of non-active personality must be recognized by client program

personify(), forget(), personifies() etc.

35

Fully Dynamic Personalities - 1

Ubiquitous personification
no need to declare the personalities at
class-creation time
any personality can (potentially) be
attached to any class
must redesign the method dispatch system
in the runtime environment

36

// class Pelican definition - FDP


class Pelican
// personifies Flier, Walker {...}
// the above line is no longer needed!

Fully Dynamic Personalities - 2


Method Dispatch

// client code - FDP


Class is
unaware
of
the
personality
it
Pelican toto = new Pelican();
might get
attached new Flier(), ...);
toto.personify(

((Flier)toto).Fly(10,10,10);
i.e. class
Pelican does not know that a Fly() request will
come its way in the future!
In the clients code, we still want to be able to do typing based
// class Pelican
definition
- FDP
- AFTER
on the personalitys
upstream
interface
class Pelican implements Personable {
Mimic method dispatch
by lifting all
void
CATCHALL(Personality
p,
String
...) {...}
functions
as name,
parameters
to a meta

// client
code -function
FDP - AFTER
dispatch
Pelican toto = new Pelican();
need to add new
moreFlier(),
plumbing to ...);
make it work
toto.personify(
((Personable)toto).
CATCHALL(toto.getPers(Flier),Fly,10,10,10);

37

Pelican.Takeoff()
Pelican.Descend()
Pelican.Ascend()
Pelican.Land()
...

Fully Dynamic Personalities


-3

Class Conformance to DI

Pelican toto = new Pelican();


toto.personify( new Flier() );

Pelican
toto =atnew
Pelican();
Must be
checked
attachment-time
// Pelican.myTakeoff, Pelican.myAscend
Implicit// but the rest share the same signature

PersAttachMap map = new PersAttachMap();


identical
method signatures
map.addPair(
Takeoff, myTakeoff );
map.addPair( Ascend, myAscend );
toto.personify( new Flier(), map );

Explicit

specified in a correspondence table

Dispatch of DI from UI implementation


same CATCHALL trick can be used
38

Fully Dynamic Personalities -3


Report Card

Runtime attachment and detachment


Preservation of object identity

Nice. Though
Preservation
of Typing properties
performance
might
become
Common
interface among
personalities
an issue.
Reasonable performance
(hmmm)
same framework as static personalities

compile-time strong typing (on the PJ code itself)


possibility of non-active personality must be recognized by client program

personify(), forget(), personifies() etc.

Ubiquitous personification

39

Personalities/J - Outline

The environment and assumptions


Knowing and unknowing clients
The mapping process
Static PJ
Indecisive PJ

40

Environment and Assumptions

The system is built using PJ alone


Java is only an intermediary step
Semantic analysis is done on the PJ
code
type checking

41

void main() {
// ... taken from Zoo.pj [static] in Appendix-A
// ... knowing client sets up its data structs.
Vector all_swimmers = new Vector();

Knowing and Unknowing Clients


...

// ... classes are created. This knowing client


// ... knows how to classify them. Notice how it
// ... puts the object into the appropriate vector
// ... depending on whether it personifies Swimmer,
// ... Flier, Jumper, or Walker
SeaLion toto
= new SeaLion();
toto.setName("Toto");
all_swimmers.addElement( toto ); // personifies Swimmer
all_walkers.addElement( toto ); // personifies Walker
all_jumpers.addElement( toto ); // personifies Jumper

Knowing and unknowing clients


know the class and its personalities
or...only designed to interface with one
// ... when this clients needs to do work, however,
personality
// ... it delegates to other functions (potentially

// ... entire systems that are built only to the


// ... personality interface. For instance, it delegates
// ... to PoolShow(), but notice how it casts the object
// ... first
for(int i=0; i < all_swimmers.size(); i++)
PoolShow ( (Swimmer)all_swimmers.elementAt(i) );

Using a class that personifies something


cast + call UI (knowing client)
call
...
UI (unknowing client)

}
// ... this unknowing client knows only about
// ... the personality it cares about.
static void PoolShow(Swimmer swimmer) {
System.out.println(" PoolShow with " + swimmer);
swimmer.Swim( 1, 1 ); // and uses its UI
}

42

The Mapping Process (to Java)


Flier.java
Flier.pj
personality
Flier { ... }

interface Flier
{ ... }
Flier$Ego.java
class Flier$Ego
{ ... }

Bat.pj
class Bat
personifies Flier
{ ... }
Zoo.pj
class Zoo
{ ... // uses }

Bat.java
class Bat
implements Flier
{ ... }
Zoo.java
class Zoo
{ ... // uses }

43

Static PJ - class.java

personifies becomes implement


// SeaLion.java [static]
All the methods from
import java.util.*;
<<class>>.java
public class SeaLion extends
Mammal are copied as-is
implement Walker,Jumper,Swimmer
{

erCopy intact from SeaLion.pj ...


...
p
o
g
E
============== for Swimmer
One $ lit//
.
y
a Swimmer$Ego $swimmer=new Swimmer$Ego(); t the
n
o
s
r
pe
tha
o
s
de
o
d
public void Swim(int miles, int
depth)
c
e
s
I
s
U
Pa
s

y
t
i
l
{ $swimmer.Swim(this, miles, depth);
}
ct
na
o
e
j
s
r
b
e
o
e
h
// ============== for Walkerp
t
l
l
a
can c r the DI
Walker$Ego $walker = new Walker$Ego();
fo
k
c
n!
a
o
public void Walk(int distance)
i
b
t
a
t
en
m
e
l
{ $walker.Walk(this, distance);
}
p
im
// ============== for Jumper
Jumper$Ego $jumper = new Jumper$Ego();
public void Jump(int x, int y, int alt)
{ $jumper.Jump(this, x, y, alt); }

44

Static PJ - personality.java
personality becomes interface

// Swimmer.java [static]
interface Swimmer
{
public void Swim(int miles, int depth);
void JumpInTheWater();
void Submerge();
Got rid of the UI
void MoveFin();
implementation.
void Rise();
void JumpOutOfTheWater();
}
and also all the di
keywords
45

Static PJ - pers$Ego.javaface as

er
t
n
i
e
alls
e th
c
he
s
t
t
U
i
f
o
w
o Swimmer$Ego.java [static]
h//
pe
y
s
i
t
s
e
i
th
Th
.
e
r
public
class
Swimmer$Ego
h
e
t
t
e
o
t
param
back f{ying class
ni public void Swim(Swimmer host,
o
s
r
e
p
int miles, int depth) {
host.JumpInTheWater();
for (int d = 0; d < depth; d++)
host.Submerge();
while ((miles--) > 0) host.MoveFin();
for(int d = depth; d > 0; d--)
host.Rise();
host.JumpOutOfTheWater();

}
public Swimmer$Ego()
{ }
}

46

Static PJ - UI Call Sequence

47

Dynamic PJ - Common Protocol


personify( <personality> )

Enable personification of <personality>

forget( <personality> )

Disable personification of <personality>

personifies( <personality> )

Returns true or false depending on


whether <personality> is enabled in the
class.
Returns a Vector of Strings with the
names of all the personalities that are enabled in
the class.

personalities()

48

Dynamic PJ - Client Changes


// smallZoo.pj
void main() {
// create a new object
SeaLion toto = new SeaLion();
toto.personify( Swimmer ); // enable Swimmer
toto.personify( "Jumper" );
// and Jumper
// this should print [Swimmer,Jumper]
System.out.println(toto.personalities());
toto.personify( "Walker" );
// enable Walker
DoShow(toto);
toto.forget( "Walker" );
toto.forget( "Jumper" );
toto.forget( Swimmer );
a
s
i
t
}
n
ich
ie
h
l
c
w
s
t
i
void DoShow(Object animal) { Th
en
i
l
c

i
if ( animal.personifies( "Swimmer"
)ng
w
on
o
m
n
k
m

o
c
((Swimmer).animal).Swim(10,10);
e
h
t
uses) ) to decide y
if ( animal.personifies( "Walker"
r
ol
e
c
v
((Walker).animal).Walk(10,10);
o
t
t
o
o
(n
pr
if ( animal.personifies( "Flier" ) ) to do
)
:
t
!
a
h
w
o
((Flier).animal).Fly(10,10,10);
w
n
k
I
if ( animal.personifies( "Jumper"
se)fu)l,
u
((Jumper).animal).Jump(10,10);
}

49

Personalities and Frameworks


Outline

Using Hotspots to plug-in a framework


through inheritance
through delegation
through personalities

Personalities as traffic cops


the benefits
composing frameworks using personalities
delegating composition to the apps code
50

Using Inheritance for Hotspots


Framework
Hotspots

Application A

Application B

e
l
p
i
t
l
Mu
ce
n
a
t
i
Inher

A class that can provide


the behavior required by
both hotspots.

A class that
already
inherits once
within its
own app.

51

Using Delegation for Hotspots


HotspotA
HotspotB
HotspotImpl
Classes
must
register
with
the
framework
-attrA: int
-attrB: int
+void fwork();
-hsi:HotSpotImpl
+void
so fwork();
they can be called

+void fwork(){
hsi.fwork();}

error prone
can get out of
OID:sync
HotspotB@0x0ffe54

AppClassA
-appAttrA:int

+void fwork(){...}
+void appFn(){...}

Object identity

AppClassB
-appAttrB:int
+void fwork(){...}
+void appFn(){...}

two live references (the hotspot, and the


delegation class)
OID: HotspotA@0x0ffe23
OID: AppClassB@0x0ffade
delegation of protocol (Wieringa) does not work
void client(HotspotA
hs) { typed languages
void client(HotspotB hs) {
in
strongly
hs.fwork();
// ok
hs.fwork();
// ok
}

((AppClassA)hs).appFn(); // ok

((AppClassB)hs).appFn(); // error!
// invalid cast

52

Using Personalities for Hotspots

Easy to adapt a framework


inheritance-like

Flexible
multiple inheritance-like

Robust
solve the object identity problem introduced by
delegation

Plus some semantic guarantees


encapsulated in their UI methods

53

Personalities as Traffic Cops

The additional behavior encapsulation


really helps
When we need to integrate
frameworks
Or compose them
Lets examine one example...

54

ShowFramework
ShowFramework
ShowDirector

Flier

personality Flier {
void Fly(int a) {
Takeoff();
Flap(a);
Land(); }
di void Takeoff();
di void Flap(int);
di void Land();
}

The entry point


to this framework
is the do_show()
method.

class ShowDirector {
Vector fliers=new Vector();
...
void do_show(int a) {
for(int i=0; i<fliers.size(); i++) {
Flier aFlier=
(Flier)fliers.elementAt(i);
aFlier.Fly(a);
}
}
}

And were using the


Flier personality (simplified)
as the frameworks hotspot. 55

TakeoffAndLandFramework
TakeoffAndLandFramework
MechFlier

LandGear

personality LandGear {
void down() {
if (_state = UP) {
servoOn();
servoMove();
servoOff();
}
}
void up() { ... }
...
}

servoOn(), servoMove()
servoOff() is LandGears
downstream interface.

takeoff() and land() are


the entry points to this
framework.
class MechFlier {
LandGear lg = MechFact.makeLandGear();
...
void takeoff() {
...
lg.up();
}
void land() {
lg.down();
...
}
}

LandGear personality used


as the TALFrameworks
hotspot

56

PlaneApp

Two simple hierarchies. The


Planes and the Wheels.

PlaneApp
Plane

B747

Wheels

WaterPlan
e
BWheel WWheel

class Plane { ... }


class B747 extends Plane { ... }
class WaterPlane extends Plane
{...}
class Wheels { ... }
class BWheel extends Wheels { ... }
class WWheel extends Wheels { ... }

57

rk
o
w
e
Composition using Personalities
am
r
f
e
th
here

Show_TakeoffAndLandFramework
Show Framework
ShowDirector

Flier

<<personifies>>
TakeoffAndLandFramework

Needed to ask forMechFlier


the part of Flier
that TALFramework
does not provide
PartialFlier

Once ntiated, t r
a
ie
l
t
F
s
l
n
i
a
i
t
is
ar
P
a
l {
l
e personifies
class MechFlier
Flier
a
b
c
l
l
s
i
w lg = MechFact.makeLandGear();
hi
LandGear
T
.
r

e
t
d
c
l
...
e
o
j
h
ob
voidtakeoff()
{ place
a
ns
t
a
s
...
e
u
j
m
is
er
lg.up();
v
e
t
ve
a
e
h
i
}
w
r
t
r
e
fo { d to r
void land()
e
s
lg.down();
u
f.
e
e
r
t
... ar
jec
b
o
}
t
haFlier
// --- t
for
}

PartialFlier pf = getFromApp();
void Takeoff() { takeoff(); }
void Land()
{ land();
}
void Flap(int a) { pf.PartialFlap(a); }

LandGear
personality PartialFlier {
void PartialFlap(int a) { Flap(a);}
di void Flap(int a);
}

58

PlaneApp with
Show_TakeoffAndLandFramework
Show_TakeoffAndLandFramework
do_show()
Partial
Flier

Lots of
flexibility!
Flier

Plane

B747

class Plane { ... }


class B747 extends Plane,
personifies PartialFlier {
...
void Flap(int a) { ... }
}
class WaterPlane extends Plane,
personifies Flier {
...
void Takeoff() { ... }
void Flap(int a) { ... }
void Land() { ... }
}
class Wheels { ... }
class BWheel extends Wheels,
personifies LandGear {
...
void servoOn() { ... }
void servoMove() { ... }
void servoOff() { ... }
}
class WWheel extends Wheels {...}

WaterPlan
e

LandGear

Wheels

BWheel WWheel
However,
its intrusive since it requires
PlaneApp

modifying the TALFramework to create


the new one. Sometimes, you just cant
do that. What then?

59

ts
n
e
m
e
pl
m
i
n
tio
a
ing
c
i
t
l
a
p
g
p
e
a
del
ShowFramework
The
y
b
s Flier {
k
I
r
o
D
class
Plane
personifies
w
s
do_show()
rame iers
Flier TAL...
F
void Takeoff()
Fl {}
e
h
c
h
t
e
void
Land() {}
(M
to
t
n
i
)) {}
o
Flier
(a)
p void Flap(int
d
n
y
r
a
l
t
TakeoffAndLand
} and
en
)
(
Framework keoff class B747 extends Plane {
MechFlier flier = ...;
ta

Delegating Composition to the App.

takeoff()
land()
LandGear

Plane

B747

Wheels

WaterPlan
e
BWheel WWheel

PlaneApp

void Takeoff() { flier.takeoff(); }


void Land()
{ flier.land();
}
void Flap(int a) { ... }

}
class WaterPlane extends Plane {
...
void Takeoff() { ... }
void Flap(int a) { ... }
void Land() { ... }
}
class Wheels { ... }
class BWheel extends Wheels,
personifies LandGear {
...
void servoOn() { ... }
void servoMove() { ... }
void servoOff() { ... }
}
class WWheel extends Wheels {...}

60

Other Northeastern
Collaboration-Based Work

Miras APPCs
one APPC per DI method
multiple personification becomes essential

Johans CGVs
behavior methods similar to UI methods
map methods similar to DI methods

61

Future Work - Outline

Performance ranges and guarantees


add requirements to the DI specification
(OOPSLA workshop)

Mapping and parameter conversion


Inheritance of personalities
Composition of personalities
Flier + Acrobat = AcrobaticFlier
62

class SpaceShuttle {
void EngageRockets() { ... }
void ExitAtmosphere() { ... }
void Orbit(int x, int y) { ... }
void EnterAtmosphere() { ... }
void Land() { ... }
boolean ThereYet(int x, int y) { ... }
}

class SpaceShuttle personifies Flier


with EngageRockets = Takeoff,
ExitAtmosphere = Ascend,
Orbit = Flap,
EnterAtmosphere = Descend
{
void EngageRockets() { ... }
void ExitAtmosphere() { ... }
void Orbit(int x, int y) { ... }
void EnterAtmosphere() { ... }
void Land() { ... }
boolean ThereYet(int x, int y) { ... }
}

Mapping and Parameter


Conversion

// from Vendor A (in Argentina, for instance)


personality FruitProducer {
...
di boolean CheckStockHas(double kilograms);
}

Already existent class, different method


names

// from Vendor B (in the US, for instance)


personality FreezerUser {
...
di boolean ValidateProdQuant(double pounds);
}

class TheRedAppleInc extends AppleCo


personifies FruitProducer, FreezerUser
with CheckStockHas =
ValidateProdQuant(<pounds>*2.2)
{
...
boolean CheckStockHas( double kilograms )
{ ... }
// ValidateProdQuant needs not
// be implemented at all
}

map DI to new names

Already existent class, different


signatures
(minor diffs only)
class TheRedAppleInc extends AppleCo

!!!

:-)

personifies FruitProducer, FreezerUser


map
+ parameter conversion
{

...
public boolean CheckStockHas(double kilograms) {
// behavior is implemented in metric system
}
public boolean ValidateProdQuant(double pounds) {
return CheckStockHas( pounds * 0.454 );
}

63

Inheritance of Personalities

Useful for decreasing granularity


personality MechanicFlier extends Flier
{
void TakeOff() {
gotoRunway();
waitForClearance();
Abstraction
speedUp();
increaseFlaps();
+ } bringLandingGearUp();
Flier
void Ascend() { ... }
void FlapTowards(int x, int y) { ... }
boolean ThereYet(int x, int y) { ... }
void Descend() { ... }
void Land() { ... }
MechanicalFlier
di void gotoRunway();
di void waitForClearance();
-di void speedUp();
di void increaseFlaps();
di bringLandingGearUp();
Granularity
...
}

Implement some of
Fliers DI methods...
DI

And add some


of your own.
Keep standard inheritance semantics

64

Related Works

Using delegation
LaLonde86, Gottlob96
roles are tightly bound to the class, not easy to apply them to
different hierarchies

Relaxing inheritance
Bracha90,92, Holland93, Lucas94, Flatt98, Mezini98, Seiter98
do not attempt to commit to a specific behavior (as in popular
functions)

The visitor pattern


Krishnamurthi98, Gamma94
no notion of DI, code duplication, strongly tied to class hierarchy

65

Related Works (contd)

Subject-Oriented programming
Harrison93
similar goals to personalities, no concept of UI/DI, no enforcement of
LoP

Adaptive programming
Lieberherr96
no concept of UI/DI, no enforcement of LoP

Rapide
Luckham95
provided and required similar to upstream and downstream, different
scope

66

Personalities/J Compiler

Built entirely using Demeter/Java 0.7


Distributed team
GTE Labs
Catholic University of Cordoba, Argentina
Daniel Gandara
Diego Rodrigo

Version 0.1.9
static personalities
Lets try it!
indecisive are around the corner! :-)

67

You might also like