500 likes | 607 Views
Language and Compiler Support for Mixin Programming. Richard Cardone Calvin Lin, Advisor Department of Computer Sciences University of Texas at Austin April 22, 2002. The Problem. Large applications are difficult and expensive to build! Variation over time
E N D
Language and Compiler Support for Mixin Programming Richard Cardone Calvin Lin, Advisor Department of Computer Sciences University of Texas at Austin April 22, 2002
The Problem • Large applications are difficult and expensive to build! • Variation over time • Variation in execution environments Cardone Defense
Tangled feature code feature 1 Scattered feature code feature 2 feature 3 feature 4 feature 5 Variation over Time Class Hierarchy Scattered/Tangled code:hard to understand, maintain, and reuse Cardone Defense
Variation in Execution Environments • Need multiple versions of an application • Different users • Different market segments • Different computer architectures Support for multiple versions requires effective reuse Cardone Defense
Our Solution: Java Layers (JL) • Address problems of variation over time and environments • Build software from reusable components • Extend Java with mixins • Mixins: an object-oriented reuse technology • Provide novel language and compiler support for mixin programming Cardone Defense
Presentation Overview • Mixin Background • Contributions • Support for Mixin Programming • Addressing complexity • Increasing expressiveness • Evaluating Mixin Programming • Fidget: Building flexible widgets • ACE: Comparing OO frameworks • Conclusion & Future Work Cardone Defense
F1<Vector> F2<F1<Stack>> Stack Vector F1_Stack F1_Vector F2_F1_Stack Mixins as Reusable Components Mixins: types with parametrically-specified supertypes Prototypical JL Mixin Classes class F1<T> extends T {…} class F2<U> extends U {…} • Mixins increase modularity • Encapsulate feature implementations • Mixins support flexible composition • Parent/Child relationships are not hardcoded Cardone Defense
Mixins Increase Complexity • Increased flexibility can lead to increased complexity! • Can arbitrarily compose mixins Easy to make undesirable compositions • Supertypes are not known at definition time Initialization is tricky • Existing OO languages don’t support useful mixin idioms Cardone Defense
Why Java Layers? • Start with Java • Widespread use • Embodies good software engineering characteristics • Address complexity of mixin programming • Design and implement specialized mixin support Make mixins a practical way to program Cardone Defense
Contributions • Design new language and compiler support for mixin programming • Enhance effectiveness of mixins • Integrate mixin support into an OO language • Implement Java Layers as an extension of Java • Demonstrate effectiveness of mixin programming using Java Layers • Show that mixin programming improves application development Cardone Defense
Overview • Mixin Background • Contributions • Support for Mixin Programming • Addressing complexity • Increasing expressiveness • Evaluating Mixin Programming • Fidget: Building flexible widgets • ACE: Comparing OO frameworks • Conclusion & Future Work Cardone Defense
Mixin Initialization Problem: Mixin initialization is tricky because superclass is not known Classes class ParentA {ParentA(){…} …}class ParentB {ParentB(String s){…} …}class M<T> extends T {M(int i){x = i;…} …} Classes class ParentA {ParentA(){…} …}class ParentB {ParentB(String s){…} …}class M<T> extends T {M(int i){x = i;…} …} Classes class ParentA {ParentA(){…} …}class ParentB {ParentB(String s){…} …}class M<T> extends T {M(int i){x = i;…} …} Classes class ParentA {ParentA(){…} …}class ParentB {ParentB(String s){…} …}class M<T> extends T {M(int i){x = i;…} …} Instantiations M<ParentA> // OKM<ParentB> // ERROR! Superclass no-argument constructor implicitly called Cardone Defense
Previous Approaches to Mixin Initialization • Restrict constructor signatures • Often only no-arg constructor allowed • Sometimes special argument classes are used • Leads to ad-hoc initialization protocols • Special initialization methods • Maintenance of auxiliary data structures Cardone Defense
M<ParentB> ParentB M_ParentB Constructor Propagation JL Solution: Automatically add constructor arguments Redefined Classesclass ParentB {propagate ParentB(String s){…} …}class M<T> extends T {propagate M(int i){x = i;…} …} class M_ParentB extends ParentB { M_ParentB(int i, String s) {super(s); x = i;…} …} class M_ParentB extends ParentB { M_ParentB(int i,String s) {super(s); x = i;…} …} class M_ParentB extends ParentB { M_ParentB(int i, String s) {super(s); x = i;…} …} class M_ParentB extends ParentB { M_ParentB(int i, String s) {super(s); x = i;…} …} • Simple, orthogonal, no extra code to maintain • Reduces the number of hand-coded constructors Cardone Defense
Restricting Composition Problem: Mixins can be composed in arbitrary ways Common Solution: Use type parameter constraints to prohibit invalid or undesirable compositions Constrained Type Parameter Exampleclass TaskBase implements TaskIfc {…}class TaskQueue<T implements TaskIfc> extends T {…} Constrained Type Parameter Exampleclass TaskBase implements TaskIfc {…}class TaskQueue<T implements TaskIfc> extends T {…} InstantiationsTaskQueue<TaskBase> // OKTaskQueue<Hashtable> // ERROR! But What About:TaskQueue<TaskQueue<TaskBase>> // Type-safe, but… Cardone Defense
Semantic Checking • JL’s Semantic Checking goes beyond syntactic type checking • Tests for the presence, absence, ordering and cardinality of mixins • Tests use regular expression pattern matching and a count operator Single Use Idiom class TaskQueue<T implements TaskIfc> extends T requires unique {…} • Simpler programming model than previous approach [Batory97] • See thesis for details Cardone Defense
Overview • Mixin Background • Contributions • Support for Mixin Programming • Addressing complexity • Increasing expressiveness • Evaluating Mixin Programming • Fidget: Building flexible widgets • ACE: Comparing OO frameworks • Conclusion & Future Work Cardone Defense
Referencing the Most-Derived Class • Applications are built incrementally in layers using mixins • Features added one-by-one • Most-derived class in mixin hierarchy contains all features Linked List Example DNode<SNode<int>> class SNode<T> { T data; SNode<T> next;} SNode_int SNode_int next; class DNode<T> extends T { DNode<T> prev;} DNode_SNode_int DNode_SNode_int prev; We want next and prev to be type DNode_SNode_int Cardone Defense
Previous Approaches • Ad-hoc naming conventions • Fixed leaf class name • Configuration repositories [Czarnecki00] • Maintain auxiliary data • New type systems [Thorup97, Bruce97-98] • Powerful, but change Java semantics and implementation Cardone Defense
Implicit This Type Parameter • This refers to most-derived class in mixin-generated hierarchy • Implicit type parameter • This is bound at instantiation-time Linked List Example DNode<SNode<int>> SNode<int> class SNode<T> { T data;This next;} SNode_int SNode_int next; DNode_SNode_int next; class DNode<T> extends T {This prev;} DNode_SNode_int DNode_SNode_int prev; • Provides a static way to reference most-derived class • Easy to use Cardone Defense
feature 1 Encapsulating Feature Code Class Hierarchy Encapsulate feature code • Mixin Layers are mixins with nested types [Smaragdakis98] • Encapsulate application features that crosscut multiple classes • Specialize multiple (nested) classes simultaneously Cardone Defense
Defining Mixin Layers class BaseFidget { class Button {…} class Checkbox {…} …} class BaseFidget { class Button {…} class Checkbox {…} …} Basic widget support class LtWtFidget<T> extends T { class Button extends T.Button {…} class Checkbox extends T.Checkbox {…} …} class LtWtFidget<T> extends T { class Button extends T.Button {…} class Checkbox extends T.Checkbox {…} …} Basic display support class ColorFidget<T> extends T { class Button extends T.Button {…} class Checkbox extends T.Checkbox {…} …} Color display support Cardone Defense
... ColorFidget CheckBox Button Composing Mixin Layers ColorFidget<LtWtFidget<BaseFidget>> • Deep Conformance inheritance pattern for mixin layers [Smaragdakis99] • Enclosing classes form a hierarchy • Nested classes form hierarchies with corresponding nested classes ... BaseFidget Button CheckBox ... LtWtFidget Button CheckBox Cardone Defense
Alternative Implementations of Deep Conformance Constraints • One size fits all • Make all subtyping deeply conforming • Breaks existing code • Inappropriate semantics • Two sizes fit all [Smaragdakis99] • Types require either deeply conforming subtypes or they don’t • Requires knowledge about future usage • A more flexible approach • Specify deep conformance constraints in subtypes Cardone Defense
Expressing Deep Conformance in JL • JL’s deeply modifier enforces deep conformance • Types can require deeply conforming type parameters • Types can declare themselves to be deeply conforming T conforms to BaseFidget class ColorFidget<T extends BaseFidget deeply> extends T deeply {class Button extends T.Button {…} class Checkbox extends T.Checkbox {…} …} class ColorFidget<T extends BaseFidget deeply> extends T deeply {class Button extends T.Button {…} class Checkbox extends T.Checkbox {…} …} ColorFidget conforms to its superclass • First implementation of deep conformance • Simple, orthogonal, static • Ensures structural compatibility in mixin layer compositions Cardone Defense
The Big Picture Java Layers = Java + Constrained Parametric Polymorphism + Constructor Propagation + Implicit This Type Parameter + Deep Conformance + Semantic Checking Design only + Class Hierarchy Optimization Cardone Defense
Overview • Mixin Background • Contributions • Support for Mixin Programming • Addressing complexity • Increasing expressiveness • Evaluating Mixin Programming • Fidget: Building flexible widgets • ACE: Comparing OO frameworks • Conclusion & Future Work Cardone Defense
Evaluating Java Layers • Can we encapsulate application features in mixins? • If YES, then we automatically support application variation • Is JL’s language support for mixin programming effective? • Is mixin programming practical? • Do mixins improve application development? Cardone Defense
Device-Independent Programming • Today’s computing devices are diverse • Workstations, PDA’s, cell phones, consumer appliances • Different capabilities: CPU, RAM, I/O, graphics, storage, connectivity • Still, different devices often support the same function • Ex: User interface, network protocol stack Cardone Defense
Fidget = Flexible Widgets Problem: Same function is re-implemented for different devices • Re-engineer a subset of Java AWT widget library using mixin layers • Generate specialized GUI libraries for different devices • Workstations, PDAs and cell phones • Tailor interfaces to device capabilities • Minimize unneeded code • Generate GUI libraries from a single code-base Solution: Implement library code that’s reusable on dissimilar devices Cardone Defense
Generating Fidget Libraries Basic Fidget Class class BaseFidget { class Button {…} class Checkbox {…} …} Optional features implemented in 13 mixin layers: Color, event handling, look and feel, … GUI Library: Handles Mouse Events class Fidget extends EventMouse<LtWtFidget<BaseFidget>> {} GUI Library: Handles Mouse, Keys and Color class Fidget extends ColorFidget<EventKey<EventMouse<LtWtFidget<BaseFidget>>>> {} Cardone Defense
Fidget Results • Portable GUI libraries can be built using mixin layers • Encapsulate GUI features in mixin layers • Generate different GUI libraries from the same mixin code-base • JL language support effective • This and deeply are key to Fidget’s design • Most widget constructors are automatically generated Cardone Defense
Reuse with OO Frameworks • Frameworks are current state of the art OO reuse technology • Compare programming with mixins and programming with frameworks • Frameworks are application starter kits • Abstract classes provide partially implemented applications • Programmers supply concrete classes to complete applications Cardone Defense
The ACE Framework • Schmidt’s Adaptive Communication Environment (ACE) • C++ client/server application framework • Proven, mature OO framework technology • More than 60 commercial and academic applications Cardone Defense
Re-Engineering ACE • Re-engineer a subset of the ACE framework using mixins • Decompose ACE interfaces into smaller JL interfaces • JL interfaces define fine-grain application features • Each feature is implemented in a mixin • Compose applications by mixing and matching features Cardone Defense
ACE Interface Width 20 24 15 66 5 5 13 13 10 27 3 4 Avg. JL Interface Width 1.5 1.8 2.4 1.7 1.3 No. of ACE Interfaces Timer 1 1 Queue 1 Task Reactor 1 1 Acceptor 1 Connector No. of JL Interfaces 1.5 Re-Engineered Interfaces Cardone Defense
ACE Results • Avoids complex interfaces • Promotes smaller, faster executables • Avoids overfeaturing • Allows precise customization of applications • Avoids Framework Evolution problem • Separately evolving framework and application code JL advantages over frameworks: Cardone Defense
Related Work • Mixins defined as abstract subclasses[Bracha & Cook, 1990] • Useful in single inheritance languages • Mixins are reusable software components [VanHilst & Notkin, 1996] • Mixin Layers simplify mixin composition [Smaragdakis & Batory, 1998] • Encapsulate features that crosscut multiple classes • CLOS mixin classes use multiple inheritance[Moon, 1986; Keene, 1989] • CLOS mixin classes use multiple inheritance[Moon, 1986; Keene, 1989] Cardone Defense
Conclusion • Designed/Implemented novel support for mixin programming[Cardone & Lin, ICSE 2001], [Cardone, Brown, McDirmid & Lin, AOSD 2002] • Integrated mixin support into a conventional OO language • Implementation lessons described in thesis • Demonstrated benefits of mixin programming over current techniques[Batory, Cardone & Smaragdakis, SPLC 2000] Specialized language and compiler support make mixins a practical reuse technology Cardone Defense
Future Work • Build real-world applications using mixins • Implement a JL-to-bytecode compiler • Implement Semantic Checking and Class Hierarchy Optimization • Explore different Java bytecode representations for mixins • Explore generative programming • What compile-time code transformations should be supported? Cardone Defense
The End www.cs.utexas.edu/users/richcar/JavaLayers.html Cardone Defense
Semantic Checking • Undesirable compositions are often type-safe • Ex: TaskQueue<TaskQueue<TaskBase>> • JL’s Semantic Checking goes beyond syntactic type checking • Classes define semantic attributes • Each class hierarchy constructs an ordered attribute list • Classes test attribute lists • Tests use regular expressions and a count operator • Attributes are tested for presence, absence, ordering and cardinality • Test failure aborts compilation Cardone Defense
Semantic Checking Contributions • JL’s Semantic Checking is: • Simple • Static • Orthogonal • Expressive (so far) [Batory97] • Designed, but not implemented Cardone Defense
TCP Secure Compress LogError KeepAlive send(){…; super.send();} send(){…; super.send();} send(){…; super.send();} send(){…; super.send();} send(){…} Runtime Efficiency Fact: Mixins generate deep hierarchies of small classes Question: How does this affect performance? Network Protocol Stack KeepAlive<LogError<Compress<Secure<TCP>>>> Cardone Defense
Class Hierarchy Optimization • Class Hierarchy Optimization • Flatten hierarchies, but preserve leaf class interface • Inline methods • Simple idea, not so simple to do • Nested types • Access control • Contributions • Novel optimization • Novel design (not implemented) Cardone Defense
An Interesting Design Topic Basic Fidget Class class BaseFidget { abstract class Component {…} class Button extends Component {…} …} class BaseFidget { abstract class Component {…} class Button extends Component {…} …} Mixin Layers class LtWtFidget<T extends BaseFidget deeply> extends T deeply { abstract class Component extends T.Component {…} class Button extends T.Button {…} …} class LtWtFidget<T extends BaseFidget deeply> extends T deeply { abstract class Component extends T.Component {…} class Button extends T.Button {…} …} class ColorFidget<T extends BaseFidget deeply> extends T deeply { abstract class Component extends T.Component {…} class Button extends T.Button {…} …} … 11 other mixin layers Cardone Defense
BaseFidget ... Button Component LtWtFidget ... Button Component ColorFidget ... Button Component Building Fidget Libraries ColorFidget<LtWtFidget<BaseFidget>> Cardone Defense
The Sibling Pattern Basic Fidget Class • The Sibling design pattern • A nested class (Button) inherits from the most-derived subclass of its sibling class (Component) • Useful semantics for mixins • In a deeply conforming mixin layer, changes to a nested class can be inherited by its sibling classes • Pattern also used in GenVoca [Batory98] and Jiazzi [McDirmid01] class BaseFidget<> { abstract class Component {…} class Button extends This.Component {…} …} Cardone Defense
Key Insights • Mixins use feature-specific interfaces to enhance usability • Applications support only the interfaces/code they need • Mixins defer parent/child relationships to enhance flexibility • Could use mixins to build frameworks! Cardone Defense
Applications User Kernel HAL Graphic System Fidget Design Fidget Code Cardone Defense