500 likes | 616 Vues
Explore a novel approach integrating Java with mixins, improving software modularity and reducing complexity. Learn about the benefits and challenges of mixin programming in application development.
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