Designing and Programming with Personalities Luis Blando [email protected] Copyright © 1998.

34
Designing and Programming with Personalities Luis Blando [email protected] Copyright © 1998

Transcript of Designing and Programming with Personalities Luis Blando [email protected] Copyright © 1998.

Designing and Programming with Personalities

Luis [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

13

Mapping Popular Functions

Fly()Swim()

Walk()

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

34

Indecisive Personalities - 1

“personifies” semantics change to mean “can” instead of “does”

Third-party instructs the class to activate and deactivate the personality– security concerns are ignored

Still need to declare all potential personalities at class-creation time

Very fast implementation