Reactive Behavior in Object-oriented Applications: An ... · [Functional reactive animation,...
Transcript of Reactive Behavior in Object-oriented Applications: An ... · [Functional reactive animation,...
Reactive Behavior in Object-oriented Applications: An Analysis and a
Research Roadmap
Guido Salvaneschi
Mira MeziniSoftware Technology Group, University of Darmstadt
Outline
• Design space of OO reactive applications
• Empirical case studies
• Advanced languages for reactive applications
• Research roadmap
• External/internal events trigger a reaction
– User input
– Network packet
– Interrupt
– Data from sensors
• Classic example:
– Data change in MVC
Reactive Applications
• Derived graph (D): edges exceeding MIN weight
• Add an edge to the Basic graph (B) !
Strategies for Reactivity: Graphs
BASIC DERIVEDComputational dependency
D = B.filter(edge > MIN)
• On-demand recomputation
• Caching
• Tracking dependencies
• Update incrementalization
• Accumulating changes
Strategies for Reactivity: Graphs
On Demand Recomputation
“Recompute the D each time it is needed”
– Request from the client• Generate a report, refresh a view, …
– Recompute D
– Discard
• Simple: just compute the outputs from inputs.
• Safe/consistent: values are always computed from the current state of the program
• Memory efficient
Caching
“Save the D for further requests”
– Store D
– Request from the client• If the D is valid return it
• otherwise recompute D
– Changes invalidate D
• When the inputs change: invalidate/recompute
– Is the computed value is used frequently?
Tracking dependencies
“Update only the outputs that depend on changed input”
– Store B with the edges sorted
– Recompute D from scratch
– Only a subset of B is evaluated
• Hard: knowledge of input-output computational relations
• Dataflow is not explicit in imperative code
– Code analysis is required to reconstruct it.
Update incrementalization
“Update the cached value incrementally”
– Keep always the same D– Update D only if
weight(newEdge) > MIN
• For complex objects more efficient than recomputation
• Fine-grained analysis of the changes to the inputs. – Change detection is not enough. Which change?
• Need for incremental algorithms – E.g. D is the Minimum Spanning Tree of the B !?
Accumulating changes
“Store the changes” – Cache D
– Store the changes
– Apply changes at least when D is requested
• Requires caching and incrementalization
• More complex than updating after each change– Data structures to store the changes
– Sophisticated algorithms for the update.
• Opportunities for optimization!
Applications
• SWT Text Editor: editor in the SWT library• FreeCol Game: open-source turn-based strategy game • Apache JMeter: performance assessment of servers• AccelerometerPlay: example Android application
Analysis
• Static analysis / dynamic measurements / instrumentation via AspectJ / (a lot of) manual inspection (sigh…)
• What we have found:– Code Complexity
– Hidden Design Intent
– Redundant Computations
– Scattering and Tangling of Update Code
– Error-proneness and Code Repetitions
Issues of Implementing Reactivity
• Complexity
– SWT StyledText• 70 mutable fields
• Handlers/listeners = 40 methods
• Hidden Design Intent
– AccelerometerPlay
• Redundancy
• Scattering and tangling
– Worst case: field updated in 96 places!
Complexity of Reactivity
• SWT StyledText ~10,000 LOC
– 70 mutable fields
– “addListener”+“removeListener”+“handleEvent” = 40 methods
• Efficient data structures
• Values are separated from their update logic
– Local reasoning is impossible: understanding the application requires inspecting a lot of code
Redundancy of Computation
• AspectJ probes
– Method executions in the Freecol game
– Freecol game Vs SWT Text editor
Update code
• Scattering and tangling
• Fields is updated in just one place:
– FreeCol game: 38.4%,
– Jmeter: 46.0%
– SWT text editor: 30.7%
– In the worst case, a field was updated in 96 places!
Lesson Learned: Modularization
• Modularization of update code is hard in the OO style
– Dependencies are not explicit and span over several modules
– Updates code scattering and tangling
Lesson Learned: Consistency
• Manual update is error-prone
– Fail to update all functionally dependent values.
– Values are often updated defensively no clear knowledge of whether it is necessary.
Lesson Learned: Maintenance
• No automatic consistency of the update code with the actual dependencies of the computation.
• Update the update functionality to reflect the current state of the dependencies!
Lesson Learned: Design
• Trade-off: efficiency Vs complexity.
– Keep the design simple: accept the cost of on-demand recomputation and potential redundancy.
– Optimization: highly complicates the application • Complex update logic
• Object fields for intermediate caching
The (good? old) Observer Pattern
Decoupling the code that changes a value from the code that updates the values depending on it
• Long story of criticism…
– Inversion of natural dependency order
– Boilerplate code
– Reactions do not compose
– Scattering and tangling of triggering code
– …
Event-based Languages
• Event-based languages are better!– Language-level support for events
– C#, Ptolemy, EScala, …
• Features:– Integration with OO
and imperative style: • Fine-grained updates
• Object identity
– More composable
– Less boilerplate code
abstract class Figure {evt moved[Unit] = afterExec(moveBy)evt resized[Unit]evt changed[Unit] = resized || moved || afterExec(setColor)evt invalidated[Rectangle] = changed.map( _ => getBounds() )
...def moveBy(dx: Int, dy: Int) { position.move(dx, dy) }def resize(s: Size) { size = s }def setColor(col: Color) { color = col }def getBounds(): Rectangle
...}
Event-based Languages
• Dependencies still encoded manually– Handler registration
• Updates must be implemented explicitly – In the handlers
• Dependents notifications is still error prone: – Too rarely / too often
• No support fornon-functional choices– E.g. manual caching
– Accumulation of changes ?
class Connector(val start: Figure, val end: Figure) {start.changed += updateStartend.changed += updateEnd
...def updateStart() { ... }def updateEnd() { ... }
…
Reactive Languages
• Functional-reactive programming (FRP) -- Haskell
– Time-changing values as dedicated language abstractions. [Functional reactive animation, Elliott and Hudak. ICFP ’97]
• More recently:
– FrTime [Embedding dynamic dataflow in a call-by-value language, Cooper and Krishnamurthi, ESOP’06]
– Flapjax [Flapjax: a programming language for Ajax applications.
Meyerovich et al. OOPSLA’09]
– Scala.React [Imaier te al, Deprecating the Observer Pattern with Scala.React. Technical report, 2012]
Reactive Languages
• Functional-reactive programming (FRP) -- Haskell
– Time-changing values as dedicated language abstractions.
var nowB = timerB(1000);
var startTm = nowB.valueNow();
var clickTmsB = $E("reset", "click").snapshotE(nowB)
.startsWith(startTm);
var elapsedB = nowB − clickTmsB;
insertValueB(elapsedB, "curTime", "innerHTML");
<body onload="loader()">
<input id="reset" type="button" value="Reset"/>
<div id="curTime"> </div>
</body>
[Flapjax: a programming language for Ajax applications. Meyerovich et al. OOPSLA’09]
(Functional) Reactive Languages
• Functional flavor and immutability.
– Refactoring to a functional style ?
– Some computations are hard to express functionally
• Objects: modeling, modularization, Reuse, Runtime variability, …
Reactive Languages
• Several issues in the case studies are solved!– Dependent values automatically consistent
• Simpler applications
• No update errors
– The update code modularized with the entity• Local reasoning
• No scattering and tangling
– Reactive behaviors are composable• In contrast to callbacks, which return void
• Design intentions are explicit
• Declarative style
var elapsedB = nowB − clickTmsB;
(Functional) Reactive Languages
• Do not fit well with mutable objects.
– Reactive languages recompute the dependents every time• E.g. require immutable data structures
– Changes to the state of the object are not even detected
list2 = list1.filter(x>10)
var elapsedB = nowB − clickTmsB;
Reactive Collections
• Efficient incremental updates
– “View maintenance” in the database community
[Deriving production rules for incremental view maintenance. S. Ceri and J. Widom. VLDB’91]
L1
L2 = f (L1)
L3 = g (L2)
Reactive Collections
• Language extensions / libraries
– Intercepting the updates via AspectJ, code generation[Caching and incrementalization in the Java query language, D. Willis et al.
OOPSLA’08]
[Generating incremental implementations of object-set queries, T. Rothameland Y. A. Liu, GPCE’08]
– Off-the-shelf libraries: LiveLinq , Glazed Lists (e.g. JabRef).
Reactive Collections
• Efficient incremental updates, LiveLinq, Glazed Lists
– “View maintenance” in the database community
L1
L2 = f (L1)
L3 = g (L2)
EventList cars = new BasicEventList();EventList sorted = new SortedList(cars);TextFilterList filtered = new TextFilterList(sorted);filtered.getFilterEdit().setText("Hybrid");
cars.add("Insight");cars.add("EV1");cars.add("Prius Hybrid");cars.add("Jetta TDI");cars.add("Escape Hybrid");cars.add("Escalade");
// should print "[Escape Hybrid, Prius Hybrid]"System.out.println(filtered);
Reactive Collections
• Advantages similar to reactive languages
– Automatic updates!
• Efficient update of various operators
– Incremental changes /caching
• Approach restricted to a specific domain / operators
Aspect-oriented Programming
“Intercept object changes, update dependent entities”
– (Crosscutting) update functionalities are separated
public abstract class Figure {...
public void moveBy(int dx, int dy) {position.move(dx, dy);
}public void setColor(Color col) {
color = col;}
} public aspect FigureEvents {pointcut changed(): execution( void Figure+.moveBy( ... ) )
|| execution( void Figure+.setColor( ... ) );}
Aspect-oriented Programming
• Success stories:– (Observer) Pattern with AOP
• [Design pattern impl. in Java and AspectJ, Hannemann and Kiczales, OOPSLA’02]
– Combination with events and OO• [Gasiunas et al, EScala: modular event-driven object interactions in Scala, AOSD ’11]
– Complex relations among objects• [Association aspects, Sakurai et al. AOSD ’04]
• [Relationship aspects , Pearce and Noble. AOSD ’06]
• Many limitations of events hold for AOP, too. – Explicit updates in the aspect
– Dependencies are not automatically tracked
– Composition of reactive behaviors is harder compared to FRP.
Other Approaches
• Constraint-based languages
– Kaleidoscope
• One-way constraints
– Graphical interfaces, Garnet and Amulet
• Self-adjusting computation
– Automatic derivation of incremental programs
• Complex event processing (CEP)
– TelegraphCQ, SASE, EventJava
Summary
• Event-based languagesFit into the OO design, mutable objects / fine-grained changes
Not declarative.
Drawbacks of Observer
• Reactive languagesOvercome the limitations of Observer
Declarative style
No fine grained changes / mutable objects, no integration with OO
• Reactive collectionsEfficient, declarative
Single domain
Roadmap
Reactive languages
• Integration with Event-based Programming
• Integration with Object-oriented Design
• Efficient Reactive Expressions
• Propagation Model
Roadmap
Reactive languages
• Integration with Event-based Programming
• Integration with Object-oriented Design
• Efficient Reactive Expressions
• Propagation Model
Integration of Reactive Programming and Event-based Programming
• Events and reactive abstractions are complementary
• Interface• *Signal → Event+ Signal.changed
• *Event → Signal+ Event.latest
• *(S, E) → Signal+ snapshot
• Methodology
– When to use behaviors and when events
– Case studies and guidelines
– Patterns ?
EVENTS SIGNALS
Roadmap
Reactive languages
• Integration with Event-based Programming
• Integration with Object-oriented Design
• Efficient Reactive Expressions
• Propagation Model
Objects
• Modeling: reproduce the interaction of real world entities.– For example, the hundreds of simulation elements used by the FreeCol game
• Modularizing functionalities and abstracting over implementation details. – SWT widgets are ready-to-use, but open for modifications via subtyping– E.g., the SWT text editor implementation for text container, can be overridden
• Reuse by class inheritance. – E.g., the StyledText class is part of an inheritance hierarchy of depth 7.
• Runtime variability. via dynamic polymorphism. – Simulation elements in JMeter are treated uniformly and late bound.– In the SWT, a text editor can be used wherever a generic widget is expected.
Integration of Reactive Programming and Object-oriented Design
• Methodological/design issues
– Encapsulation
– Behaviors should be part of the interface ?• Private behaviors?
– Reassign behavior expressions ?
– Inheritance of behaviors ?
– Subtype polymorphism ?
[Crossing state lines: Adapting object-oriented frameworks to functional reactive languages, Ignatoff et al, FLOPS’06]
Roadmap
Reactive languages
• Integration with Event-based Programming
• Integration with Object-oriented Design
• Efficient Reactive Expressions
• Propagation Model
Efficient Reactive Expressions
• Reactive collections
– Optimizations are out-of-the-box for built-in operators
…but not at the fingertips of end developers
• Reactive languages
– Arbitrary reactive computations
…not so efficient
Efficient Reactive Expressions: Challenge!
• Reconciling the openness of reactive languages with the efficiency of reactive collections
Openness
Efficiency
Reactive collections
Reactive Languages ?
Efficient Reactive Expressions (1)
• Predefined operators cover the most common scenarios e.g. collections and relational operations.
• Interoperability with reactive abstractions
s = list1.filter(x>K).size
behaviors
Efficient Reactive Expressions (2)
• Domain knowledge enables incremental updates.– Open refinements of reactive computations !
– Can be easy as overriding an existing method ?
• Separate creation from maintenance
• Default : complete recomputation
• Late binding of the best refinement
• Generality of mechanism Vs domain-specific incrementalization
list2 = list1.filter(x>10)
Roadmap
Reactive languages
• Integration with Event-based Programming
• Integration with Object-oriented Design
• Efficient Reactive Expressions
• Propagation Model
Propagation Model: Intro
• Graph model
– Constraints among dependent values
– Change propagation
f = 1g = 1
c := f + g // c == 2
f = 2 // c == 3
c
f g
Propagation Model: Strategies
• Current languages: single point in the design space
– Caching with invalidation ?
– Proactive recomputation ?
– Caching of intermediate values ?
– Accumulate changes ?
– Adaptive mechanism ?
a
b
cd
ef g
Propagation Model: Collapsing
• Optimizations
– Alternative graphs can be observationally equivalent
– Performance can guide the choice.• Caching Vs moving to the stack
a
b c
d
e f
a
b
c(e(y),f(z))x
y z y z
x
Propagation Model: Collapsing
• Choose carefully!– Code analysis / dynamic techniques?
(time-consuming-op
(infrequently-changing-op frequent-emitter))
d
f
z
t
z
t
d ·f
Propagation Model: VMs
• Dedicated VM support ?
• Graph:
– Events
– Time-changing values
• Previous work: dedicated VM support for AOP[Efficient control flow quantification, Bockisch et al, OOPSLA’06]
Propagation Model
• Espressive power impacts on performance– Speculative execution of signal expressions– Dynamic creation of signals– Exact tracking of dependencies– …
• Current reactive languages focus on expressive power rather than performance– FRP (Haskell), FrTime, Scala.React,
• Esterel and LUSTRE, limit expressive power to achieve better performance– Memory and time-bound execution
a
b
cd
e
f g
Propagation Model
• Current languages: expressive power
– E.g. dynamic signal creation
• Dataflow languages: performance
– Lustre, Esterel: memory and time-bound execution
• Black-or-white choice
• Leave the programmer the choice!
– Whole range available
– Explicit performance implications
Ongoing!
• ERC grant PACE, Prof. Mira Mezini
• Programming Abstractions for Applicationsin Cloud Environments
– http://www.stg.tu-darmstadt.de/index.en.jsp
Interested ? Contact us!
Ongoing: REScala
• REScala: R(eactive)EScala
– Development methodology for reactive applications
– Systematic evaluation by case studies
– Tech report is out! • http://www.stg.tu-darmstadt.de/research/escala/index.en.jsp
Reactive abstractions
Advanced event system+