52
12. Traits and Classboxes

12. Traits and Classboxes. © Oscar Nierstrasz ST — Traits and Classboxes 12.2 Roadmap Problems with Inheritance Traits Refactoring Collections with

  • View
    223

  • Download
    0

Embed Size (px)

Citation preview

12. Traits and Classboxes

© Oscar Nierstrasz

ST — Traits and Classboxes

12.2

Roadmap

> Problems with Inheritance> Traits> Refactoring Collections with Traits> Traits in Squeak> Classboxes> Traits and Classboxes > Ongoing Research

Selected material courtesy of Nathanael Schaerli and Alexandre BergelSelected material courtesy of Nathanael Schaerli and Alexandre Bergel

© Oscar Nierstrasz

ST — Traits and Classboxes

12.3

Roadmap

> Problems with Inheritance> Traits> Refactoring Collections with Traits> Traits in Squeak> Classboxes> Traits and Classboxes > Ongoing Research

© Oscar Nierstrasz

ST — Traits and Classboxes

12.4

How Can We Implement This?

Circle

Visual

BorderedCircle BorderedRectangle

Rectangle

Bordered Bordered

Circle Rectangle

BorderedBorderedBordered

© Oscar Nierstrasz

ST — Traits and Classboxes

12.5

Alternative Approaches

> Single inheritance leads to code duplication> Alternatives:

— Multiple inheritance— Mixins

© Oscar Nierstrasz

ST — Traits and Classboxes

12.6

Problems with Multiple Inheritance

> Multiple Inheritance problems— No access to super (ill-defined)

– Workarounds are clumsy or lead to duplicated code

— Complex rules for resolving conflicts (esp. state)— Fragile hierarchy

– Changes may impact distant classes

Ducasse, et al., "Traits: A Mechanism for fine-grained Reuse", TOPLAS 2006Ducasse, et al., "Traits: A Mechanism for fine-grained Reuse", TOPLAS 2006

© Oscar Nierstrasz

ST — Traits and Classboxes

12.7

Problems with Mixins

> Mixin problems— Dispersal of glue code

– Conflict resolution is sensitive to mixin composition order– Composing entity has no control!

— Fragile hierarchy– Changes may impact distant classes

Ducasse, et al., "Traits: A Mechanism for fine-grained Reuse", TOPLAS 2006Ducasse, et al., "Traits: A Mechanism for fine-grained Reuse", TOPLAS 2006

© Oscar Nierstrasz

ST — Traits and Classboxes

12.8

Roadmap

> Problems with Inheritance> Traits> Refactoring Collections with Traits> Traits in Squeak> Classboxes> Traits and Classboxes > Ongoing Research

© Oscar Nierstrasz

ST — Traits and Classboxes

12.9

Traits

Circle

Rectangle

Polygon

Colored

Bordered

Traits =Building Blocks

Circle Rectangle Polygon

Circle Colored Bordered

Rectangle Colored+

+ +

© Oscar Nierstrasz

ST — Traits and Classboxes

12.10

Traits in a nutshell

> Traits are parameterized behaviors— Traits provide a set of methods ( )— Traits require a set of methods ( )— Traits do not specify any state

TCircleareaboundscircumferencediameterhash

radiusradius:centercenter:

© Oscar Nierstrasz

ST — Traits and Classboxes

12.11

Using Traits to Compose Classes

ColoredCircle

Visual

TCircle

TColor

Class = Superclass + State + Traits + Glue methods Class = Class = Superclass Class = Superclass + State Class = Superclass + State + Traits

rgb radius center

The composing class retains control of the composition.

The composing class retains control of the composition.

© Oscar Nierstrasz

ST — Traits and Classboxes

12.12

Composition Rules

1. Class methods take precedence over trait methods2. Composition is commutative

— Conflict resolution is always explicit

3. Flattening Property— Trait methods have no special semantics

© Oscar Nierstrasz

ST — Traits and Classboxes

12.13

Rule 1: Precedence of Class Methods

ColoredCircle

TCircle

areahash...

radiuscenter...

TColor

invertred...

rgb...

rgbradius center

radiuscenter...

rgb...

areahash...

radiuscenter...

rgb...

areahash...

radiuscenterrgb

hash

hash ^ self radius hash bitXor: self center hash

© Oscar Nierstrasz

ST — Traits and Classboxes

12.14

Composition Rules

1. Class methods take precedence over trait methods2. Composition is commutative

— Conflict resolution is always explicit

3. Flattening Property— Trait methods have no special semantics

© Oscar Nierstrasz

ST — Traits and Classboxes

12.15

Rule 2: Explicit Conflict Resolution

ColoredCircle

TCircle

hash ...

TColor

hash ...

1) Override the conflict with a glue method— Aliases provide access to conflicting methods

