33
Lifting your favorite language with Traits Alexandre Bergel RMoD team, INRIA, Lille, France [email protected] !"#$

Presentation of Traits

  • Upload
    bergel

  • View
    2.586

  • Download
    0

Embed Size (px)

DESCRIPTION

Traits are a simple composition mechanism for structuring object-oriented programs. A Trait is essentially a parameterized set of methods; it serves as a behavioral building block for classes and is the primitive unit of code reuse. With Traits, classes are still organized in a single inheritance hierarchy, but they can make use of Traits to specify the incremental difference in behavior with respect to their superclasses.

Citation preview

Page 1: Presentation of Traits

Lifting your favorite language with Traits

Alexandre BergelRMoD team, INRIA,

Lille, [email protected]

!"#$

Page 2: Presentation of Traits

Outline

1. Limitation of single inheritance

2. Traits

3. Retrospective

4. Freezable & Stateful

5. Conclusion

Page 3: Presentation of Traits

Stream in Squeak

• Example of a library that has been in use for almost 20 years

• Contains many flaws in its design

Page 4: Presentation of Traits

Stream in Squeak

atEndclosecontentsdo:flushnextnext:next:put:nextPut:nextPutAll:upToEnd

Stream

atEndcontentsisEmptynext:peekpositionposition:resetsetToEndskip:skipTo:upTo:upToEnd

collectionpositionreadLimit

Positionable

Stream

nextnext:nextPut:sizeupTo:upToEnd

ReadStream

contentsflushnextnextPut:nextPutAll:position:resetsetToEndsizespacecr

writeLimitWriteStream

closecontentsnextnext:

ReadWriteStream

atEndcloseflushfullNamenextnext:nextPut:nextPutAll:peekpositionposition:resetsetToEndsizeskip:upTo:upToEnd

rwmodenamefileIDbuffer1

FileStream

Page 5: Presentation of Traits

Methods too high

atEndclosecontentsdo:flushnextnext:next:put:nextPut:nextPutAll:upToEnd

Stream

atEndcontentsisEmptynext:peekpositionposition:resetsetToEndskip:skipTo:upTo:upToEnd

collectionpositionreadLimit

Positionable

Stream

nextnext:nextPut:sizeupTo:upToEnd

ReadStream

contentsflushnextnextPut:nextPutAll:position:resetsetToEndsizespacecr

writeLimitWriteStream

closecontentsnextnext:

ReadWriteStream

atEndcloseflushfullNamenextnext:nextPut:nextPutAll:peekpositionposition:resetsetToEndsizeskip:upTo:upToEnd

rwmodenamefileIDbuffer1

FileStream

nextPutAll: aCollection aCollection do: [:v| self nextPut: v]. ^ aCollection

Page 6: Presentation of Traits

Methods too high

• The nextPut: method defined in Stream allows for element addition

• The ReadStream class is read-only

• It therefore needs to “cancel” this method by redefining it and throwing an exception

Page 7: Presentation of Traits

Unused state

atEndclosecontentsdo:flushnextnext:next:put:nextPut:nextPutAll:upToEnd

Stream

atEndcontentsisEmptynext:peekpositionposition:resetsetToEndskip:skipTo:upTo:upToEnd

collectionpositionreadLimit

Positionable

Stream

nextnext:nextPut:sizeupTo:upToEnd

ReadStream

contentsflushnextnextPut:nextPutAll:position:resetsetToEndsizespacecr

writeLimitWriteStream

closecontentsnextnext:

ReadWriteStream

atEndcloseflushfullNamenextnext:nextPut:nextPutAll:peekpositionposition:resetsetToEndsizeskip:upTo:upToEnd

rwmodenamefileIDbuffer1

FileStream

Page 8: Presentation of Traits

Unused state

• State defined in the super classes are becoming irrelevant in subclasses

• FileStream does not use inherited variables

Page 9: Presentation of Traits

Multiple inheritance simulation

atEndclosecontentsdo:flushnextnext:next:put:nextPut:nextPutAll:upToEnd

Stream

atEndcontentsisEmptynext:peekpositionposition:resetsetToEndskip:skipTo:upTo:upToEnd

collectionpositionreadLimit

Positionable

Stream

nextnext:nextPut:sizeupTo:upToEnd

ReadStream

