1 / 39

Tal Cohen Research supervisor: Yossi Gil

Object Evolution A chapter from the research work on Applying Aspect-Oriented Software Development to Middleware Frameworks. Tal Cohen Research supervisor: Yossi Gil. Object Evolution. Dynamic reclassification : allowing an object to change its type at runtime. e.g., prince → frog .

mcglone
Download Presentation

Tal Cohen Research supervisor: Yossi Gil

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Object EvolutionA chapter from the research work onApplying Aspect-Oriented Software Development to Middleware Frameworks Tal Cohen Research supervisor: Yossi Gil

  2. Object Evolution • Dynamic reclassification: allowing an object to change its type at runtime. • e.g., prince → frog. • Supported by Smalltalk, several others. • Many real-world uses • e.g., State design pattern. • Type safety problems… Prince p = new Prince(); if (…) p → Frog(); p.drawSword(); // potential runtime type error • Our solution: limit to monotonic changes only. • "Object evolution" -- moving down the inheritance tree. • Prince → king is okay! Overview begin::Overview Motivation I-Evolution M-Evolution S-Evolution

  3. Three Kinds of Evolution • I-Evolution: Moving down the inheritance tree. • M-Evolution: Evolving by applying mixins. • S-Evolution: Evolving by applying shakeins. Overview Motivation I-Evolution M-Evolution S-Evolution

  4. Contributions • The case for object evolution. • Why you want your language to support this feature. • Concrete language extension. • The idea is simple, the details are not trivial. • Three kinds of evolution. • A language can support any one, two, or all. • Analysis of potential failures. • What can go wrong, and how to cope with it. • Implementation strategies. • The nitty-gritty details. Overview end:: Motivation I-Evolution M-Evolution S-Evolution

  5. Motivation

  6. The State Design Pattern Overview begin::Motivation Motivation I-Evolution M-Evolution S-Evolution

  7. State Example: TCPConnection • TCPConnection responds differently to messages (open, close, etc.) depending on its state. • Possible states: Listen, Established, Close. • A switch statement in each method…!? Overview Motivation I-Evolution M-Evolution S-Evolution

  8. TCPConnection using State • Two objects in memory • Repeated delegation code • API must be identical • No state-specific public methods. Overview Motivation I-Evolution M-Evolution S-Evolution

  9. Knowledge Refinement Parsing the source line: InterfaceMethodInvocation MethodInvocation • State pattern not applicable: subclass has many additional methods. • Should the "changeable" class contain the union of all methods of all possible states!? • Creating a new object implies: • Copying existing state (fields), • Chasing references. x.equals(y) Overview ObjectRef x MethodName equals ParamsList (y) Motivation I-Evolution M-Evolution S-Evolution

  10. Lazy Data Structures • A specific case of knowledge refinement. • Example: XML/HTML parsing. • "Varying interface" problem particularly acute. • Should the "Node" superclass include the features of every possible node type? • 80 different node types in XHTML… Overview Motivation I-Evolution M-Evolution S-Evolution

  11. Data Covariance class LinkedList { static class Node { Node next; Object data; … constructor not shown … } Node head, tail; void append(Object obj) { Node newNode = new Node(obj); … add newNode at end of list … } • Because each class needs a different node type, we can't use refinement. • The result: code duplication. Overview Motivation class BidiLinkedList extends LinkedList { static class BidiNode extends Node { Node prev; … new constructor not shown … } void append(Object obj) { BidiNode newNode = new BidiNode(obj); … add newNode at end of list … } I-Evolution M-Evolution S-Evolution

  12. Dynamic Shakeins • Shakeins are a superior alternative to AspectJ-style aspects. • Newer AOP languages support dynamic aspects. • Aspects can be applied/removed at runtime. • Applying/removing a shakein at runtime implies changing the object's class! • This was the original motivation for this work. Overview Motivation I-Evolution M-Evolution S-Evolution

  13. Dynamic Shakeins • For example: given an object of type Account, we wish to enable logging. • From Account to Logging<Account>. • … and back, as needed. • Another example: protect a List object by applying the ReadOnly shakein to it. • Turning it into ReadOnly<List> without changing the list content. Overview end:: Motivation I-Evolution M-Evolution S-Evolution

  14. I-Evolution

  15. I-Evolution • Move an object down the inheritance tree. • Syntax: v→T(…) • v is an object reference. • T is a type. • Must be a subtype of v's static type. • … indicates optional parameters. • → can be typed as ->. begin::I-Evolution Overview Motivation I-Evolution M-Evolution S-Evolution

  16. I-Evolution Example 1 class TCPConnection { // Listen state public void open() { … establish connection … this → TCPConnectionEstablished(); } … } • No need for method delegation. • Only one object in memory. • Note that connection objects cannot be "recycled" • No way to reverse state. • Solution: later… Overview class TCPConnectionEstablished extends TCPConnection { public void close() { … close connection … this → TCPConnectionClosed(); } … } Motivation I-Evolution class TCPConnectionClosed extends TCPConnectionEstablished { public void close() { throw new IllegalStateException(); } … } M-Evolution S-Evolution

  17. I-Evolution Example 2 class LinkedList { static class Node { Node next; Object data; … constructor not shown … } Node head, tail; void append(Object obj) { Node newNode = new Node(obj); … add newNode at end of list … } • BidiLinkedList.append is now a refinement of the inherited version. • No code duplication! Overview Motivation class BidiLinkedList extends LinkedList { static class BidiNode extends Node { Node prev; … new constructor not shown … } void append(Object obj) { BidiNode oldTail = (BidiNode) tail; super.append(obj); tail → BidiNode(); tail.prev = oldTail; } I-Evolution M-Evolution S-Evolution

  18. Evolvers • The change from class T to subclass T' might require code execution. • Required for preserving class invariants. • For example: when evolving from LinkedList to BidiLinkedList, we must go over the list and turn each Node into a BidiNode. • And instate the prev pointer while doing so. Overview Motivation I-Evolution M-Evolution S-Evolution

  19. Evolver Example class BidiLinkedList extends LinkedList { static class BidiNode extends Node { Node prev; … } public →BidiLinkedList() { // Evolver if (head == null) return; head → BidiNode(); BidiNode current = head; while (current.next != null) { current.next → BidiNode(); current.next.prev = current; current = current.next; } … • The evolver represents the "delta" between the superclass constructor and this class's constructor. • However, it must take into account the possibility that the object is in a non-virgin state. Overview Motivation I-Evolution M-Evolution S-Evolution • If no evolver is specified, default evolvers can often be deduced.

  20. How Can I-Evolution Fail? • I-Evolution never introduces runtime type errors. • i.e., when an object accepts a message, it knows how to handle it. • Yet the evolution operation itself can fail. • Failure #1:v→T(…), v is null. • Not an "empty operation" because we might expect the evolver code to do something. Overview Motivation I-Evolution M-Evolution S-Evolution

  21. How Can I-Evolution Fail? • Failure #2:v→T(…), and the evolver code →T throws an exception. • Just as new can fail due to exceptions. • Failure #3:v→T(…), but v's dynamic type is not a superclass of T. • Given: • This might fail: Overview end:: Motivation I-Evolution A Note: This is just like the downcast operation (B)a can fail! M-Evolution B C void foo(A a) { a → B(); // But what if ainstanceofC!? } S-Evolution

  22. M-Evolution

  23. Mixin Example • This mixin can be applied to any class that implements the List interface: begin::M-Evolution Overview Motivation mixin ReadOnly { inherited public void add(Object o); inherited public void remove(int index); public final void add(Object o) { throw new IllegalStateException(); } public final void remove(int index) { throw new IllegalStateException(); } } I-Evolution M-Evolution S-Evolution

  24. Is "ReadOnly" Useful? • We can now create objects of type, e.g., ReadOnly<Vector>. • However, even the constructor of this class will fail to add items to it! • The mixin looks useless, unless we can turn existing list objects into read-only. • … Evolution! Overview Motivation I-Evolution M-Evolution S-Evolution

  25. Evolving to ReadOnly • ReadOnly<Vector> is a new class, which extends Vector. • So we can use regular I-Evolution with it. • But a reference to List can actually be of type Vector, ArrayList, LinkedList, or any other implementation class! Overview Motivation I-Evolution M-Evolution if (lst instanceof Vector) lst → ReadOnly<Vector>(); else if (lst instanceof ArrayList) lst → ReadOnly<ArrayList>(); else … unbounded number of possibilities … S-Evolution I-Evolution doesn't cut it in this case.

  26. M-Evolution • Syntax: v→M<v>(…) • v is an object reference. • M is a mixin. • v is evolved into the class created by applying M to v's dynamic type! Overview Motivation I-Evolution M-Evolution lst → ReadOnly<lst>(); … works for any implementation of List! … S-Evolution

  27. Idempotent Mixins • M-Evolution can result in infinitely long inheritance threads, generated at runtime. • ReadOnly<ReadOnly<ReadOnly<Vector>>> • To prevent this, if mixin M is marked @Idempotent (or detected to be idempotent), then applying M to M<T> yields M<T>. Overview Motivation I-Evolution M-Evolution S-Evolution

  28. How Can M-Evolution Fail? • Existing failures: Evolving null, exception-throwing evolvers. • Avoided failures:never fails due to incorrect dynamic type! • New failure type: inability to apply mixin. • Final class / final members. • Accidental overriding. Overview end:: Motivation I-Evolution M-Evolution S-Evolution

  29. S-Evolution

  30. What is a Shakein? • A Shakein makes a re-implementation of a class. • It does not change the type. • We get a new implementation of an existing type. • Never introduces new non-private members. • A parameterized, generic-like structure. begin::S-Evolution Overview Motivation I-Evolution M-Evolution S-Evolution

  31. Shakein Example Overview shakein Logging { before execution of public methods { Log.log("Began " + methodName); } after successful execution of same { Log.log(methodName + " ended successfully"); } after failed execution of same { Log.log(methodName + " caused exception: " + e); } } Motivation I-Evolution M-Evolution S-Evolution

  32. S-Evolution • Syntax: v→S<v>(…) • v is an object reference. • S is a shakein. • v is evolved into the class created by applying S to v's dynamic type! Overview Motivation I-Evolution M-Evolution obj → Logging<obj>(); … works for just about any object! … S-Evolution

  33. Replacing One Shakein by Another • S-Evolution does not change the object's type. • Only it's (implementation) class. • It is therefore possible to undo S-Evolution without any risk for runtime type errors. • Or, replace one shakein with another. Overview Motivation I-Evolution M-Evolution S-Evolution

  34. State Groups • A set of shakeins can be declared as belonging to the same state group. • If S1, S2S, then: • State transition: Applying S1 to S2<T> yields S1<T>. • And vice versa. • All states are idempotent: Applying S1 to S1<T> yields S1<T>. • Likewise for S2. • i.e., an object can only have one shakein (state) from a given state group. • Note: idempotent mixins can be viewed as one-state groups. Overview Motivation I-Evolution M-Evolution S-Evolution

  35. State Group Example class TCPConnection { // Default = listen state public void open() { … establish connection … this → Established<this>(); } … } • Connection objects can now be recycled. Overview @StateGroup("Connection") shakein Established { public void close() { … close connection … this → Closed<this>(); } … } Motivation I-Evolution @StateGroup("Connection") shakein Closed { public void reset() { this -> Listen<this>(); } … } M-Evolution @StateGroup("Connection") shakein Listen { // Empty: restore default state } S-Evolution

  36. Dynamic Aspects with Shakeins @StateGroup("Log") shakein Logging { before execution of public methods { Log.log("Began " + methodName); } after successful execution of same { Log.log(methodName + " ended successfully"); } after failed execution of same { Log.log(methodName + " caused exception: " + e); } } @StateGroup("Log") shakein NotLogging { // Empty: restore default } Overview Motivation • Unlike some other dynamic aspect solutions: • No boolean test at every method call. • No list of aspects to iterate over. • Zero performance overhead when no shakeins are applied. • However, applying/removing a dynamic aspect (i.e., evolution) can be costly. • Depending on implementation strategy. • We expect this operation to be less common than method invocation. I-Evolution M-Evolution obj → Logging<obj>(); … obj → NotLogging<obj>(); S-Evolution

  37. How Can S-Evolution Fail? • Existing failures: Evolving null, exception-throwing evolvers. • Applying to final class / final members. • Avoided failures:never fails due to incorrect dynamic type! • Never fails due to accidental overriding! • Since no new members are introduced. Overview end:: Motivation I-Evolution M-Evolution S-Evolution

  38. Summary

  39. Summary • The quest for dynamic shakeins was successful. • … with several extra benefits. • Language designers can choose any subset of {I,M,S}-Evolution. • Some issues not discussed here: • The fine details of evolvers. • Multi-state objects. • Implementation strategies.

More Related