2) Exclude conflicting methods

hash

hash

hash

hash -> circleHash

hash -> colorHash

© Oscar Nierstrasz

ST — Traits and Classboxes

12.16

Composition Rules

1. Class methods take precedence over trait methods2. Composition is commutative

— Conflict resolution is always explicit

3. Flattening Property— Trait methods have no special semantics

© Oscar Nierstrasz

ST — Traits and Classboxes

12.17

Rule 3: Flattening Property

Circle

radiuscenter TCircle

radiuscenter...

radius center

Visual

hash

area ^ self radius squared

areadiameterhash

hash ^ super hash bitXor: self radius hashdiameter ^ self radius * 2

area ^ self radius squareddiameter ^ self radius * 2

© Oscar Nierstrasz

ST — Traits and Classboxes

12.18

Roadmap

> Problems with Inheritance> Traits> Refactoring Collections with Traits> Traits in Squeak> Classboxes> Traits and Classboxes > Ongoing Research

© Oscar Nierstrasz

ST — Traits and Classboxes

12.19

Problems with the Smalltalk Collections Hierarchy

> The ST collection hierarchy suffers from:— Duplicated code— Methods implemented too high in the hierarchy— Inappropriate inheritance— Incomplete protocols

© Oscar Nierstrasz

ST — Traits and Classboxes

12.20

Methods implemented “too high”

Collection

Sequenceable-Collection

ArrayHeapSet

add:addAll:remove:removeAll:

add:addAll:remove:removeAll:

add:addAll:remove:removeAll:

add:

remove:

Array

add: anObject self shouldNotImplement

remove: anObject self shouldNotImplement

add:addAll:remove:removeAll:

addAll: aCollection aCollection do: [:each | self add: each].

© Oscar Nierstrasz

ST — Traits and Classboxes

12.21

Inappropriate Inheritance

Set

sizeunion:remove:removeAll:...

Dictionary

remove:removeAll:...

sizeunion:...

remove: anObject self shouldNotImplement

removeAll: anObject self shouldNotImplement

sizeunion:remove:removeAll:...

> Hard to see the real interfaceof a class

> Unexpected runtime errors

© Oscar Nierstrasz

ST — Traits and Classboxes

12.22

Classifying the Collection Classes

> Many different classification criteria— Order

– unordered (Set)– explicitly ordered (LinkedList)– implicitly ordered (Heap)

— Extensibility– fixed size (Array)– variable size (OrderedCollection)

— Mutability– immutable (String)– mutable (the others)

— Comparison– using “identity” (IdentitySet)– using “equals” (Set)

© Oscar Nierstrasz

ST — Traits and Classboxes

12.23

ImplicitlyOrdered

Linked

Extensible

ExplicitlyOrdered

ArrayBased

Refactoring Strategy

> Create traits for the identified properties> Combine them to build the collection classes

Extensible

ExplicitlyOrdered

ArrayBased

CollectionFunctionalproperties

Implementationproperties

Extensible

ExplicitlyOrdered

ArrayBased

© Oscar Nierstrasz

ST — Traits and Classboxes

12.24

Facilities supported by all collection classes Common combinations

of functional traitsConcrete classes addingimplementation traits

© Oscar Nierstrasz

ST — Traits and Classboxes

12.25

What Did We Gain?

> Consistent hierarchies— No inappropriate inheritance— No methods implemented too high (before ~10%)— Protocols are uniform and complete

> Less code— Refactored 38 classes with 1252 methods— Created a total of 67 traits— After the refactoring

~ 10% less source code > 20% fewer methods

> Improved Reusability— “Toolbox of traits” makes it easy to build new classes

Black, et al., “Applying Traits to the Smalltalk Collection Hierarchy,” OOPSLA 2003Black, et al., “Applying Traits to the Smalltalk Collection Hierarchy,” OOPSLA 2003

© Oscar Nierstrasz

ST — Traits and Classboxes

12.26

Roadmap

> Problems with Inheritance> Traits> Refactoring Collections with Traits> Traits in Squeak> Classboxes> Traits and Classboxes > Ongoing Research

© Oscar Nierstrasz

ST — Traits and Classboxes

12.27

Traits in Squeak

> Language Extension— Extended the language kernel to represent traits— Modified the compilation process for classes

built from traits

> No changes to the Squeak VM— Essentially no runtime performance penalty— Except indirect instance variable access— But: This is common practice anyway

> No duplication of source code> Small amount of byte-code duplication

— Only methods with super-sends

© Oscar Nierstrasz

ST — Traits and Classboxes

12.28

Traits in Squeak 3.9

Object subclass: #Behavioruses: TPureBehavior @