contentsflushnextnextPut:nextPutAll:position:resetsetToEndsizespacecr

writeLimitWriteStream

closecontentsnextnext:

ReadWriteStream

atEndcloseflushfullNamenextnext:nextPut:nextPutAll:peekpositionposition:resetsetToEndsizeskip:upTo:upToEnd

rwmodenamefileIDbuffer1

FileStream

Page 10: Presentation of Traits

Multiple inheritance simulation

• Methods are duplicated among different class hierarchies

Page 11: Presentation of Traits

Class responsibilities

• Too many responsibilities for classes

- object factories

- group methods when subclassing `

Page 12: Presentation of Traits

Class schizophrenia?

• Too many responsibilities for classes

- object factories => need for completeness

- group methods when subclassing => need to incorporate incomplete fragments

Page 13: Presentation of Traits

Traits

TCircleareaboundsdiameterhash...

radiusradius:centercenter:

• Traits are parameterized behaviors- traits provide a set of methods - traits require a set of methods - traits are purely behavioral

Page 14: Presentation of Traits

Class = Superclass + State + Traits + Glue Methods

• Traits are the behavioral building blocks of classes

Generic propertiesObject

Component Geometrical

RectangleWidget

setX1(...)setY1(...)

RectangleShape

setX1(...)setY1(...)TRectangle

TColorx1, y1, x2, y2 point1, point2

TRectangle

TColor

...

Page 15: Presentation of Traits

Composition rules

Class methods take precedence over trait methods

ColoredCircle

TColorhuergb

draw

ColoredCircle

TColorhuergb

TCircledrawradiusdrawdraw

TCircledrawradius

Page 16: Presentation of Traits

Conflicts are explicitly resolved

• Override the conflict with a glue method

- Aliases provide access to the conflicting methods

• Avoid the conflict

- Exclude the conflicting method from one trait

ColoredCircle

TColorhash

TCirclehashhash -> circleHash

hash

ColoredCircle

TColorhash

TCirclehashhash hash -> circleHash

hash -> colorHash

Page 17: Presentation of Traits

Flattening property

ColoredCircle

TColor

TCircledraw

rgb

draw

hue

radius

Object

ColoredCircle

Object

rgbhue

radius

draw

equivalentStructured view Flat view

Page 18: Presentation of Traits

Stream revisited

do:nextMatchFor:next:peekFor:skip:skipTo:upTo:upToEndupToElementSatisfying:

atEndnextpeekoutputCollectionClass

TGettableStream

atEndatStartbackcloseisEmptyposition:resetsetToEnd

positionsetPosition:size

TPositionableStream

nextPutAll:next:put:print:flush

nextPut:TPuttableStream

Core

binarycloseclosedisBinaryisClosedisStream

TStream

backbackUpTo:match:nextDelimited:skip:

TGettablePositionableStream TPuttablePositionableStream

writeBack

@ {#basicBack->#back}

Page 19: Presentation of Traits

Retrospective

• International recognition- Fortress- Slate- Perl 6- Squeak

• Numerous type systems- Nierstrasz’06- Fisher&Reppy’03, Reppy & Turon’06- Drossopoulou’05

Page 20: Presentation of Traits

StatefulTraits

• Alexandre Bergel, Stéphane Ducasse, Oscar Nierstrasz and Roel Wuyts, “Stateful Traits,” Advances in Smalltalk — Proceedings of 14th International Smalltalk Conference (ISC 2006), LNCS, vol. 4406, Springer, August 2007, pp. 66-90.

• Alexandre Bergel, Stéphane Ducasse, Oscar Nierstrasz and Roel Wuyts, “Stateful Traits and their Formalization,” Journal of Computer Languages, Systems and Structures, vol. 34, no. 2-3, 2008, pp. 83-108

Page 21: Presentation of Traits

Traits limits

• Trait users should define missing traits state

• Important required methods and required state are mixed

• Boilerplate glue code

• Propagation of required accessors

Page 22: Presentation of Traits

TSyncReadWritelockinitializesyncReadsyncWrite

readwritelock:lock

SyncFilelocklock:lockreadwrite

SyncStreamlocklock:lockreadwrite

SyncSocketlocklock:lockreadwrite

syncRead | value | self lock acquire. value := self read. self lock release. ^ value

syncWrite | value | self lock acquire. value := self write. self lock release. ^ value

Duplicated code

Use of trait

initialize super initialize. self lock: Lock new

Page 23: Presentation of Traits

Stateful traits

• Instance variables are per default private to the trait

• Via composition

• Composing classes may get access to state

• Composing classes may merge the accessed state

Page 24: Presentation of Traits

By default state is private

T1

getXT1

setXT1:

x

T2

getXT2

setXT2:

x

C

getX

setX:

x

c := C new.c setXT1: 1.c setXT2: 2.c setX: 3.

{ Now: c getXT1 = 1 c getXT2 = 2 c getX = 3 }

Page 25: Presentation of Traits

But remain accessible still

@@{ xFromT1 -> x }T1

getXT1

setXT1:

x

@@{ xFromT2 -> x }

c := C new.c setXT1: 1.c setXT2: 2.

{ Now: c getXT1 = 1 c getXT2 = 2 c sum = 3 }

sum

^ xFromT1 + xFromT2

T2

getXT2

setXT2:

x

sum

C

Page 26: Presentation of Traits

Variables may be merged

T1

getX

setX:

x

T2

getY

setY:

y

C

getW

setW:

@@{w -> x}

@@{w -> y}

c := C new.c setW: 3.

{ Now: c getX = 3 c getY = 3 c getW = 3 }

Page 27: Presentation of Traits

Analysis• Traits and state reconciled

Traits are completeStateless traits are just a special case of stateful traitsNo accessor requiredNo boiler plate code

Flattening property can be rescued using instance variable mangling

State is private but can be made accessible at composition

Page 28: Presentation of Traits

Freezable Traits

• Stéphane Ducasse, Roel Wuyts, Alexandre Bergel and Oscar Nierstrasz, “User-Changeable Visibility: Resolving Unanticipated Name Clashes in Traits,” Proceedings of 22nd International Conference on Object-Oriented Programming, Systems, Languages, and Applications (OOPSLA'07), ACM Press, New York, NY, USA, October 2007, pp. 171—190.

Page 29: Presentation of Traits

Trait limits

Composer

T1foo {self x}x {^ 'T1'}

T2bar {self x}x {^ 'T2'}

trait trait composition

• Methods may conflict while they are private to the traits

• You can only have one x in Composer: either T1x, T2x or Cx

Page 30: Presentation of Traits

Method Visibility

Composer

Freezing T1 x

Composer new foo -> 'T1'Composer new bar -> 'T2'Composer new x -> 'T2'

T1+ foo {self x}+ x { ^ 'T1'}

T2+ bar {self x}+ x { ^ 'T2'}

T1 freeze x Composer

Freezing T2 x and T2 x

Composer new foo -> 'T1'Composer new bar -> 'T2'Composer new x -> Error

T1+ foo {self x}+ x { ^ 'T1'}

T2+ bar {self x}+ x { ^ 'T2'}

T2 freeze x

+ x {^'C'}Composer

T1+ foo {self x}- x { ^ 'T1'}

T2+ bar {self x}- x { ^ 'T2'}

Conflict resolution via method redefinition in Composer

Composer new foo -> 'C'Composer new bar -> 'C'Composer new x -> 'C'

Composer

Unfreezing T1 x and freezing T2 x

Composer new foo -> 'T1'Composer new bar -> 'T2'Composer new x -> 'T1'

T1+ foo {self x}- x { ^ 'T1'}

T2+ bar {self x}+ x { ^ 'T2'}

T1 unfreeze x

T2 freeze x

T1 freeze x

T1 unfreeze xT2 unfreeze x

Page 31: Presentation of Traits

Map

Traits

Encapsulation policies

Stateful traits

Freezable traits

Pure traitslanguageecoop’03

oopsla’03icse’04toplas

ecoop’04

Jour. of Comp. Lang., Sys. Struct.

oopsla’07

Page 32: Presentation of Traits

Conclusion

• Traits are interesting constructs

• But

- Need more experience building complex software

- Do we get patterns (composition vs. inheritance)?

• Less operators?

• A trait-based only language

Page 33: Presentation of Traits

A trait is:-a group of methods

-may be composed with other traits- may be used by classes

in order to share behavior

http://www.iam.unibe.ch/~scg/Research/Traits/

or simply ask google