context traits: dynamic behaviour adaptation through run...

12
Context Traits Dynamic Behaviour Adaptation Through Run-Time Trait Recomposition Sebastián González, Kim Mens ICTEAM Institute Université catholique de Louvain, Belgium {s.gonzalez,kim.mens}@uclouvain.be Marius Col ˘ acioiu, Walter Cazzola Department of Computer Science Università degli Studi di Milano, Italy {cazzola,colacioiu}@di.unimi.it ABSTRACT Context-oriented programming emerged as a new paradigm to support fine-grained dynamic adaptation of software beha- viour according to the context of execution. Though existing context-oriented approaches permit the adaptation of in- dividual methods, in practice behavioural adaptations to specific contexts often require the modification of groups of interrelated methods. Furthermore, existing approaches impose a composition semantics that cannot be adjusted on a domain-specific basis. The mechanism of traits seems to provide a more appropriate level of granularity for defining adaptations, and brings along a flexible composition mechan- ism that can be exploited in a dynamic setting. This paper explores how to achieve context-oriented programming by using traits as units of adaptation, and trait composition as a mechanism to introduce behavioural adaptations at run time. First-class contexts reify relevant aspects of the envir- onment in which the application executes, and they directly influence the trait composition of the objects that make up the application. To resolve conflicts arising from dynamic composition of behavioural adaptations, programmers can explicitly encode composition policies. With all this, the notion of context traits offers a promising approach to im- plementing dynamically adaptable systems. To validate the context traits model we implemented a JavaScript library and conducted case studies on context-driven adaptability. Categories and Subject Descriptors D.3.3 [Programming Languages]: Language Constructs and Features General Terms Design, Languages Keywords Context-oriented programming; Dynamic composition; Run- time behaviour adaptation; Software traits Permission to make digital or hard copies of all or part of this work for personal or classroom use is granted without fee provided that copies are not made or distributed for profit or commercial advantage and that copies bear this notice and the full citation on the first page. To copy otherwise, to republish, to post on servers or to redistribute to lists, requires prior specific permission and/or a fee. AOSD’13, March 24–29, 2013, Fukuoka, Japan. Copyright 2013 ACM 978-1-4503-1766-5/13/03 ...$15.00. 1. INTRODUCTION Observing that traditional programming languages do not facilitate the construction of adaptable applications, Context- Oriented Programming (COP) [7] has emerged as a response by providing dedicated programming abstractions to define context-specific behaviour. Such behaviour can be recom- posed dynamically when context changes are detected, so that applications can adapt to their varying circumstances of use. From a software engineering perspective, COP avoids both scattering and tangling of context-dependent beha- viour throughout a program. Indeed, COP was born as a light-weight alternative to Aspect-Oriented Programming [6], albeit for a narrower family of languages. Whereas existing COP approaches are fine grained in that they permit the adaptation of individual methods, methods seldom make sense on their own. Methods often come in groups of related functionality that should be adapted in unison. A typical example of this are the push, pop and isEmpty methods of stack data structures. Given that meth- ods seldom work as isolated units, it would be more natural to adapt objects through slightly coarser-grained units of behaviour. Such units would make it easier to define coher- ent adaptations, because adaptations for methods that work together would also be bundled together. When it comes to composing adaptations, typical COP approaches impose a layering order such that more recently activated layers overshadow the methods from less recently activated ones. This makes sense in most cases, though it precludes domain-specific compositions in which different orderings are needed. Traditional composition approaches such as mixins [3] and multiple inheritance [1] also provide insufficient control to reach a desired composition for every situation. In the case of mixins, mixins earlier in the inherit- ance chain are overshadowed by mixins appearing afterwards. With multiple inheritance, conflict resolution is fixed by the chosen method lookup mechanism. The previous observations make of traits [8] a natural fit as behavioural units of adaptation. Traits are at the right level of abstraction for adaptability, because their intention is pre- cisely to group methods that make sense together and are as cohesive as possible. Furthermore, traits have been conceived to expose composition conflicts, rather than automatically solving them through some fixed strategy imposed by inher- itance or layering. Since any possible method combination can be obtained if needed, traits open up new possibilities for behaviour reconfiguration and thus foster adaptability. The main contribution of this paper is a proposal for man- aged object recomposition at run time, aimed at supporting 209

Upload: others

Post on 15-Jul-2020

3 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Context traits: dynamic behaviour adaptation through run ...homes.di.unimi.it/~cazzola/pubs/aosd13- · of applications can adapt. More specialised contexts are of course also possible

Context Traits

Dynamic Behaviour Adaptation Through Run-Time Trait Recomposition

Sebastián González, Kim MensICTEAM Institute

Université catholique de Louvain, Belgium{s.gonzalez,kim.mens}@uclouvain.be

Marius Colacioiu, Walter CazzolaDepartment of Computer Science

Università degli Studi di Milano, Italy{cazzola,colacioiu}@di.unimi.it

ABSTRACTContext-oriented programming emerged as a new paradigmto support fine-grained dynamic adaptation of software beha-viour according to the context of execution. Though existingcontext-oriented approaches permit the adaptation of in-dividual methods, in practice behavioural adaptations tospecific contexts often require the modification of groupsof interrelated methods. Furthermore, existing approachesimpose a composition semantics that cannot be adjusted ona domain-specific basis. The mechanism of traits seems toprovide a more appropriate level of granularity for definingadaptations, and brings along a flexible composition mechan-ism that can be exploited in a dynamic setting. This paperexplores how to achieve context-oriented programming byusing traits as units of adaptation, and trait composition asa mechanism to introduce behavioural adaptations at runtime. First-class contexts reify relevant aspects of the envir-onment in which the application executes, and they directlyinfluence the trait composition of the objects that make upthe application. To resolve conflicts arising from dynamiccomposition of behavioural adaptations, programmers canexplicitly encode composition policies. With all this, thenotion of context traits offers a promising approach to im-plementing dynamically adaptable systems. To validate thecontext traits model we implemented a JavaScript libraryand conducted case studies on context-driven adaptability.

Categories and Subject DescriptorsD.3.3 [Programming Languages]: Language Constructsand Features

General TermsDesign, Languages

KeywordsContext-oriented programming; Dynamic composition; Run-time behaviour adaptation; Software traits

Permission to make digital or hard copies of all or part of this work forpersonal or classroom use is granted without fee provided that copies arenot made or distributed for profit or commercial advantage and that copiesbear this notice and the full citation on the first page. To copy otherwise, torepublish, to post on servers or to redistribute to lists, requires prior specificpermission and/or a fee.AOSD’13, March 24–29, 2013, Fukuoka, Japan.Copyright 2013 ACM 978-1-4503-1766-5/13/03 ...$15.00.

1. INTRODUCTIONObserving that traditional programming languages do not

facilitate the construction of adaptable applications, Context-Oriented Programming (COP) [7] has emerged as a responseby providing dedicated programming abstractions to definecontext-specific behaviour. Such behaviour can be recom-posed dynamically when context changes are detected, sothat applications can adapt to their varying circumstancesof use. From a software engineering perspective, COP avoidsboth scattering and tangling of context-dependent beha-viour throughout a program. Indeed, COP was born as alight-weight alternative to Aspect-Oriented Programming [6],albeit for a narrower family of languages.

Whereas existing COP approaches are fine grained in thatthey permit the adaptation of individual methods, methodsseldom make sense on their own. Methods often come ingroups of related functionality that should be adapted inunison. A typical example of this are the push, pop andisEmpty methods of stack data structures. Given that meth-ods seldom work as isolated units, it would be more naturalto adapt objects through slightly coarser-grained units ofbehaviour. Such units would make it easier to define coher-ent adaptations, because adaptations for methods that worktogether would also be bundled together.

When it comes to composing adaptations, typical COPapproaches impose a layering order such that more recentlyactivated layers overshadow the methods from less recentlyactivated ones. This makes sense in most cases, though itprecludes domain-specific compositions in which differentorderings are needed. Traditional composition approachessuch as mixins [3] and multiple inheritance [1] also provideinsufficient control to reach a desired composition for everysituation. In the case of mixins, mixins earlier in the inherit-ance chain are overshadowed by mixins appearing afterwards.With multiple inheritance, conflict resolution is fixed by thechosen method lookup mechanism.

The previous observations make of traits [8] a natural fit asbehavioural units of adaptation. Traits are at the right levelof abstraction for adaptability, because their intention is pre-cisely to group methods that make sense together and are ascohesive as possible. Furthermore, traits have been conceivedto expose composition conflicts, rather than automaticallysolving them through some fixed strategy imposed by inher-itance or layering. Since any possible method combinationcan be obtained if needed, traits open up new possibilitiesfor behaviour reconfiguration and thus foster adaptability.