{ #basicAddTraitSelector:withMethod:-> #addTraitSelector:withMethod: }

instanceVariableNames: 'superclass methodDict formattraitComposition localSelectors'

classVariableNames: 'ObsoleteSubclasses'poolDictionaries: ''category: 'Kernel-Classes'

Object subclass: #Behavioruses: TPureBehavior @

{ #basicAddTraitSelector:withMethod:-> #addTraitSelector:withMethod: }

instanceVariableNames: 'superclass methodDict formattraitComposition localSelectors'

classVariableNames: 'ObsoleteSubclasses'poolDictionaries: ''category: 'Kernel-Classes'

© Oscar Nierstrasz

ST — Traits and Classboxes

12.29

Practical Impact of Traits

> Perl— Traits were ported to Perl 5 (by Stevan Little)— Traits are planned as a standard feature of Perl 6

> VisualWorks Smalltalk— Traits were ported to VW (by Terri Raymond)

> Scala (developed at EPFL)— Traits are a built-in language feature of Scala— Fully integrated into the static type system

> .NET— Microsoft Research Project to bring traits to C#

© Oscar Nierstrasz

ST — Traits and Classboxes

12.30

Roadmap

> Problems with Inheritance> Traits> Refactoring Collections with Traits> Traits in Squeak> Classboxes> Traits and Classboxes > Ongoing Research

© Oscar Nierstrasz

ST — Traits and Classboxes

12.31

Class Extension

> A Class Extension is the ability to add or redefine methods on a class after its creation— Solves a different problem than subclassing

– Clients of existing classes see the extensions

— Common in dynamic languages like CLOS and Smalltalk

© Oscar Nierstrasz

ST — Traits and Classboxes

12.32

Visitor example

BlackPackage

Opr

Add Mult

acceptVisitor()

acceptVisitor() acceptVisitor()

BluePackage

VisitordoAdd()doMult()

© Oscar Nierstrasz

ST — Traits and Classboxes

12.33

Subclassing does not Solve it

Opr

Add Mult

Parserparse()

Add.new()……

Subclasses are not referenced by the tree constructor

Add’ Mult’acceptVisitor() acceptVisitor()

© Oscar Nierstrasz

ST — Traits and Classboxes

12.34

In Smalltalk

> Class extensions are global— Any application can modify any class in the system

Consequences:— Conflicts may arise

– e.g., two applications may add the same method— System fragility

– e.g., an application may redefine a critical method

Problems:— How to control class extensions?— How to apply a set of unanticipated changes without breaking

existing clients?

© Oscar Nierstrasz

ST — Traits and Classboxes

12.35

Classboxes

> A Classbox— Is a unit of scoping

– I.e., a namespace

— Can define classes— Can import class definitions from other classboxes— Can define class extensions

– I.e., methods on classes in scope

> Definitions are local to the classbox that introduces them— Changes only impact the classbox itself and classboxes that

explicitly import its definitions

© Oscar Nierstrasz

ST — Traits and Classboxes

12.36

Classboxes: Avoiding Conflict

Since class extensions local to a classbox, conflicts are avoided

TextClassbox

String

import

WWWClassboxWWWURL

StringasUrl

WWWURL.new()

URLClassboxURL

StringasUrl

URL.new()

© Oscar Nierstrasz

ST — Traits and Classboxes

12.37

Classboxes: Import and Visibility

Extensions can be imported by other classboxes

TextClassbox

String

import

URLClassboxURL

StringasUrl

RedClassbox…url = “http://www.iam.unibe.ch/~scg”.asUrl()

© Oscar Nierstrasz

ST — Traits and Classboxes

12.38

Classbox as a Sandbox

CollectionClassbox

OrderedCollection

import

do()

A classbox establishes a purely local scope for extensions, so they cannot break applications that do not import the extensions.

Cfoo()

aCollection.do(…)

C.new().foo()

GreenClassboxOrderedCollectiondo()

© Oscar Nierstrasz

ST — Traits and Classboxes

12.39

Local consistency

Any expression executed in a classbox will be evaluated from the perspective of that classbox alone.

CollectionClassboxOrderedCollection

import

do()copy()

OrderedCollectiondo()

C

3

1

aCollection.copy(…)

bar()

GreenClassbox

2

self.do(element.copy())

C.new().bar()

© Oscar Nierstrasz

ST — Traits and Classboxes

12.40

From within the Green Classbox

aCollection.copy(…)

C.new().bar()

self.do(element.copy()) OrderedCollectiondo()

C1

3

bar()

GreenClassbox

2copy()

© Oscar Nierstrasz

ST — Traits and Classboxes

12.41

Implementation

> Implemented in Squeak, an open-source Smalltalk— New method lookup to take classboxes into account

– Originating classbox– Collection of all the traversed classboxes – Import before inheritance

— Intensive use of reflection:– Reification of the method calls stack– Message passing control

© Oscar Nierstrasz

ST — Traits and Classboxes

12.42

Roadmap

> Problems with Inheritance> Traits> Refactoring Collections with Traits> Traits in Squeak> Classboxes> Traits and Classboxes > Ongoing Research

© Oscar Nierstrasz

ST — Traits and Classboxes

12.43

Traits + Classboxes

> Collaborating traits should be applied to a set of classes— Use classboxes to encapsulate and apply

Bergel and Ducasse, “Supporting Unanticipated Changes with Traits and Classboxes,” NODE 2005Bergel and Ducasse, “Supporting Unanticipated Changes with Traits and Classboxes,” NODE 2005

© Oscar Nierstrasz

ST — Traits and Classboxes

12.44

Cross-Cutting Collaborations

> Used to describe cross-cutting features by layering an application into collaborations [Holland, ECOOP 92].— A role is a set of features intended to be applied to a class.— A collaboration is a set of roles intended to be applied to

another collaboration.

> With Mixin-layers [Batory, ECOOP 98]:— a role is a mixin— a collaboration is a parametrized class

> With Traits and Classboxes— A role is encapsulated as a trait— A collaboration is encapsulated as a classbox

© Oscar Nierstrasz

ST — Traits and Classboxes

12.45

Example: Graph Application using Inheritance

UndirectedGraph

Graph Vertex

CycleChecking

GraphCycle VertexCycleWorkspace

ConnectedRegion

GraphRegions VertexRegionsWorkRegions

© Oscar Nierstrasz

ST — Traits and Classboxes

12.46

UndirectedGraph

Graph VertexTUGraph TVertexAdj

The Graph Application using Traits/Classboxes

CycleChecking

Graph VertexWorkspaceGraphDFT VertexDFTWNumber

ConnectedRegion

Graph VertexWorkspaceWRegions GraRegions VerRegions

© Oscar Nierstrasz

ST — Traits and Classboxes

12.47

Gain with Traits and Classboxes

> No subclasses— Identity of participant preserved.

> A collaboration can be used to defined unanticipated change— Scope of change is limited to extending classbox and clients

> Bounded visibility of extensions— Multiple versions of classes can be simultaneously active in the

system

© Oscar Nierstrasz

ST — Traits and Classboxes

12.48

Roadmap

> Problems with Inheritance> Traits> Refactoring Collections with Traits> Traits in Squeak> Classboxes> Traits and Classboxes > Ongoing Research

© Oscar Nierstrasz

ST — Traits and Classboxes

12.49

Ongoing research

> Scoped reflection— Restricting both availability and effect of reflection to given

scope

> Changeboxes— Encapsulating changes, not just extensions— For both forward- and reverse-engineering

> Context-oriented programming— Software systems whose behaviour is context-dependent

© Oscar Nierstrasz

ST — Traits and Classboxes

12.50

What you should know!

Why does single inheritance lead to duplicated code? How does the composing class retain control of trait

composition? What do “glue” methods do for traits? What is the “flattening property” and why is it important

for traits? Why is there “inappropriate inheritance” in the Smalltalk

Collections hierarchy? What is a “class extension”? In what way to classboxes ensure locality of changes? What problems are solved by combined traits and

classboxes?

© Oscar Nierstrasz

ST — Traits and Classboxes

12.51

Can you answer these questions?

Why do multiple inheritance and mixins leads to “fragile class hierarchies”?

C++, Eiffel and Python all offer multiple inheritance – are they broken?

Why don’t traits specify any state? How much code is duplicated in the standard Java

libraries? What problems occur in Java due to the lack of class

extensions? Can classboxes be “flattened” in the same way that traits

can? Why or why not?

© Oscar Nierstrasz

ST — Traits and Classboxes

12.52

License

> http://creativecommons.org/licenses/by-sa/2.5/

Attribution-ShareAlike 2.5You are free:• to copy, distribute, display, and perform the work• to make derivative works• to make commercial use of the work

Under the following conditions:

Attribution. You must attribute the work in the manner specified by the author or licensor.

Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a license identical to this one.

• For any reuse or distribution, you must make clear to others the license terms of this work.• Any of these conditions can be waived if you get permission from the copyright holder.

Your fair use and other rights are in no way affected by the above.

Attribution-ShareAlike 2.5You are free:• to copy, distribute, display, and perform the work• to make derivative works• to make commercial use of the work

Under the following conditions:

Attribution. You must attribute the work in the manner specified by the author or licensor.

Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a license identical to this one.

• For any reuse or distribution, you must make clear to others the license terms of this work.• Any of these conditions can be waived if you get permission from the copyright holder.

Your fair use and other rights are in no way affected by the above.