personalities-3360.ppt

Download Report

Transcript personalities-3360.ppt

Designing and Programming
with Personalities
Luis Blando
[email protected]
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, Object Oriented
Software Construction, 1988
4
When Behavior Misbehaves - 1
Mammal
Lion
Animal
Oviparous
Use their reproductive
What about using
really
behavior, ofNonsense!
course! What’stheir
eating habits?
important is their
intelligence!
ZooSys
“The name of a class should reflect its
intrinsic nature and not a role that it
plays in an association”. James
Veterinary
Trainer
Feeder
Rumbaugh et.al. Object-Oriented
Modeling and Design, 1991.
5
When Behavior Misbehaves - 2
The intrinsic stuff
is easy to do! :-)
The vets got
their way
But what about the trainers and
the feeders ???
6
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
7
Mapping Popular Functions
Swim()
Fly()
Walk()
8
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 fullfledged classes)
9
Personalities - Outline


Designing with roles
Personalities
– Concept, Architecture, Components,
Syntax, Usage

The law of personalities
10
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
11
Personality - Architecture
Users of the object only
deal with the Personality’s
“Upstream Interface”
The role behavior is
encapsulated here...
…and defined in terms
of the “Downstream
Interface”, which classes
in the hierarchy must
implement.
12
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 role’s state

Constructor
– to initialize the role-specific attributes
13
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. Don’t 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(); }
}
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.
14
Personality - Usage Syntax
Declare intent...
// 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 that’s
}
// 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 */ }
}
Implementation
of the Bat class.
Nothing to do
with the Flier
personality here...
The Bat class
implements the DI
of the Flier
personality
15
Law of Personalities Hooray!
(LoP) - 1

No default implementation
– only abstract functions in DI

Karl
Basic types
– only language-defined types allowed in method signatures

Behavioral buffer
– users of the object communicate only through UI

Fixed popular behavior
– implementation of popular functions is final

Implementation separation
– popular functions’ implementation can only use DI to talk to
the personifying class
16
Luis
LoP - No default implementation

Default implementation does not make
// compute and return today’s date
sense
Easy to check
String Today();
automatically
– since we can use personality
in many
different domains!
VS.

Expected semantics of DI must be clear
// compute and return today’s date
– so
the behavior
of the Can’t
personality’s
check
// that
in the
format “YYYYMMDD”
popular
guaranteed
automatically!
String functions
Today();is somewhat
17
LoP - Basic Types (recommendation)
personality Foo {

No user-defined
types in the signatures
...
of either
DI or UI
methods
// return
today
– using
only language-defined
types
MyDateClass
Today();
Easy to check automatically.
guarantees deployability everywhere
However, since it’s a
recommendation,
Personalities/J
VS.
 However, it’s
too constraining
a switch for “strong syntax”
– too many has
translations
to/from basic types
(a-la ANSI C) :-)
// return today
when
deploying a “component”
java.util.Date
Today();
...recommended everywhere, required
– thus,
}
only
at the “deployment boundaries”
18
LoP - Behavioral Buffer
// SeaWorldShow() is a client


Clients
call UI
methods
// ofonly
Swimmer
personality
Design
at the personality
void reuse
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)
19
LoP - Fixed Popular Behavior
// LazyPelican.pj
class LazyPelican extends Oviparous
 Popular functions’
implementations are
personifies Flier
{ final
...implementation of downstream interface
– we
help
provide
someFly(...)!
kind of semantic
//
shouldn’t
redefine
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);
for(int a = altitude;
a > 0; a++)
 Subfunctions
are easier
to Descend();
implement
Land();
}– since their scope is hopefully smaller
}
20
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)
21
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
22
Dynamic Personalities

Why bother?
– Workarounds for object migration




Shortcomings of “static” personalities
What we’d like
Partially-dynamic personalities (a.k.a.
“indecisive personalities”)
Fully-dynamic personalities
23
But wait!
What’s 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
24
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 Employee’s
upstream interface without any reclassification!
25
Shortcomings of “static”
class Person
personifies Employee, Manager …
Personalities
 However,
