Designing and Programming with Personalities Luis Blando [email protected] Copyright © 1998.
-
Upload
jeffry-underwood -
Category
Documents
-
view
214 -
download
0
Transcript of Designing and Programming with Personalities Luis Blando [email protected] Copyright © 1998.
2
Outline
Modeling behavior Personalities Dynamic Personalities Synergy with Frameworks Personalities/J language Q&A
3
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
4
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
5
/* 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) {...}...
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
Functional Decomposition and Structured Programming
rtt_init()
rtt_newpack()
rtt_start()
rtt_stop()
rtt_timeout()
dgsendrecv(…)
Smaller scopeBigger scope
Wait!
Which caller?
And when?
What if in hereI mess with
rtt_info?
6
Data Decomposition and Object Oriented Programming
RTTfloat 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()
ReliableDGRAMint rttfirst;int tout_flag;RTT myrtt;
+ sendrecv(){ myrtt.setX(); myrtt.init(); ... }
These are the accessors to
regulate object statechanges !
This used tobe rtt_struct
We’ve encapsulated data and functions together. The users keep an instance of
“both”
7
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 Construction, 1988.
“What actions must get accomplished, and which object will accomplish them, are questions that we must answer right at the start”. Rebecca Wirfs-Brock et.al., Designing Object-Oriented Software, 1990.
“The object’s operations come naturally when we consider and object’s interface. The operations can also be identified directly from the application, when we consider what can be done with the items we model”. Ivar Jacobson et. al., Object-Oriented Software Engineering, 1992.
8
Wait a minute! What’s “normal” for me
might not be so for Grady or James!
I know, let’s justconcentrate on the basicbehavior only for now...
Finding Objects and Behavior - 2
“normal” behavior
CRC, use-cases
The 3 amigos
“intrinsic” behavior. Harrison & Ossher, Subject-Oriented Programming, 1993
(one-domain, accessors)
When in doubt… Follow
the data! (anonymous :)
9
When Behavior Misbehaves - 1
ZooSys
Mammal
Lion
Animal
Oviparous
Use their reproductivebehavior, of course!
Veterinary
Nonsense! What’s reallyimportant is their
intelligence!
Trainer
What about using their eating habits?
Feeder
“The name of a class should reflect its intrinsic nature and not a role that it plays in an association”. James Rumbaugh et.al. Object-Oriented Modeling and Design, 1991.
?
10
When Behavior Misbehaves - 2The intrinsic stuffis easy to do! :-)
The vets got their way
But what about the trainers and the feeders ???
11
When Behavior Misbehaves - 3
“The show shall start with the pink pelicans and the African geese flying across the stage. They are to land at one end of the arena and then walk towards a small door on the side. At the same time, a killer whale should swim in circles and jump just as the pelicans 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 for him.”
A possible Trainer requirementHey! I’m sure I can find some
commonality in all these functions!After all, how many ways can you
actually “walk”!
12
Popular Functions
// (x,y) is the target landing spotvoid 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(int a=altitude; a > 0; a--) Descend(); Land();}
Fly() popular function
Encapsulatethis sequence.Always thesame for anyclass...
Takeoff Ascend ThereYet FlapTowards Descend Land
JumpInTheWater Submerge MoveFin
Rise JumpOutOfTheWater
Prepare MoveFoot Stabilize AtEase
Fly
Swim
Walk
CheckDistance SprintTo LiftOff
Land
Jump
The popular functions in ZooSys
…and their sub-functions
14
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)
15
Personalities - Outline
Designing with roles Personalities
– Concept, Architecture, Components, Syntax, Usage
The law of personalities
16
Designing with Roles
Some OOA/D methodologies are conducive to the discovery of roles– Wirfs-Brock et. al.– Andersen et. al.
Roles are nevertheless found by inspecting the dynamic views of a sufficiently complex system.
“The show shall start with every flying animal in our zoo flying across the stage. They are to land at one end of the arena and then walk towards a small door on the side. At the same time, a killer whale 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 for him.”
It could’ve been something like this...
“The show shall start with the pink pelicans and the African geese flying across the stage. They are to land at one end of the arena and then walk towards a small door on the side. At the same time, a killer whale should swim in circles and jump just as the pelicans 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 for him.”
Remember this requirements statement?Eureka!Maybe “Flier” is a role of a lot ofanimals here?
17
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
18
(“Trainer”)
(“Flier”)
(“Pelican”)
Personality - ArchitectureUsers of the object onlydeal with the Personality’s“Upstream Interface”
…and defined in termsof the “DownstreamInterface”, which classesin the hierarchy mustimplement.
The role behavior isencapsulated here...
19
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
20
Personality - Definition Syntax// Flier.pjpersonality 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.
Private aux.functions andattributes.
Constructor
Syntactic
Sugar
21
// Bat.pjpublic 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 */ }}
Personality - Usage Syntax
Implementation of the Bat class. Nothing to do with the Flier personality here...
Declare intent...
The Bat classimplements the DI of the Flier personality
22
Law of Personalities (LoP) - 1
No default implementation– only abstract functions in DI
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
Luis
After some debate, we demoted
this one to “recommendation” to
allow for more integrated (but
less easily deployable) personalities.
Karl
Hooray!
23
LoP - No default implementation
Default implementation does not make sense– since we can use personality in many
different domains! Expected semantics of DI must be clear
– so that the behavior of the personality’s popular functions is somewhat guaranteed
Easy to checkautomatically
Can’t checkautomatically!
// compute and return today’s date
String Today();
VS.
// compute and return today’s date// in the format “YYYYMMDD”String Today();
This small comment makes
all the difference in the
world !
24
LoP - Basic Types (recommendation)
No user-defined types in the signatures of either DI or UI methods– using only language-defined types guarantees
deployability everywhere However, it’s too constraining
– too many translations to/from basic types when deploying a “component”
– thus, recommended everywhere, required only at the “deployment boundaries”
Easy to check automatically.However, since it’s a
recommendation, Personalities/Jhas a switch for “strong syntax”
(a-la ANSI C) :-)
personality Foo {
...
// return today
MyDateClass Today();
VS.
// return today java.util.Date Today(); ...}
This forces Foo to always
have to be deployed with
MyDateClass !
25
LoP - Behavioral Buffer
Clients only call UI methods Design reuse at the personality level
– the popular functions are totally defined Semantic guarantees (sort of)
– the popular functions are final, (though based on the DI implementations)
Easy to check automatically.
// SeaWorldShow() is a client
// of Swimmer personality
void SeaWorldShow(Swimmer s) {
s.Swim(10,10); // ok, UI used
s.Submerge(); // error, DI used
}
26
LoP - Fixed Popular Behavior
Popular functions’ implementations are final– help provide some kind of semantic
guarantee to users of the personality– it keeps the personality “narrow”
Subfunctions are easier to implement– since their scope is hopefully smaller
Easy to check automatically.
// LazyPelican.pjclass LazyPelican extends Oviparous personifies Flier{ ...implementation of downstream interface // we shouldn’t redefine Fly(...)! public void Fly(int x, int y, int altitude) { Takeoff(); for(int a = 0; a < altitude/2; a++) Ascend(); while( !ThereYet(x, y) ) FlapTowards(x, y); for(int a = altitude; a > 0; a++) Descend(); Land(); }}
This LazyPelican is going
to crash! What happens to
all the clients of the Flier
personality now?
27
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)
28
Keeping everybody happy
(“personifies” relationship)
Vets
I can talk to theanimals as Mammal
and Oviparous.
Trainers
And to me they are justFliers, Swimmers,
Walkers, and Jumpers!
29
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
30
Why Bother with DynPers?
Roles are very much “dynamic” Object migration problem
Person john = new Person();
// 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 johndelete john;tmp.yellToBoss(); // now it works
But wait! What’s wrong here???
MedSys { addPatient(Person p) {…} doSomething() { if (p.age() > 80) … }}
Medsys.addPatient(john);
31
Workarounds for the Object Migration problem Reclassification
– need to update every single client that is using the “old” instance
Delegation – counterintuitive since “john” is one entity– duplicated state when overlapping semantics– not the same object instance for all clients (typing)– problem of triggering state changes “up”
Using personalities (even the “static” version) helps, since:
// Person will (someday) be Employee and, // with any luck, also a Managerclass Person personifies Employee, Manager …...Person john = new Person();
Whoever has the “john” instance, can still use methods from Manager and/or Employee’s upstream interface without any reclassification!
32
Shortcomings of “static” Personalities However, you need to know at class-creation
time, all the personalities you might need in the future– tough to do
And, there’s no way for controlling “access” to the personalities for a class– similar to always instantiating a Manager object if
using inheritance No common protocol among personalities
class Person personifies Employee, Manager …
If you forget something here,you’ll have to recompile your class and refresh the instances later!
// personality codeclass Person personifies Employee, Manager …
// client codePerson john = new Person();((Manager)john).yellToBoss();
But wait! Johnis still not even anEmployee, much less a Manager!
33
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