The main contribution of this paper is a proposal for man-aged object recomposition at run time, aimed at supporting

209

Page 2: Context traits: dynamic behaviour adaptation through run ...homes.di.unimi.it/~cazzola/pubs/aosd13- · of applications can adapt. More specialised contexts are of course also possible

the adaptation of software to its context of use. In responseto context changes, the composition of objects is modified toopportunistically improve or gracefully degrade the globalbehaviour of a system. To achieve this goal, we propose anovel context traits model, which as its name suggests is atthe crossroads of COP and traits. Both of these compositionmechanisms deal with important limitations of current-dayprogramming languages: COP provides the necessary ma-chinery to reify contexts and adapt behaviour dynamically,and traits provide a convenient unit of composition withwell-defined composition semantics. To fully integrate theCOP and trait worlds, we build a causal connection betweencontexts and object compositions, so that context changesdetected in the environment are reflected directly as changesin the composition of objects. To manage such a dynamic sys-tem, we allow the definition of custom composition policies.

Since our approach proposes a highly dynamic object mod-el, we chose JavaScript as implementation medium to proto-type and test our ideas. The object core of JavaScript provedto be a good paradigmatic match to support the semanticswe were after. However, to emphasise that the approachcould be implemented in other object-based languages aswell, the paper clearly separates the description of conceptsfrom their implementation in JavaScript. For validation weimplemented three case studies, each targeted at assessingdifferent properties of the approach. From the experience wehave gathered so far, context traits seem to bring advantagesthat cannot be observed in the COP and trait worlds alone.

The next section gives a conceptual description of ourapproach. Section 3 then outlines our current implementationin JavaScript. Section 4 explains how we validated theapproach through case studies. Section 5 discusses designissues and future work. Finally, we present related approachesin Section 6, and conclude the paper in Section 7.

2. CONTEXT TRAITSToday’s software systems call for new computation models

in which objects can adapt dynamically to the changingcircumstances in which they run. In such a vision, objectscan be regarded as evolving entities that are shaped by theirenvironment —much like real life evolution shapes livingentities in natural ecosystems. Under this metaphor, it isnatural to think of objects as evolving compositions of traits,which are selected so that the object fits better in its changinglogical and physical environment. This section explains suchan adaptation mechanism, starting from core concepts andbuilding up to the complete approach.

2.1 Contexts as Situation ReifiersStandard object-oriented analysis prescribes that concepts

found in the application domain that are relevant to theapplication should be modelled and represented explicitly asobjects [16]. Following this principle, when some situation isof importance to an application and could potentially affectits behaviour, it should be modelled and given first-classstatus, just as any other relevant concept in the applicationdomain. This is precisely what we do. We put forward thecircumstances under which a software system executes as first-class entities that can be dealt with by the software. We thusdefine context objects as representations of the particularsituations in which the system may execute [10]. This isin line with dictionary definitions of context such as “thesituation within which something exists or happens, and

that can help explain it”1 and “the interrelated conditions inwhich something exists or occurs”.2

Example: A context BusyCPU can reify the situationthat the CPU is highly loaded at the moment. A Connectedcontext is for situations in which there is Internet connectivity.These are general contexts with respect to which a large classof applications can adapt. More specialised contexts areof course also possible. In the case of JavaScript, a Firefoxcontext can model the situation that the program is runningunder such web browser, whereas a context NodeJS signifiesthat the script is running on the server-side using the node.jsframework.

A context becomes active when it is detected that thesituation it reifies is taking place, and is otherwise inactive.The detection of such situations, and thus the triggering ofactivation and deactivation of contexts, is usually signalledthrough events. Events can come from a graphical user in-terface, network discovery service, sensor polling mechanism,and so forth. Context changes might also be triggered whenreceiving client requests from the network, or even internallyby applications themselves when a logical situation changeswithin their own execution. However diverse these sourcesmight be, the precise origin of context changes is irrelevantfor the sake of this paper. All what matters for our pur-poses is that contexts are activated and deactivated to reflectas closely as possible the situation under which the systemexecutes.

To manage the activation dynamics of contexts, every con-text has an activation count that is incremented for eachactivation request and correspondingly decremented for eachdeactivation request. The context becomes inactive onlywhen the count reaches zero, and is otherwise active. Adeactivation request of an inactive context makes no sense,since a situation cannot cease to exist if it was not occurringin the first place; for this reason, such a request is consideredan error. However, it can very well be that a context isactivated at some point and never deactivated again duringthe lifetime of a system. Hence, the number of activations isalways greater or equal than that of deactivations. Activa-tion counts help us deal with situations that can be causedby different occurrences of the same event. Such multiply-occurring situations hold until their last cause disappearsfrom the environment.3

Example: A Connected context should remain active foras long as there is WiFi, 3G, Edge, or Ethernet connectivity.Connected is deactivated when none of the connectivity mediaare available. Examples of single-activation contexts areLowBattery (activated when the remaining battery chargegoes below a certain threshold) and Firefox (activated whenit is detected that the application is running in such browser).Firefox is also an example of a permanent context, whichremains active for as long as the system runs.

The prototypical environment of execution of the applic-ation is modelled through a Default context. The Defaultcontext is not just a straightforward application of the prin-ciple that relevant situations should be modelled explicitly,but also it brings formal and technical advantages discussedfurther in the paper. When in Default context, objects cor-respondingly exhibit their prototypical behaviour [14]. Beha-

1http://dictionary.cambridge.org/dictionary/british/context 12http://merriam-webster.com/dictionary/context3Note that activation counts are not related to concurrency,despite their superficial resemblance to semaphores.

210

Page 3: Context traits: dynamic behaviour adaptation through run ...homes.di.unimi.it/~cazzola/pubs/aosd13- · of applications can adapt. More specialised contexts are of course also possible

tagNamehreftype. . . attributesAnchorElementAnchorElement

tagNamehreftype. . .

attributes

htmlString tagNameattributeschildrenSerializableElementSerializableElement

htmlString tagNameattributeschildren

parentattributeschildren. . . tagNameElementElement

parentattributeschildren. . .

tagName

Figure 1: Traits for an HTML DOM library.

vioural adaptations to other contexts are usually expressedas variations with respect to default behaviour. We explainnext the terms in which such default and adapted behaviourcan be defined.

2.2 Traits as Basic Behavioural UnitsThe kind of objects we propose for dynamic software ad-

aptation are composed of traits [8]. Traits are behaviouralunits originally designed to facilitate software reuse. Theyare finer-grained than whole objects, because traits containfunctionality that is as small and cohesive as possible. Forinstance, a Stack trait can contain the typical push, pop andisEmpty operations of any stack-like data structure —nothingmore. Whole objects, in contrast, usually have broader func-tionality, some of which is shared with other objects. Forinstance, a full stack object normally features all base meth-ods from its Collection hierarchy.4

The model of traits we use is a slight variation of theoriginal [8], since our model is meant for classless objects,and more importantly, our emphasis is not on reuse butrather on dynamic recomposition. At the core, our notionof trait is defined just like in classical traits, including theirformalisation [8]. Intuitively, a trait provides a minimal set ofmethods that semantically go together, and requires certainmethods that it uses to fill in the remaining details of itsinternal implementation. Required methods are left open bytrait developers for customisation by clients, akin to hookmethods in traditional object-oriented frameworks.

Example: The depictions in Figure 1 are part of a trait-based design of a Document Object Model (DOM). For eachtrait, the methods on the left of the box are provided, andthose on the right are required. The Element trait providesthe bare minimum any DOM node must have, namely accessto the parent, attributes and children of the node. However,since it is a generic node, the tagName is unspecified (i.e. itis required). The AnchorElement trait models a hypertextlink, which knows its tagName (in this particular case, ’a’)and anchor-specific attributes such as href and type. It readsthe necessary information from a required attributes struc-ture. Finally, the SerializableElement trait provides a methodhtmlString which produces a representation of the node <tag-Name attr1=”...”, attr2=”...”>...</tagName>, provided thatit has access to the necessary properties.

Our model of traits benefits from simple object-basedunderpinnings. Unlike the classical model of traits, we haveno notion of dictionary , class and super-sends. Hence, therelatively complex interaction between traits and classes [8]

4In the Pharo dialect of Smalltalk, this amounts to 160methods.

parentattributeschildrentagNamehreftype. . .htmlStringSerializableAnchorElementSerializableAnchorElement

parentattributeschildrentagNamehreftype. . .htmlString

Figure 2: Result of Element + SerializableElement +AnchorElement, a plain trait composition.

needs not be considered (e.g. how methods of classes takeprecedence over methods of traits, and methods of traits overthose of superclasses). This removed complexity makes ourmodel simpler and homogeneous.