you needhere,
to know at classIf
you forget something
you’ll
have to time,
recompile
yourpersonalities
class
creation
all the
you
and refresh the instances later!
might need in the future
– tough to do
But wait! John
// personality code
is still not even an
 And,
there’s
no
way
for
controlling
class Person
Employee,
much
personifies Employee, Manager
…
“access” to the personalities
a class
less afor
Manager!
clienttocode
–//similar
always instantiating a Manager
Person john = new Person();
object if using inheritance
((Manager)john).yellToBoss();

No common protocol among
personalities
26
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
27
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
 ...
john.personify( “Employee” ); // hired
“can”
instead of “does”
...
john.personify( “Manager” ); // promoted
 Third-party
instructs the class to
...
john.forget( “Manager” );
// fired
john.forget( “Employee” );
– security concerns are ignored
“personifies” semantics change to mean
activate and deactivate the personality


Still
need to declare all potential
// class Person definition
class Person at class-creation time
personalities
personifies Employee, Manager {...}
Very fast implementation
Still need to declare all potential personalities...
28
Indecisive Personalities -2
Report Card

Runtime attachment and detachment
Preservation of object identity
Hey!
 Preservation
of Typing
properties
Five
out
of Six isn’t
 Common interface
that among
bad!personalities

– same framework as static personalities
– compile-time strong typing
– possibility of “non-active” personality must be recognized by
client program
– “personify()”, “forget()”, “personifies()” etc.


Reasonable performance
Ubiquitous personification
29
Personalities/J - Outline





The environment and assumptions
Knowing and unknowing clients
The mapping process
Static PJ
Indecisive PJ
30
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
31
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 }
32
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
{
... Copy intact from SeaLion.pj ...
// ============== for Swimmer
Swimmer$Ego $swimmer=new Swimmer$Ego();
public void Swim(int miles, int depth)
{ $swimmer.Swim(this, miles, depth); }
// ============== for Walker
Walker$Ego $walker = new Walker$Ego();
public void Walk(int distance)
{ $walker.Walk(this, distance); }
// ============== for Jumper
Jumper$Ego $jumper = new Jumper$Ego();
public void Jump(int x, int y, int alt)
{ $jumper.Jump(this, x, y, alt); }
}
33
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
34
Static PJ - «pers»$Ego.java
// Swimmer$Ego.java [static]
public class Swimmer$Ego
{
public void Swim(Swimmer host,
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()
{ }
}
35
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()
36
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” );
}
void DoShow(Object animal) {
if ( animal.personifies( "Swimmer" )
((Swimmer).animal).Swim(10,10);
if ( animal.personifies( "Walker" ) )
((Walker).animal).Walk(10,10);
if ( animal.personifies( "Flier" ) )
((Flier).animal).Fly(10,10,10);
if ( animal.personifies( "Jumper" ) )
((Jumper).animal).Jump(10,10);
}
37
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 app’s code
38
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
39
Personalities as Traffic Cops



The additional behavior encapsulation
really helps…
When we need to integrate
frameworks…
Or compose them
40
Other Northeastern
Collaboration-Based Work

Mira’s APPCs
– one APPC per DI method
– multiple personification becomes essential

Johan’s CGVs
– behavior methods similar to UI methods
– map methods similar to DI methods
41
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
Flier’s DI methods...
DI
And add some
of your own.

Keep “standard” inheritance semantics 42
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
43
Related Works (cont’d)

Subject-Oriented programming
– Harrison93
– similar goals to personalities, no concept of UI/DI, no
enforcement of LoP

Adaptive programming
– Lieberherr96
– no enforcement of LoP

Rapide
– Luckham95
– provided and required similar to upstream and downstream,
different scope
44
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
– indecisive are around the corner! :-)
45
Personalities/J Compiler





Built entirely using Demeter/Java 0.7
63 000 chars written
2 047 000 chars generated
1000 line (18400 chars) class dictionary
8 traversals
– from CompilationUnit via ClassDeclaration
to UnmodifiedClassDeclaration
– creates 147 line traversal graph (*.trv)
46