Formally, a trait is a function T : N → B∗ that maps aset of method names N to a set of method bodies B∗, justlike in classical traits [8]. The set B∗ includes an undefinedmethod (⊥) and an overspecified method (>) used to repres-ent respectively required methods and conflicting methods.A trait is free of conflicts if none of its methods is >.

Traits are composed by summing them (+ : T × T → T ),which amounts to taking the respective unions of all theirprovided and required methods. Since required methodsspecify only a signature and have no implementation, theycannot cause conflicts when composed. In contrast to re-quired methods, conflicts between provided methods mayarise if they share the same signature but have different im-plementations. Conflicts must be resolved explicitly, whichavoids the limitations of the automatic linearisation mech-anisms imposed by composition of mixins, and classes withmultiple inheritance [8].

Example: The trait composition Element + Serializable-Element + AnchorElement gives as result the trait Serializ-ableAnchorElement illustrated in Figure 2. It constitutes acomplete hypertext link that can be rendered as plain HTML,thanks to the provided method htmlString.

The main mechanism to avoid composition conflicts isoverriding (. : T × T → T ) of one trait over another. Sincewe don’t have the notion of dictionaries, our definition differsslightly from that of classical traits:

(T1 . T2)(a) =

{T2(a) if T1(a) = ⊥T1(a) otherwise

For cases in which overriding is not expressive enough, traitscan be modified through aliasing (→: T × (N ×N )→ T ),and exclusion (− : T × N → T ), which are defined as inclassical traits [8].

Thanks to the composition operators, the final result ofa trait composition may arbitrarily mix methods startingfrom a set of source traits {T0, . . . , Tn}. Such compositionspreserve the flattening property of traits [8], though rephrasedin object-based terms: for any object o composed of traits{T0, . . . , Tn}, every non-overridden method in a trait Ti hasthe same semantics as if it were implemented directly in theobject o in question.

2.3 Behaviour is State, and State is BehaviourThe distinction between state and behaviour in trait com-

position has been discussed in the past on a technical ground:state composition implies changing the memory layout of

211

Page 4: Context traits: dynamic behaviour adaptation through run ...homes.di.unimi.it/~cazzola/pubs/aosd13- · of applications can adapt. More specialised contexts are of course also possible

objects, whereas behaviour composition does not [2]. Putthis way, the distinction between state and behaviour seemsto be the symptom of a leaky abstraction: added conceptualcomplexity caused by underlying implementation concerns.The reason why state composition generally changes memorylayout, whereas behaviour does not, is that state is usuallyinlined in objects, whereas behaviour is usually stored indictionaries —a more flexible data structure. It has beendemonstrated long ago that the leak can be plugged whileretaining efficiency [5].

Given the previous observations, we do not distinguishstate and behaviour. In some sense, we could say that inour traits model everything is state, since methods can beregarded as plain object slots that happen to hold a methodbody instead of some other value. But we can also reverse thispoint of view and say that in our traits model everything isbehaviour , because methods are obviously behaviour and anyother value which is not a method can formally be regardedas a method whose only purpose is to return the value inquestion.5 It is clear that the views of traits-as-state andtraits-as-behaviour are not only reconcilable but are one andthe same under different formal and technical guises. Thedistinction between state and behaviour is thus irrelevantat the formal and design levels of our traits model and itscomposition system.

2.4 Objects as Context-Driven Trait Compos-itions

In our model, an object o ∈ O ⊂ T is a dynamicallyevolving composition of traits

o = TC0 · TC1 · · ·TCn

where each TCi is a trait containing the behaviour specific toa context Ci. We call this class of traits meant for context-driven adaptation context traits. Their composition operator(·) is introduced further on in this section. A trait TCi

becomes part of the composition of an object when thecorresponding context Ci becomes active, and is withdrawnwhen Ci becomes inactive. Given that objects are obtained aspure compositions of traits, it follows that objects themselvesare actually traits, albeit of a particular kind: objects mustbe complete, which means that they are free of conflicts andhave no required methods.

According to the previous view of objects, the behaviourof an object o in Default context must be contained in atrait TDefault. Since the Default context is always active,6 thecomposition of o will always contain TDefault. By conventionwe take C0 = Default, yielding

o = TDefault · TC1 · · ·TCn

When Default is the only active context (i.e. in prototypicalconditions), the object is identical to its default trait: o =TDefault. For this reason, TDefault must be free of conflicts andhave no required methods. The homogeneous treatment ofdefault behaviour as just another trait renders the conceptualmodel purer and simplifies its implementation.

It should be noted that our model does not preclude theoriginal use of traits for software modularisation and reuse,

5In this view of traits as pure behaviour, assigning a value toa method (e.g. point.x = 3) can be interpreted as replacingthe method’s body by another one (e.g. the body return 3).6Our model does not forbid the deactivation of the Defaultcontext, but we have not found a use so far.

since a context trait TC might be statically composed of othertraits. Although perfectly admissible, for the sake of dynamicadaptation such static compositions need not be exposedand considered. The static structure of traits is opaque(irrelevant) to the run-time composition infrastructure, whichneeds to manage only those traits that participate in thedynamically evolving composition of objects.

The run-time system uses a total object constitution func-tion constitution : L × C → T , to retrieve the trait T(l,C) =constitution(l, C) that adapts an object with identity l to acertain context C. T(l,C) = ∅ if the object designated byl has no adaptation for context C. When the identity l ofan object is immaterial, we omit it from the notation T(l,C)

and simply write TC , like we did earlier in this section. Alsofor simplicity, we overload constitution when applied to aset of contexts, such that it is mapped over the given set:T{C0,...,Cn} = {TC0 , . . . , TCn}.7 Thanks to the constitutionfunction, the system is able to retrieve the traits that makeup an object for any given set of active contexts.

Note that the constitution function is not necessarily inject-ive, meaning that two different contexts C1 and C2 can havea same associated trait T(l,C1) = T(l,C2) for a given objectl, and also that two different objects l1 and l2 can have thesame trait T(l1,C) = T(l2,C) for a given context C. In otherwords, a same trait can be reused as adaptation in differentcontexts and for different objects. Reusability of contexttraits can therefore leverage both the object-oriented andthe context-oriented axes of our approach.

The dynamic composition operator (·) used previously isinfix notation for the function composition : 2T → O whichtakes a set {TC0 , . . . , TCn} of traits and returns a composedobject o. Since composition takes a plain set as argument,the order in which traits are composed is irrelevant, andtherefore the dynamic composition operator is commutativeby definition. The dynamic composition function is definedas composition(S) = ΣPg(S), which is the summation8 of theconflict-free set of traits obtained by applying the global com-position policy Pg to the given set of traits S. Compositionpolicies are explained in Section 2.5.

The object constitution and object composition functionslead to the straightforward definition of the object definitionfunction, object : L× 2C → O, as the function compositionobject = composition · constitution. Quite literally, an objectis defined as the composition of its constitution. Applyingthe previous definitions this means

o(l,{C0,...,Cn}) = ΣPg({TC0 , . . . , TCn})

That is, an object is the controlled composition as per Pg

of its constituent traits for a certain set of active contexts.When the identity l of the object is immaterial, and assumingthat A = {C0, . . . , Cn} is the set of currently active contexts,we denote o(l,A) = object(l, A) simply as o, as was doneearlier in this section.

The definition of object emphasises that all what is constantto an object is its identity, since its behaviour (i.e. traitcomposition) changes according to context. Also, the objectfunction puts contexts in direct relationship with objectcompositions. The object function therefore plays a keyrole in establishing a causal connection [17] between the

7Naturally, this overloaded definition of the function hassignature constitution : L × 2C → 2T .8The Σ operator is just a convenient notation for the +operator introduced in Section 2.2.

212

Page 5: Context traits: dynamic behaviour adaptation through run ...homes.di.unimi.it/~cazzola/pubs/aosd13- · of applications can adapt. More specialised contexts are of course also possible

composition of the computational system and the situationor circumstances in which the system executes.9 Thanks tothis causal connection, the physical and logical environmentin which objects live literally shapes those objects, and as aresult, the system as a whole.

2.5 Composition PoliciesThe setting for which we use trait-based composition is

fundamentally different from the setting assumed by sim-ilar existing techniques. Whereas other approaches expectprogrammers to manually compose traits as a normal partof the application development cycle, we aim at composingtraits automatically during system execution, so that objectsare shaped according to their changing environment. In asystem that is already deployed and running, trait composi-tion cannot possibly be assisted, and thus any conflict arisingfrom trait composition must be handled by the system itself.Hence, the knowledge on how to resolve composition conflictsmust be somehow embedded into the system.

In our approach, developers can encode their strategies toconflict resolution as composition policies that the systemcan use during trait recomposition. Composition policiesthus encapsulate domain-specific knowledge needed to re-solve composition conflicts at run time. Through policies,developers can encode their conflict resolution strategies asfirst-class entities, and ship them together with the rest ofthe system or module they are developing.

A composition policy is a total function P : 2T → 2T thatmaps a possibly conflicting set of traits S = {T1, . . . , Tn} to apartial resolution set P (S) = {R1, . . . , Rn}. Policies are freeof side effects on their argument traits —that is, P does notalter the definition of the given traits T1, . . . , Tn in any way.The partial resolution traits Ri are the result of composingthe traits in S in a way the policy deems appropriate. Tothis end, policies use regular trait composition operators ex-clusively (i.e. summation, overriding, aliasing and exclusionexplained in Section 2.2). This means in particular thatpolicies do not introduce foreign traits to the trait set Sbeing composed.10

A (total) resolution R is a set containing exactly oneconflict-free trait resulting from application of a policy. Thetrait in a resolution R = P (S) can be used for compositioninstead of the original traits found in S. A policy P thatresolves every possible conflict set S to a total resolution Ris said to be general . General policies can hardly be domain-specific, since they should be able to resolve arbitrarily diversesets of traits. Section 2.6 gives an example of a general policy.

Composition of policies follows normal function compos-ition: given two policies P1 and P2, P1 · P2 is a composedpolicy. We call such compositions Pc = P1 · P2 · · ·Pn−1 · Pn

policy chains. A policy chain Pc processes a given conflict setin order, starting from Pn and going through the chain untilP1 yields the final partial resolution of the original conflictset. Policy chains allow the aggregation of independentlydeveloped resolution strategies.

9The other key ingredient needed to establish this causal con-nection is the function that detects changes in the executionenvironment through events, and triggers context activationsaccordingly. As mentioned in Section 2.1 however, this paperdoes not discuss context detection.

10This might seem like a strong limitation, but our goal is tokeep a simple semantics such that traits are introduced in acomposition only because of active contexts, not policies.

The context-driven composition machinery of our approachuses a global policy chain Pg to resolve conflicts. Each partialpolicy Pi that makes up Pg encodes a particular (possiblydomain-specific or object-specific) strategy to solving con-flicts. To make sure that conflicts are always resolved, thesystem closes the chain with a general default policy Pd

that will solve any remaining conflict not handled by policiesearlier in the chain. The global policy chain Pg = Pd·P1 · · ·Pn

is thus never empty, since it contains at least Pd.

2.6 Resolution by Activation AgeThe general policy that we have found to make the most

sense to be used as default policy Pd relies on the intuitionthat contexts activated more recently in the system are morerelevant than contexts activated long ago, since recentlyactivated contexts are “hot” and correspond to situationsthat are just arising, whereas long-activated contexts are“cold” and correspond to background circumstances whichare more stable. If a context has just been activated, theadapted behaviour it defines is probably better suited to thecurrent situation than the behaviour of related though lessrecent adaptations.

To encode the previous observation as a policy, we definethe activation age of an active context as a measure suchthat, if the last activation request for context Ci happenedmore recently than the last activation request for context Ck,then the age of Ci is less than the age of Ck, or equivalently,Ci is younger than Ck. Note that the Default context isalways the oldest context in the system, since it is activatedat the start of execution. We make sure that two activecontexts can never have the same age measure, so that theactivation age defines a total order <a for any set of activecontexts.

Given a set of conflicting traits S = {TC1 , . . . , TCn} thatadapt the behaviour of an object o, the youngest trait com-position policy Pa yields a resolved trait formed by favouringyounger traits over older traits, as per activation age of theirrespective contexts. Assuming without loss of generality thatCi <a Ci+1 for 1 ≤ i < n, Pa is defined as

Pa({TC1 , . . . , TCn}) = {TC1 . TC2 . . . . . TCn−1 . TCn}

The resulting set contains a single conflict-free trait. Hence,the activation age policy Pa is general, because it alwaysreturns a total resolution, and it can thus be used as defaultpolicy Pd.

The youngest trait composition policy Pa produces a sortof layering between contexts, since all traits from a youngercontext C1 will override all traits from an older context C2.We therefore obtain the same semantics found in context-oriented systems based on layers [7] and delegation [11],though the ordering is not fixed: our approach allows toadjust it as needed on a domain-specific basis, by addingcustomised policies to the global policy chain Pg.

2.7 The Independent Behaviour ExtensibilityChallenge

Plain trait composition makes it possible to define ad-aptations that replace the original behaviour of an objectthrough the override operator . discussed previously. Suchadaptations do not invoke the original behaviour, which isthus not manifested by the adapted object. In practice, how-ever, many (if not most) behavioural adaptations need to bedefined as extensions of the original behaviour of an object.

213

Page 6: Context traits: dynamic behaviour adaptation through run ...homes.di.unimi.it/~cazzola/pubs/aosd13- · of applications can adapt. More specialised contexts are of course also possible

Such extensions invoke the original behaviour of the objectthey adapt as a regular part of their adaptation logic.

Any approach to adaptation that allows behaviour exten-sion thus needs to provide a mechanism to invoke overrid-den behaviour. In a plain trait-based approach, however,any attempt to compose an adaptation T2 as an extensionof another adaptation T1 will result in conflicts for all ex-tended methods, since the extended methods are preciselymeant to have the same signature as the overridden meth-ods. In the static composition setting of classical traits, suchconflicts could be resolved by having T2 override T1, afterhaving aliased each conflicting method of T1 so that it canstill be accessed from T2, and —crucially— changing thecode of each extension method in T2 so that it uses thealias name instead of the original name to invoke overrid-den behaviour. In trait notation, this composition wouldbe T ′2 . (T1[b1 → a1][b2 → a2] . . . [bn → an]), where T ′2 isthe modified version of T2, ai is the name of each extendedmethod, and bi is the corresponding alias. Note that notonly does the code of T2 need to be modified by the pro-grammer for the composition to work, but also the particularmodifications needed in T2 depend on the particular conflictsit has with T1, and thus different modifications would beneeded if T2 were to extend some other trait T3 with (forinstance) one more or one less conflicting method. Plaintrait composition was not designed to support independentbehaviour extension, but it is hard to go without in a modelwhere traits can be composed dynamically with other traits.

2.8 Extensibility Through proceedDynamic adaptation requires independent behaviour ex-

tensibility —once the software is deployed and running, pro-grammers can no longer intervene to refactor their developedadaptations according to particular composition needs. Soft-ware extension by method aliasing as proposed originally forplain traits is not an option. Yet traits are all about softwarecomposition and reuse. We resolve this dilemma by pluggingindependent behaviour extensibility into traits in a way thatleverages the existing traits composition mechanism, so thatit does not need to be modified nor extended.

Any method me designed to be a behaviour extension cansend the message proceed to self to signal the invocationof overridden behaviour. This is akin to advice compos-ition through proceed in AOP [12], method compositionthrough call-next-method in CLOS [13], and super calls intypical object-oriented languages. Following regular traitsemantics [8], such a self-send implies that proceed becomesrequired by the trait Te owning the method me:

me proceedTeTe

me proceed

Any such trait that requires proceed is called an extensiontrait. This makes sense conceptually: the trait is intendedto be composed with the behaviour it extends, and thus isby itself incomplete —the trait requires original behaviourto work properly, and this is signalled through proceed. Alsoin keeping with the intention of required methods, it is notknown in advance which concrete implementation of theoverridden behaviour will be used for composition, since thisdecision depends on the context.

The composition of two extension traits is itself an exten-sion trait, since the proceed requirement is propagated to

htmlString proceedparentFastSerializationFastSerialization

htmlString proceedparent

Figure 3: Fast DOM serialization as behavioural ex-tension of plain DOM serialization.

the composed trait. To produce complete compositions, theproceed requirement should be fulfilled somehow. To complywith this requirement, we include as part of every dynamictrait composition an extensibility trait which provides suchmethod:

proceedExtensibleExtensible

proceed

The Extensible trait provides proceed, and given that it hasno requirements, it will never render the composition inwhich it participates incomplete. Extensible is not only atechnical solution: conceptually, any object that can beextended should feature this trait, much like an object thatincludes a Reflective trait to allow reflection, for example.Rather than having programmers add Extensible to everyobject they develop, the system does it automatically forthem at dynamic composition time. Extensible is thus asystem-defined part of the default trait TDefault discussedin Section 2.4; in keeping with that discussion, Extensibleis part of the prototypical behaviour of any object. Toprevent that programmers inadvertently override the versionof proceed provided by Extensible with behaviour that breaksthe expected semantics, proceed needs to become a reservedmethod name.

Example: For efficiency, we would like to cache the serial-isation of HTML nodes in a DOM. To this end, we introduceas illustrated in Figure 3 a FastSerialization trait extension.This extension features a specialised htmlString method thatcalls proceed to obtain a serialised representation of the cur-rent node, which it caches and uses upon the next invocationinstead of calling proceed again. The serialisation cache inval-idates itself when the structure of the DOM node changes (forinstance, as a result of calling appendChild), and propagatesinvalidation to the parent node. Note that FastSerialization in-troduces parent as a new requirement that the extended traitSerializableElement does not have. Trait extensions are notrestricted in this sense, and can introduce new requirementsas needed.

The behaviour that proceed invokes can be the originalbehaviour mo of the object, but it can also be yet anotherextension method that is part of the current composition.In principle it is unknown in advance which of the otheravailable implementations of the current method will beinvoked by proceed. Fortunately, we can rely on the conflictresolution machinery to perform method composition, asexplained in the next section.

2.9 Resolution of proceed Through PoliciesConsider two traits T1, T2 that conflict for a name a. They

define implementations T1(a) = m1, T2(a) = m2 such thatm1 6= m2 (else it would not be a conflict). Apply the globalpolicy Pg to obtain a resolution {TR} = P ({T1, T2}); TR

214

Page 7: Context traits: dynamic behaviour adaptation through run ...homes.di.unimi.it/~cazzola/pubs/aosd13- · of applications can adapt. More specialised contexts are of course also possible

htmlString proceedPrettySerializationPrettySerialization

htmlString proceed

Figure 4: Definition of trait PrettySerialization thatconflicts with trait FastSerialization.

will map a to either m1 or m2.11 Assume without loss ofgenerality that TR(a) = m1. This means that m1 is morespecific than m2 according to the policy Pg, which induces anorder m1 < m2. For a more general set of conflicting traits{T1, . . . , Tn}, Pg can be applied pairwise to induce a totalorder m1 < m2 < · · · < mn. Any general policy induces suchan order on a set of methods in this way.12

For the case of the youngest trait composition policy Pa

explained in Section 2.6, the induced order will correspondto activation age. However, the global policy Pg of whichPa makes part can have small alterations or “tweaks” of thisactivation age order, according to the partial policies Pi thatcurrently make part of the chain.

The resulting total order induced by the global policy Pg

determines which method should be called next by proceed.The set of methods {m1, . . . ,mn} that implement the samemessage as the currently executing method mc is ordered as achain m1 < · · · < mc < mc+1 < · · · < mn. Having found theposition of mc in the chain, proceed can then invoke mc+1.These chained invocations will end with the first methodmi in the chain that does not invoke proceed. This couldbe a behaviour replacement introduced as an adaptation tothe current context, but else it will be the default behaviourmd, and it will be located at the end of the chain since theDefault context is always the oldest.

Example: For readability, we want to format the HTMLoutput produced by the htmlString method of trait Serializ-ableElement. Figure 4 depicts a PrettySerialization trait thatextends the original behaviour through the use of proceed.With this definition, traits PrettySerialization and FastSerial-ization have a conflict for method htmlString. Because thepreferred order should be to cache the formatted output (asopposed to formatting the cached output every time again),the programmer can define a policy

PFast({FastSerialization,PrettySerialization})= {FastSerialization . PrettySerialization}

This domain-specific policy can be composed as part of theglobal policy Pg.

This concludes the conceptual explanation of our approachto dynamic behaviour adaptation through run-time traitrecomposition. In the next section we describe how thisconceptual model has been implemented in JavaScript.

3. CONTEXT TRAITS IN JAVASCRIPTIn our context traits model, objects are purely composed

out of traits, and their composition varies dynamically ac-cording to detected context changes. To lower the barrier

11Recall from Section 2.5 that policies do not introduce foreigntraits into a composition, and thus a third method m3 cannotappear.

12Note that the policy cannot be used more generally toinduce an order on a set of traits, because the resolutionR = P ({T1, T2}) does not necessarily return either {T1} or{T2}; it can return a new composed trait {T3} that mixesmethods from both.

1 var cop = require(’context-traits’);2 var Untrusted = new cop.Context();3 var LowBattery = new cop.Context({4 name: ’low battery’,5 description: ’The remaining battery charge is low.’});

Snippet 1: Context creation.

for prototyping such an object-centric and dynamic model,a natural choice was JavaScript and the existing traits.jslibrary [26]. Section 3.1 explains the implemented modelfrom a programmer’s perspective, and Section 3.2 discussessalient elements of the underlying implementation.

3.1 Main MechanismsWe first present the main tools provided to JavaScript pro-

grammers to define, organise and discover contexts, to adaptbehaviour to contexts, and to specify strategies for resolvingcomposition conflicts. To make this functionality available,Snippet 1 (Line 1) shows how to import the context-traits.jsmodule, thenceforth referenced through the cop variable.

3.1.1 Context CreationSnippet 1 shows how to create a minimal Untrusted context

(Line 2), and how to create a LowBattery context (Line 3) withinitialisation parameters. Note that, by convention, contextvariable names start with uppercase. This is to emphasizethat these contexts are singleton objects —a very importantproperty for interoperation that we discuss in Section 3.1.2.Since contexts are singletons, the classless object model ofJavaScript is a better paradigmatic match than a class-basedone, because we do not incur the creation of a class for thesole purpose of creating a context.

3.1.2 Context OrganisationContexts constitute a sort of shared vocabulary that allow

different applications —or independently developed parts ofthe same application— to collaborate by defining adapta-tions with respect to the same specific situation [11]. It iscrucial for context-oriented systems to be defined in terms ofwell-known contexts, since these contexts are common pointsof reference to define behavioural adaptations. Luckily, Java-Script —like any other object-based language— allows theuse of objects as name spaces [23] to name and categorisecontexts:

• cop.contexts.resources.memory.LowMemory• cop.contexts.environment.acoustics.Noisy• cop.contexts.programming.testing.FaultInjection• cop.contexts.user.activities.Meeting

Name clashes are avoided by separating contexts in differentdomains, effectively constituting a shared vocabulary of pro-totypical contexts. This being said, local and vendor-specificcontexts are also possible and useful for internal adaptations.

3.1.3 Context DiscoveryContext detection or discovery goes from straightforward

to very sophisticated, depending on the nature of each con-text. For instance, whereas detecting contexts like Eveningor Firefox is fairly simple, detecting UserSleepy may involveadvanced image recognition and machine learning techniques.As mentioned in Section 2.1, context discovery matches wellan event-based programming style, in which context activa-tion and deactivation follow the occurrences of events. Snip-pet 2 illustrates the detection of LowBattery by registering a

215

Page 8: Context traits: dynamic behaviour adaptation through run ...homes.di.unimi.it/~cazzola/pubs/aosd13- · of applications can adapt. More specialised contexts are of course also possible

1 window.addEventListener(’batterystatus’,2 function (info) {3 if (info.level <= 30) LowBattery.activate();4 else LowBattery.deactivate(); })

Snippet 2: Context detection.

1 FastSerialization = Trait({2 htmlString: function() {3 var result = this.retrieve(); // probe cache4 if (result == undefined) { // cached?5 result = this.proceed(); // get serialisation6 this.store(result); } // cache it7 return result; }}); // return stored value8

9 Production.adapt(HTMLElement, FastSerialization);

Snippet 3: Object adaptation to context.

listener to the event batterystatus of the PhoneGap library.13

A crucial point regarding context detection is that any associ-ated code for detection, such as the conditional statement inSnippet 2, is written only once, rather than being scatteredthroughout the application at each point where behaviourdepends on such detection.

3.1.4 Adaptation to ContextAs explained in detail in Section 2.4, our approach is based

on the definition of traits as behavioural adaptations tocontext. An object can specify a trait that contains context-dependent behaviour, so that the adapted behaviour becomesavailable when the context is activated, and the behaviour iswithdrawn when the context deactivates. Snippet 3 showsthe definition of the trait FastSerialization (lines 1–7), whichwas depicted in Figure 3. The call to method adapt in Line 9suffices to register FastSerialization as adaptation of HTM-LElement for a Production environment. The application thusapplies such optimisations when running in production mode,but can run without if the Production context is inactive.

Since Default is a context like any other, it is possible tospecify the default serialisation behaviour of the HTMLEle-ment object using the same machinery for adaptation toother contexts:

cop.contexts.Default.adapt(HTMLElement, Serializable);

With this specification, HTML elements will be serialisableby default. Since the Default context is always active, theadaptation SerializableElement will be applied immediatelyto the object HTMLElement. Note the use of a name spacein the adaptation expression: the Default context used hereis one and the same used for every application, as discussedin Section 3.1.2.

Snippet 3 (Line 5) also illustrates the proceed mechanismin action, explained in detail in Section 2.8. The proceedmethod is used to invoke the original version of htmlStringbelonging to HTMLElement, which actually comes from thecomposition with SerializableElement shown previously.

3.1.5 Conflict ResolutionAn adapted object can have different traits for different

contexts. At run time, objects acquire traits depending onthe set of currently active contexts. When those traits arecomposed, conflicts can arise if two or more traits providea property with the same name but different values. Toresolve conflicts, a composition policy can be specified as

13See http://phonegap.com.

1 cop.manager.addObjectPolicy(HTMLElement,2 [FastSerialization, PrettySerialization]);3

4 cop.manager.addObjectPolicy(HTMLElement,5 [Production, Browser],6 return function (FastSerialization, PrettySerialization) {7 return Trait.override8 (FastSerialization, PrettySerialization); });

Snippet 4: Definition of a composition policy.

illustrated in Snippet 4. Lines 1–2 show a shorthand invoc-ation of the method addObjectPolicy, in which an array oftraits [FastSerialization, PrettySerialization ] specifies a desiredoverriding order. This order is specific to object HTMLEle-ment. Note that this policy is more specific than the policygiven as example in Section 2.9, since the policy illustratedhere is effective only for HTMLElement and not in generalfor every object.

Lines 4–8 in Snippet 4 show an invocation of addObject-Policy in which an explicit function for conflict resolution ispassed as argument. For illustration purposes, the passedfunction makes the policy functionally equivalent to the oneof lines 1–2. The arguments passed to the resolution function(Line 6) are the traits corresponding to the contexts passed asarguments of addObjectPolicy (Line 5). For example, Browseris associated to PrettySerialization. The Trait.override methodin Line 7 is provided by the traits.js library [26]. In general,any composition using summation, overriding, aliasing andexclusion is possible.

3.2 Implementation Notes

3.2.1 Context Activation AgeTo implement the activation age measure described in

Section 2.6, it is inconvenient to use a physical time stamp,because it depends on the resolution of the system clock. Ifthe activation of two contexts happens so closely in timethat they fall within the same clock tick, it will appear as ifthey were activated simultaneously. Rather than a physicalmeasure, we use a logical one, defined with respect to thetotal number of activations that have taken place in thesystem. When any context is activated, the total activationcount is incremented and the context is stamped with thisnew value. At any given time, the activation age of a contextis the difference between the total activation count and thevalue stored in the context. If no other activations havetaken place in the meantime, the age will be 0, meaning thatthis is the youngest context for the moment.

3.2.2 How To proceedAs explained in Section 2.8, the contract of proceed is

that “it invokes the behaviour that has been overridden bythe current extension method”. The question remains as tohow such contract can be implemented in practice. In lan-guages that allow introspection of method invocations, suchas Smalltalk, the proceed mechanism can be implementedstraightforwardly.14 For languages with less reflective powersuch as JavaScript, there is a less immediate though still

14In Smalltalk, the proceed method can have access to theMethodContext using the thisContext pseudo-variable. Fromthe method context, it is possible to introspectively find theextension method that invoked proceed, and also recover thereceiver and arguments used in this invocation. The proceed

216

Page 9: Context traits: dynamic behaviour adaptation through run ...homes.di.unimi.it/~cazzola/pubs/aosd13- · of applications can adapt. More specialised contexts are of course also possible

1 traceable = function(name, method) {2 wrapper = function() {3 var invocations = cop.manager.invocations;4 invocations.push([name, arguments, wrapper]);5 try { return method.apply(this, arguments); }6 finally { invocations.pop(); } };7 return wrapper; };8

9 proceed = function() {10 var invocations = cop.manager.invocations;11 if(invocations.length === 0) throw new Error12 (’Proceed must be called from an adaptation’);13 var name, args, method;14 [name, args, method] = invocations.top();15 args = arguments.length === 0 ? args : arguments;16 var alternatives = cop.manager.orderMethods(this, name);17 var index = alternatives.indexOf(method);18 if (index === -1) throw new Error19 (’Cannot proceed from an inactive adaptation’);20 if (index+1 === alternatives.length) throw new Error21 (’Cannot proceed further’);22 return alternatives[index+1].apply(this, args); }

Snippet 5: Core of the proceed mechanism.

valid solution, provided that the language features closures.Closures make it possible to build an auxiliary stack thatmimics the method invocation stack. This ad-hoc stack canthen be consulted by proceed.

The key parts of this technique are shown in Snippet 5.The traceable method is in charge of wrapping methodsso that they become traceable —that is, their invocationis registered in the ad-hoc invocation stack. To achievethis, traceable takes a method name and implementation asarguments (Line 1), and creates an anonymous closure thatwraps the given method (Line 2). The wrapper first fetchesthe ad-hoc stack (Line 3), and records the method invocation(Line 4).15 The wrapper then invokes the wrapped method,preserving the receiver and arguments, and returns the result(Line 5). The invocation is removed from the stack afternormal termination of the method, or even if it throws anexception (Line 6). The result of traceable is the wrappermethod (Line 7). The net effect of traceable methods issimply that their invocation is reflected in the ad-hoc stack.

The traceable method just explained works hand in handwith the proceed method (Line 9). First of all, proceedfetches the ad-hoc invocation stack (Line 10), and checkswhether it has been invoked from a method that makes partof an adaptation (lines 11–12). The necessary informationcorresponding to the current invocation is then read fromthe top of the ad-hoc stack (Line 14; recall that the stackis maintained by wrapper methods in lines 4 and 6). Theassignment in Line 14 uses JavaScript’s destructuring syntaxto assign the three variables at once. If the user passesexplicit arguments to proceed, these are used instead ofthose in the current method invocation (Line 15). Havingobtained the method name corresponding to the currentinvocation, the run-time composition system finds out themethods that are applicable for the current receiver andmethod name (Line 16). Normally the arguments of thecurrent invocation (held in the args variable) should also bepassed to orderMethods along with the receiver and method

method can then invoke the overridden behaviour, passingthe same receiver and arguments.

15The arguments local variable used in traceable is availablewithin all JavaScript functions and needs not be declared.

1 Encrypter = Trait({2 store: function(key, value) {3 this.proceed(key, this.encrypt(value)); },4 lookup: function(key) {5 var encrypted = this.proceed();6 if (encrypted)7 return this.decrypt(encrypted); }});8

9 Untrusted.adapt(cacheServer, Encrypter);

Snippet 6: Adaptation of cache server to Untrusted.

name, but in JavaScript arguments do not play any role indetermining the applicability of methods, so they are ignored.The result is a list of method alternatives which is orderedaccording to the current composition policy, following thesemantics explained in Section 2.9. In this list, the positionof the currently executing method (the one which invokedproceed) is determined (Line 17), and unless there are anyerrors (lines 18–21), the next method in order of specificityis finally invoked and the result is returned (Line 22).

Methods need to be wrapped (i.e. made traceable) onlywhen they override other methods —that is, when two ormore traits provide the same method in a composition. Thismeans the run-time overhead of wrappers is incurred onlywhen necessary. Despite the added complexity of this solutionas compared to a reflection-based approach, the techniquejust explained for implementing proceed can be ported to anylanguage that supports closures, and is thus fairly generic.16

4. CASE STUDIESOur proposal of context traits is at the crossroads of COP

and traits. By conducting a number of small case studies,three of which are presented in this section, we tested thecorrectness of our implementation and explored some of theadvantages this novel paradigmatic mix has to offer.

4.1 Cache ServerAs a first fairly typical scenario for context-orientation,

inspired by an example of Ghezzi et al. [9], we took thecase study of an adaptive cache server. The server offerscaching functionality for speeding up retrieval of informationrequested by other machines, and exposes a typical set ofprimitives used to store and retrieve generic resources, suchas store(key, value), lookup(key) and remove(key). The cacheserver is adaptive: when in Untrusted context, the serveractivates an Encrypter trait that ciphers a resource before it isstored in the cache, and deciphers it upon retrieval; in Volatilecontext, the server backs up resources on persistent storagein order to be resilient to likely failures (Persistent trait);finally in context Auditing, the server logs each significantoperation it performs (Logger trait). Snippet 6 illustratesthe adaptation to Untrused mentioned previously. The codefor the other adaptations is similar. For this case study, weidentified 4 possible conflict scenarios:

1. Logger, Encrypter: store and lookup methods.2. Logger, Persistent: store method.3. Persistent, Encrypter: store method.4. Logger, Persistent, Encrypter: store, and lookup methods.

As an example, Snippet 7 shows the definition of the com-position policy for Logger and Encrypter (lines 2–6). The

16In particular, we have successfully applied the same tech-nique to Ruby, which also lacks reflective call stack access.

217

Page 10: Context traits: dynamic behaviour adaptation through run ...homes.di.unimi.it/~cazzola/pubs/aosd13- · of applications can adapt. More specialised contexts are of course also possible

1 cop.manager.addObjectPolicy(cacheServer,2 [Auditing, Untrused],3 function(Logger, Encrypter) {4 return Trait.compose (Encrypter,5 Trait.resolve({ store: undefined,6 lookup: undefined }, Logger)); });

Snippet 7: Comp. policy for Logger vs. Encrypter.

Android.adapt(ciclaMi, Trait({initHandlers: function() { ... /* Android specific */ },run: function(zoomLevel) { ... /* Android specific */ },gotoPosition: function(position, zoomLevel) {this.proceed();... // Android specific

},initScreen: function() {this.proceed();... // Android specific

},// New behaviouronCenterChanged: function() { ... },capturePhoto: function() { ... },uploadData: function() { ... },... }));

Snippet 8: Adaptation of CiclaMi for Android.

policy solves the conflict by excluding store and lookup fromtrait Logger. As a result, the methods will be taken from theEncrypter trait. This simple cache server example illustratesthat our proposal for composition and conflict resolutionworks fine in typical context-oriented scenarios.

4.2 CiclaMiCiclaMi was conceived as an application for monitoring the

state of bicycle paths in the city of Milan, taking advantageof the sensors typically embedded in smartphones. It servesas an example of how to write an application in such a waythat it can either run as a web application, or as a mobileapplication, having different functionality depending on theplatform. CiclaMi was originally designed and implementedas a traditional Web application, and two different codebases were needed for the mobile and web browser versions.Although the code was straightforward, it was duplicated(for the mobile and fixed versions) and suffered from tanglingof environment sensing and base logic code. For instance, itcontained several conditional statements invoking isAndroidto express Android-specific functionality. Similarly, codeto detect whether the device had connectivity was tangledwith the functionality that relied on having connectivity. Torefactor CiclaMi as a COP application having a unique codebase, we created a context Android, which can be activatedby registering a PhoneGap event listener:document.addEventListener

("deviceready", function() { Android.activate(); }, true);

Once active, context Android is never deactivated. To providethe behaviour of CiclaMi that is specific to Android, wedefined the adaptation outlined in Snippet 8. This case studyallowed us to improve the architecture of our application byseparately defining the platform-dependent parts. It therebyillustrated a less publicised use of COP for static softwaremodularisation and configuration.17

17This shows that COP is not a dynamic or static approachper se; the static or dynamic nature of behaviour goes withthe context for which such behaviour has been defined.

1 $(document).ready(function() {2 LowBattery.adapt($.mobile, Trait({3 changePage: function(to, options) {4 newOptions = jQuery.extend({}, options);5 newOptions[’transition’] = ’none’;6 this.proceed(to, newOptions); }}))});

Snippet 9: Adaptation of jQuery core functionality.

4.3 jQuery MobileThe main goal of this third case study was to assess wheth-

er our approach could be used to dynamically adapt thesource code of an existing system that was not written ina context-oriented style, without modifying its source codeto introduce adaptations. To this end, we started from thejQuery Mobile library, which is a well-known library with oneof the largest user bases in the JavaScript community. By de-fault, jQuery Mobile uses animated transitions between pages.This “graphic candy” enhances the user experience, but con-sumes slightly more battery than not having intermediateanimations for every modal transition in the user interface.For this reason, in this case study we wanted to adapt thelibrary to low battery conditions by disabling animations.Snippet 9 shows the simple adaptation we introduced for themain $.mobile object in LowBattery context. The adaptationextends the changePage method of $.mobile. The changePageis used internally for the page loading and transitioning thatoccurs as a result of clicking a link or submitting a form.Our adapted version leaves the destination (to) untouched,but passes a new options object in which the transition hasbeen disabled. In passing, Snippet 9 illustrates a call toproceed with explicit parameters (Line 6). This case studyalso illustrates unanticipated adaptation to context, sincethe code of jQuery Mobile was completely oblivious to ourlibrary, but could be adapted nevertheless. Finally, the casestudy also illustrates non-invasive definition of adaptations,since we did not need to touch the source code of jQueryMobile to introduce our adaptation.

5. DISCUSSION AND FUTURE WORKJavaScript naturally supports the view of traits-as-state

discussed in Section 2.3, since both object state and behaviourare stored in assignable slots. However, JavaScript alsosupports the traits-as-behaviour view, thanks to the newlyintroduced properties abstraction:18 in this case, a slot accesssuch as point.x is actually a method call without arguments,as in Self [24]. Modern JavaScript thus aligns well withour traits model, which does not distinguish between stateand behaviour. As to whether static languages such as Javacan accommodate context traits, the question is still open.With recent progress on dynamic software updates [19], thetechnical barrier seems to have lowered.

Regarding the benefits our model brings to JavaScript,it could be argued that JavaScript by itself already allows

—even invites— very flexible manipulation of objects. Pro-grammers can change the implementation of any method atrun time. What our approach adds is a conceptual frame-work on top of this low-level basis, a mindset that invitesprogrammers to move from thinking in isolation, in a waythat is mostly oblivious of the context in which the softwarewill be used, towards thinking in context to build adaptive

18Properties are defined in the ECMAScript5 standard.

218

Page 11: Context traits: dynamic behaviour adaptation through run ...homes.di.unimi.it/~cazzola/pubs/aosd13- · of applications can adapt. More specialised contexts are of course also possible

applications from the ground up. This new programmingperspective comes with necessary language-level support,such as first-class contexts, traits, composition operators,and composition policies.

This paper focussed essentially on presenting the under-lying concepts of our approach, backed by a prototype im-plementation in JavaScript. Although a first evaluation hasalready been performed through small case studies, we needto carry out a more thorough validation, including bench-marks to assess the performance overhead of our approachas compared to traditional approaches. Our prior experiencewith the design of context-oriented languages makes us con-fident, however, that performance loss will not be drasticand will be compensated by increased expressiveness [10].Regarding correctness of context trait composition, it is animportant topic that we are currently exploring generally forany context-based approach [4], and that we plan to tailorto the particular case of context traits.

In designing context traits we leveraged our previous exper-ience and incorporated a minimal set of mechanisms that wehave found to be most useful in practice, such as activationcounters (Section 2.1) and composition policies based onactivation age (Section 2.6). There remains a last generallyuseful mechanism, context combinations [11], that we willincorporate in the future. This should pose no problems,since context combinations are independent of the adaptationunit being used —whether methods or traits.

6. RELATED WORKDynamic aspect weaving , of which we take PROSE as

iconic example [18], shares our motivation of streamliningdynamic behaviour adaptability, and also the approach ofachieving it through run-time software recomposition. How-ever, the means are quite different. Joinpoints in PROSEfeature a rich set of events such as field accesses, methodentry, catch and throw of exceptions, class loading and un-loading, and breakpoints. Support of method invocationsgoes without saying. The interception of these events allowsfor detection of joinpoints at run time and execution of cor-responding advice. Dynamic aspect weaving approaches suchas PROSE are often more expressive than COP approacheslike ours. PROSE can be seen as a sort of “compositionassembler” that allows the execution of advise at practicallyany conceivable point during program execution. Our ap-proach, on the other hand, proposes a high-level conceptualframework in terms of contexts, objects and adaptations. Itshould be noted that the purer the underlying object-orientedlanguage, the closer COP and dynamic AOP come together,because with pure message-passing semantics, every action(including field accesses, caught and thrown exceptions, andso on) can be captured and adapted by COP. COP is con-ceptually simpler and works best with purer object-orientedmodels, whereas dynamic AOP is more complex but hasbetter support for primitive constructs and mechanisms thatbypass a strict object-oriented semantics.

Chai3 [22] is the first effort to introduce dynamic traitsubstitution. Since Chai3 has been conceived for class-based,statically typed languages, it allows the adaptation of ex-isting methods, but the interface of adapted objects mustbe preserved. Objects are adapted by substituting one traitfor a compatible one —one which provides and requires thesame set of method signatures. Augmenting or reducingan object’s protocol is not supported. Chai3 was described

formally, but the formalisation was not backed up by animplementation [22].

Lexically-nested traits [25] propose a novel trait composi-tion mechanism based on prototype-based delegation. In thisapproach traits are actually closures, and are thus stateful.Nested scopes delegate to their parent scope. The state of atrait is visible only within the scope of the trait or its nes-ted scopes. Like in our proposal, traits are regular objects,and any object can thus play the role of a trait. The ideaof defining traits as closures and visibility control throughlexical scoping inspired the development of the traits.jslibrary [26], upon which we relied to build the dynamicadaptation machinery in our JavaScript implementation.

Talents [20] define behaviour that can be acquired byobjects. Like classical traits, talents are stateless, composi-tional (i.e. new talents can be made from existing talents)and preserve the flattening property (i.e. objects containingtalents cannot be distinguished semantically from objectsthat do not). Unlike traits, talents are added to objects,not to classes, leaving other instances of the same class un-changed. Further, talent composition is dynamic: objectscan be recomposed at run time by adding and removing tal-ents. Talents thus constitute a valid stepping stone towardssoftware adaptation through dynamic object recomposition.Unfortunately, they do not feature a proceed-like mechan-ism for behaviour extension. Furthermore, since they werenot specifically conceived for self-adaptive context-orientedsystems, some of the necessary concepts and infrastructureare missing: they do not reify context nor build a causalconnection between context and object composition, andtherefore also lack a dynamic conflict resolution mechanism.

ContextL [7] is the seminal work on context orientation,and gave rise to a family of similar approaches that have cometo be known as layer-based approaches [21]. Our approachrather belongs to the context-based branch of COP initiatedby Ambience [11] —the first COP language to introducefirst-class contexts, and in which the activation of adapta-tions was not dictated by base program control flow. Ourapproach improves on current approaches —whether layerbased or context based— in that it offers more meaningfulunits of adaptation. Traits, as opposed to single methods,are geared towards flexible composition, liberating the pro-grammer from the restrictions of inheritance mentioned inSection 2.2, and providing explicit abstractions to solve com-position conflicts. Further, traits give first-class status tobundles of methods that have been designed to work togetherunder a certain context. With single-method adaptation, thesemantic connection between those methods remains implicit.

ContextJS [15], a JavaScript framework, does support thedefinition of adaptations as whole objects instead of indi-vidual methods, but when it comes to composition, suchplain objects are far from having the status of full-blowntraits with composition policies presented here. More im-portantly, there is no backing conceptual mindset such asthe one presented in Section 2.4 that invites programmers tothink in terms of meaningful units of adaptation.

7. CONCLUSIONTraits have been proposed to overcome some of the limita-

tions of composition in object-oriented languages, by havingbetter granularity and no imposed composition semantics.COP too has been proposed to overcome some of the limit-ations of composition in object-oriented languages, namely

219

Page 12: Context traits: dynamic behaviour adaptation through run ...homes.di.unimi.it/~cazzola/pubs/aosd13- · of applications can adapt. More specialised contexts are of course also possible

the lack of run-time behaviour adaptability. This paper pro-poses to marry the best of those two solutions. On the onehand, the paper presents a contribution to research on COPby proposing traits as units with convenient granularity fordynamic behaviour adaptation and a well-defined compos-ition semantics. On the other hand, the paper proposes acontribution to research on traits by proposing a simplertraits model and a way of using it dynamically dependingon detected context changes. At the crossroads of bothapproaches, we have found a convenient way of developingsoftware applications that need to evolve according to theirchanging environment of execution.

8. ACKNOWLEDGEMENTSThis work has been supported by the ICT Impulse Pro-

gramme of the Brussels Institute for Research and Innovation,and by the MIUR project CINA: Compositionality, Interac-tion, Negotiation, Autonomicity for the future ICT society.We thank the anonymous reviewers for their comments onearlier versions of this paper.

References[1] Kim Barrett, Bob Cassels, Paul Haahr, David A. Moon,

Keith Playford and P. Tucker Withington. A MonotonicSuperclass Linearization for Dylan. ACM SIGPLANNotices 31.10 (1996).

[2] Alexandre Bergel, Stephane Ducasse, Oscar Nierstraszand Roel Wuyts. Stateful Traits and Their Formalization.Computer Languages, Systems and Structures 34.2–3(2008).

[3] Gilad Bracha and William Cook. Mixin-Based Inherit-ance. ACM SIGPLAN Notices 25.10 (1990).

[4] Nicolas Cardozo, Jorge Vallejos, Sebastian Gonzalez,Kim Mens and Theo D’Hondt. Context Petri Nets: En-abling Consistent Composition of Context-DependentBehavior. PNSE Workshop Proceedings. CEUR-WS.org,2012.

[5] Craig Chambers, David Ungar and Elgin Lee. An Ef-ficient Implementation of Self, a Dynamically-TypedObject-Oriented Language Based on Prototypes. ACMSIGPLAN Notices 24.10 (1989).

[6] Pascal Costanza. Dynamically Scoped Functions as theEssence of AOP. ACM SIGPLAN Notices 38.8 (2003).

[7] Pascal Costanza and Robert Hirschfeld. Language Con-structs for Context-Oriented Programming: An Over-view of ContextL. DLS Symposium Proceedings. ACMPress, 2005.

[8] Stephane Ducasse, Oscar Nierstrasz, Nathanael Scharli,Roel Wuyts and Andrew P. Black. Traits: A Mechanismfor Fine-Grained Reuse. ACM Transactions on Program-ming Languages and Systems 28.2 (2006).

[9] Carlo Ghezzi, Matteo Pradella and Guido Salvaneschi.An Evaluation of the Adaptation Capabilities in Pro-gramming Languages. SEAMS Symposium Proceedings.ACM Press, 2011.

[10] Sebastian Gonzalez, Nicolas Cardozo, Kim Mens, Al-fredo Cadiz, Jean-Christophe Libbrecht and Julien Gof-faux. Subjective-C: Bringing Context to Mobile PlatformProgramming. SLE Conference Proceedings. Springer-Verlag, 2011.

[11] Sebastian Gonzalez, Kim Mens and Patrick Heymans.Highly Dynamic Behaviour Adaptability Through Pro-totypes with Subjective Multimethods. DLS SymposiumProceedings. ACM Press, 2007.

[12] Gregor Kiczales, Erik Hilsdale, Jim Hugunin, Mik Ker-sten, Jeffrey Palm and William Griswold. An Overviewof AspectJ. ECOOP Conference Proceedings. Springer-Verlag, 2001.

[13] Gregor Kiczales, Jim des Rivieres and Daniel G. Bobrow.The Art of the Metaobject Protocol. MIT Press, 1991.

[14] Henry Lieberman. Using Prototypical Objects to Im-plement Shared Behavior in Object-Oriented Systems.ACM SIGPLAN Notices 21.11 (1986).

[15] Jens Lincke, Malte Appeltauer, Bastian Steinert andRobert Hirschfeld. An Open Implementation for Context-Oriented Layer Composition in ContextJS. Science ofComputer Programming 76.12 (2011).

[16] Ole Lehrmann Madsen and Birger Møller-Pedersen. WhatObject-Oriented Programming May Be —and What ItDoes Not Have To Be. ECOOP Conference Proceedings.Springer-Verlag, 1988.

[17] Pattie Maes. Concepts and Experiments in Computa-tional Reflection. ACM SIGPLAN Notices 22.12 (1987).

[18] Andrei Popovici, Gustavo Alonso and Thomas Gross.Just-in-Time Aspects: Efficient Dynamic Weaving forJava. AOSD Conference Proceedings. ACM Press, 2003.

[19] Mario Pukall, Christian Kastner, Walter Cazzola, Se-bastian Gotz, Alexander Grebhahn, Reimar Schroter andGunter Saake. JavAdaptor —Flexible Runtime Updatesof Java Applications. Software: Practice and Experience(2012).

[20] Jorge Ressia, Tudor Gırba, Oscar Nierstrasz, FabrizioPerin and Lukas Renggli. Talents: An Environment forDynamically Composing Units of Reuse. Software: Prac-tice and Experience (2012).

[21] Guido Salvaneschi, Carlo Ghezzi and Matteo Pradella.Context-Oriented Programming: A Software Engineer-ing Perspective. Journal of Systems and Software 85.8(2012).

[22] Charles Smith and Sophia Drossopoulou. Chai: Traits forJava-like Languages. ECOOP Conference Proceedings.Springer-Verlag, 2005.

[23] David Ungar, Craig Chambers, Bay-Wei Chang and UrsHolzle. Organizing Programs Without Classes. Lisp andSymbolic Computation 4.3 (1991).

[24] David Ungar and Randall B. Smith. Self: The Power ofSimplicity. ACM SIGPLAN Notices 22.12 (1987).

[25] Tom Van Cutsem, Alexandre Bergel, Stephane Ducasseand Wolfgang De Meuter. Adding State and Visibil-ity Control to Traits Using Lexical Nesting. ECOOPConference Proceedings. Springer-Verlag, 2009.

[26] Tom Van Cutsem and Mark S. Miller. traits.js: Ro-bust Object Composition and High-Integrity Objectsfor ECMAScript 5. PLASTIC Workshop Proceedings.ACM Press, 2011.

220