Using Mixin Technology to Improve Modularity

Total Page:16

File Type:pdf, Size:1020Kb

Using Mixin Technology to Improve Modularity CHAPTER 33 Using Mixin Technology to Improve Modularity by Richard Cardone and Calvin Lin In object-oriented languages, aspects can be defined by generalizing the idea of a class to that of a mixin. Mixins, which can be implemented as generic types, become aspects when they contain code for multiple classes. In this chapter, we describe mixins and we explain how mixins can be used to define aspects. We demonstrate the flexibility of mixin programming by prototyping a graphical user interface library that can be configured to run on dissimilar devices. We describe additional language and compiler sup- 1 2 Chapter 33 Using Mixin Technology to Improve Modularity port that increases the effectiveness of mixin programming. We conclude by proposing some new ideas about how mixins, and generic types in general, can be better supported in object-oriented languages. 33.1. INTRODUCTION One approach to reducing the cost of software is to make software easier to reuse and, in doing so, to reduce the risk and expense of developing new ap- plications. If existing software can be reused, then the cost of developing and maintaining new code can be significantly reduced. This ability to reuse code depends on two properties: modularity and easy composition. Modu- larity allows us to separate concerns [26], making code easier to understand, maintain, and treat as a unit. Easy composition allows us to combine the ca- pabilities of different code modules in different applications. Unfortunately, today’s object-oriented languages, such as Java, are lim- ited in their ability to modularize and compose code. Modularity is limited because the basic unit of encapsulation and reuse is the class. Once the or- ganization of a class hierarchy is fixed, it is always possible to define new 33.1. Introduction 3 features whose implementations crosscut the existing set of classes. It is common for features that add global properties, such as security, thread safety, fault tolerance, or performance constraints, to affect code in multiple classes. It is difficult to encapsulate such features in a single class. Instead, object-oriented programs generally consist of sets of collaborating classes [15], and changes to one class often require coordinated changes to others. Current object-oriented languages are also limited in their ability to compose features. Java’s support for composition depends primarily on sin- gle inheritance and subtype polymorphism. These mechanisms do not scale well when there are a large number of features. For example, there are three possible ways to organize two features, A and B, into classes: (1) put them in the same class, (2) make A a subclass of B, or (3) make B a subclass of A. B A A+B A B (1) (2) (3) 4 Chapter 33 Using Mixin Technology to Improve Modularity Each choice has different implications regarding the composition of A and B. For example, the first two choices force B to be included whenever A is in- cluded. Thus, by forcing the programmer to choose a single fixed class hier- archy, Java makes it difficult to compose a collection of features in an or- thogonal manner. As the number of features grows, this problem becomes more severe, because the number of possible feature combinations grows rapidly, but the number of feature combinations that can be practically sup- ported does not. This chapter describes how mixins [8], a kind of generic type, can im- prove the flexibility of Java class hierarchies, thereby improving the ability to modularize code and compose features. The purpose of this chapter is threefold. First, we provide an introduction to mixin programming. We de- scribe our mixin extension to Java and the additional language support that we implemented to increase the effectiveness of programming with mixins. Second, to give a concrete example, we summarize our previously published evaluation [12] of how mixins allow us to build customizable GUI libraries. In particular, we explain how a nested form of mixins, called mixin layers 33.2. Mixin Technology 5 [27] [28], can be used to implement a configurable GUI that runs on plat- forms with widely dissimilar capabilities, such as cell phones, PDAs, and PCs. We also show how mixin layers support the implementation of cross- cutting features, so mixin layers can be thought of as aspects [23]. Third, we propose a new approach of integrating mixins into object-oriented type sys- tems and a new way of reconciling the implementation tradeoffs inherent in parametric polymorphism. 33.2. MIXIN TECHNOLOGY Our approach to increasing reuse is to build into programming languages better support for modularization and composition. To test this approach, we have developed the Java Layers (JL) language [11] [20], which extends the compositional capability of Java. Java Layers extensions include support for constrained parametric polymorphism [10] and mixins. Parametric polymorphism allows types to be declared as parameters to code. Parametric polymorphism enhances reuse by allowing the same generic algorithm to be applied to different types; the 6 Chapter 33 Using Mixin Technology to Improve Modularity collection classes in C++’s Standard Template Library [31] are an example of this kind of reuse. JL’s implementation is similar to C++’s templates, but in keeping with most proposals [1] [9] [19] for adding generic types to Java, JL allows type parameters to be constrained. Mixins are types whose supertypes are specified parametrically. Mix- ins further enhance reuse over non-mixin parametric polymorphism by al- lowing the same subtype specialization to be applied to different supertypes. We give an example of mixin reuse in Section 33.2.1. Mixin layers [27] [28] are a special form of mixins that can be used to coordinate changes in multiple collaborating classes. Mixin layers are mix- ins that contain nested types, which can themselves be mixins. Fidget, our GUI framework described in Section 33.3, is built using mixin layers. 33.2.1 Mixins The term mixin was first used to describe a style of LISP programming that combines classes using multiple inheritance [21] [24]. Since then, the mixin concept has evolved to be that of a type whose supertypes are declared pa- 33.2. Mixin Technology 7 rametrically [8] [32]. We use the term in this sense and limit ourselves to languages such as Java that support single inheritance of classes. JL sup- ports mixins and other generic types by implementing parametric classes and interfaces. Mixins are useful because they allow multiple classes to be specialized in the same manner, with the specializing code residing in a single reusable class. For example, suppose we wanted to extend three unrelated classes– Car, Box and House–to have a “locked” state by adding two methods, lock() and unlock(). Without mixins, we would define subclasses of Car, Box, and House that each extended their respective superclasses with the lock() and unlock() methods. This approach results in replicating the lock code in three places. Using mixins, however, we would instead write a single class called Lockable that could extend any superclass, and we would instantiate the Lock- able class with Car, Box, and House. This approach results in only one defini- tion of the lock code. In JL, the Lockable mixin would be defined as follows: 8 Chapter 33 Using Mixin Technology to Improve Modularity class Lockable<T> extends T { private boolean _locked; public lock(){_locked = true;} public unlock(){_locked = false;} } The above class is parametric because it declares type parameter T. JL’s parametric types are similar in syntax and semantics to C++ template classes. When Lockable<T> is compiled, T is not bound. To use Lockable<T>, T must be bound to a type to create an instantiation of the parametric class. Each distinct binding of T defines a new instantiated type, which can then be used like a conventional Java type. What makes Lockable<T> a mixin, however, is that its instantiated types inherit from the types bound to T. Mixins are distinguished from other pa- rametric types because the supertypes of mixins are specified using type pa- rameters. Thus, a mixin’s supertypes are not precisely known at compile- time, but instead are specified at instantiation-time. Mixin instantiations generate new class hierarchies. For example, Lock- able<Box> generates the following hierarchy: 33.2. Mixin Technology 9 Box Lockable<Box> In its current form, Lockable’s capabilities are limited because nothing can be presumed about the type that gets bound to the type parameter T. In JL, however, constraints can be specified to restrict the types used in instan- tiations. For example, the following redefinition of Lockable guarantees that T’s binding type implements the physical object interface (not shown). This constraint on T means members of PhysicalObject can be used within Lock- able in a type-safe manner. class Lockable<T implements PhysicalObject> extends T {…} 33.2.2 Stepwise Refinement The GenVoca software component model [5] provides a conceptual frame- work for programming with mixins. The model supports a programming methodology of stepwise refinement in which types are built incrementally in layers. The key to stepwise refinement is the use of components, called 10 Chapter 33 Using Mixin Technology to Improve Modularity layers, that encapsulate the complete implementation of individual applica- tion features. Application features are any characteristic or requirement im- plemented by an application. Stepwise refinement allows custom applica- tions to be built by mixing and matching features. Mixins implement GenVoca layers. To see how mixins can be used to build applications incrementally, we define the Colorable and Ownable mixins in the same way that we defined the Lockable mixin above. Colorable man- ages a physical object’s color, and Ownable manages ownership properties. We can now create a variety of physical objects that support various combi- nations of features: Colorable<Ownable<Car>> Colorable<Lockable<Box>> Lockable<Ownable<Colorable<House>>> We can think of each of the above instantiations as starting with the ca- pabilities of some base class, Car, Box or House, and refining those capabilities with the addition of each new feature.
Recommended publications
  • Mixins and Traits
    ◦ ◦◦◦ TECHNISCHE UNIVERSITAT¨ MUNCHEN¨ ◦◦◦◦ ◦ ◦ ◦◦◦ ◦◦◦◦ ¨ ¨ ◦ ◦◦ FAKULTAT FUR INFORMATIK Programming Languages Mixins and Traits Dr. Michael Petter Winter 2016/17 What advanced techiques are there besides multiple implementation inheritance? Outline Design Problems Cons of Implementation Inheritance 1 Inheritance vs Aggregation 1 2 (De-)Composition Problems Lack of finegrained Control 2 Inappropriate Hierarchies Inheritance in Detail A Focus on Traits 1 A Model for single inheritance 1 2 Inheritance Calculus with Separation of Composition and Inheritance Expressions Modeling 2 3 Modeling Mixins Trait Calculus Mixins in Languages Traits in Languages 1 (Virtual) Extension Methods 1 Simulating Mixins 2 Squeak 2 Native Mixins Reusability ≡ Inheritance? Codesharing in Object Oriented Systems is often inheritance-centric. Inheritance itself comes in different flavours: I single inheritance I multiple inheritance All flavours of inheritance tackle problems of decomposition and composition The Adventure Game Door ShortDoor LockedDoor canPass(Person p) canOpen(Person p) ? ShortLockedDoor canOpen(Person p) canPass(Person p) The Adventure Game Door <interface>Doorlike canPass(Person p) canOpen(Person p) Short canPass(Person p) Locked canOpen(Person p) ShortLockedDoor ! Aggregation & S.-Inheritance Door must explicitely provide canOpen(Person p) chaining canPass(Person p) Doorlike must anticipate wrappers ) Multiple Inheritance X The Wrapper FileStream SocketStream read() read() write() write() ? SynchRW acquireLock() releaseLock() ! Inappropriate Hierarchies
    [Show full text]
  • Declaring Vars in Class Php
    Declaring Vars In Class Php Is Tobe Esculapian or misformed after aluminous Neall plopping so magnanimously? Forrest corresponds prolixly? Forbidden Osmund sometimes pargets any lilliputian yell guardedly. How variable as int, php in using interpolation rather than configured one of people prefer to override whatever information useful whenever you call it leads to expose parts that We daily work with advertisers relevant to our readers. Acceptable in php programmers and retry saving again, declaration must be. Declaring a property but a class is an exact task use one table the keyword public protected or private followed by a normal variable declaration If. If you wrong there holding an IE bug with var a foo only declaring a global for file scope. Your class declaration format is declared protected field? You help also define methods in the class that allow tool to manipulate the values of object properties and perform operations on objects. PHP Class Properties Tutorials by Supun Kavinda. An amazon associate we declare the class in declarations as containers for our clients in the usages of a name given client exits and in? How clean and in declaring a class declaration scope in the vars of that are their parent selector. Using long array syntax array 1 2 3 for declaring arrays is generally. By declaring a class declaration, classes and see for? It turns out some interview situations, every time to magento source and other class names but you have a common occurrence, therefore considered a value. The var keyword in PHP is used to declare the property or variable of class which is primitive by default The var keyword is alike as out when declaring variables or root of a class Note The var keyword was deprecated from version 50.
    [Show full text]
  • Interface Types for Haskell
    Interface Types for Haskell Peter Thiemann and Stefan Wehr Institut f¨urInformatik, Universit¨atFreiburg, Germany {thiemann,wehr}@informatik.uni-freiburg.de Abstract. Interface types are a useful concept in object-oriented pro- gramming languages like Java or C#. A clean programming style advo- cates relying on interfaces without revealing their implementation. Haskell’s type classes provide a closely related facility for stating an in- terface separately from its implementation. However, there are situations in which no simple mechanism exists to hide the identity of the imple- mentation type of a type class. This work provides such a mechanism through the integration of lightweight interface types into Haskell. The extension is non-intrusive as no additional syntax is needed and no existing programs are affected. The implementation extends the treat- ment of higher-rank polymorphism in production Haskell compilers. 1 Introduction Interfaces in object-oriented programming languages and type classes in Haskell are closely related: both define the types of certain operations without revealing their implementations. In Java, the name of an interface also acts as an interface type, whereas the name of a type class can only be used to constrain types. Interface types are a proven tool for ensuring data abstraction and information hiding. In many cases, Haskell type classes can serve the same purpose, but there are situations for which the solutions available in Haskell have severe drawbacks. Interface types provide a simple and elegant solution in these situations. A modest extension to Haskell provides the simplicity and elegance of interface types: simply allow programmers to use the name of a type class as a first- class type.
    [Show full text]
  • Chapter 8. Deploying an Osgi Service
    Chapter 8. Deploying an OSGi Service The OSGi core framework defines the OSGi Service Layer, which provides a simple mechanism for bundles to interact by registering Java objects as services in the OSGi service registry. One of the strengths of the OSGi service model is that any Java object can be offered as a service: there are no particular constraints, inheritance rules, or annotations that must be applied to the service class. This chapter describes how to deploy an OSGi service using the OSGi blueprint container. The Blueprint Container ........................................................................................................... 92 Blueprint Configuration ................................................................................................... 93 Defining a Service Bean .................................................................................................. 95 Exporting a Service ........................................................................................................ 98 Importing a Service ...................................................................................................... 104 Publishing an OSGi Service .................................................................................................... 113 Accessing an OSGi Service ..................................................................................................... 118 FUSE ESB Deploying into the OSGi Container Version 4.2 91 Chapter 8. Deploying an OSGi Service The Blueprint Container Blueprint Configuration
    [Show full text]
  • Learning Javascript Design Patterns
    Learning JavaScript Design Patterns Addy Osmani Beijing • Cambridge • Farnham • Köln • Sebastopol • Tokyo Learning JavaScript Design Patterns by Addy Osmani Copyright © 2012 Addy Osmani. All rights reserved. Revision History for the : 2012-05-01 Early release revision 1 See http://oreilly.com/catalog/errata.csp?isbn=9781449331818 for release details. ISBN: 978-1-449-33181-8 1335906805 Table of Contents Preface ..................................................................... ix 1. Introduction ........................................................... 1 2. What is a Pattern? ...................................................... 3 We already use patterns everyday 4 3. 'Pattern'-ity Testing, Proto-Patterns & The Rule Of Three ...................... 7 4. The Structure Of A Design Pattern ......................................... 9 5. Writing Design Patterns ................................................. 11 6. Anti-Patterns ......................................................... 13 7. Categories Of Design Pattern ............................................ 15 Creational Design Patterns 15 Structural Design Patterns 16 Behavioral Design Patterns 16 8. Design Pattern Categorization ........................................... 17 A brief note on classes 17 9. JavaScript Design Patterns .............................................. 21 The Creational Pattern 22 The Constructor Pattern 23 Basic Constructors 23 Constructors With Prototypes 24 The Singleton Pattern 24 The Module Pattern 27 iii Modules 27 Object Literals 27 The Module Pattern
    [Show full text]
  • Mixin-Based Programming in C++1
    Mixin-Based Programming in C++1 Yannis Smaragdakis Don Batory College of Computing Department of Computer Sciences Georgia Institute of Technology The University of Texas at Austin Atlanta, GA 30332 Austin, Texas 78712 [email protected] [email protected] Abstract. Combinations of C++ features, like inheritance, templates, and class nesting, allow for the expression of powerful component patterns. In particular, research has demonstrated that, using C++ mixin classes, one can express lay- ered component-based designs concisely with efficient implementations. In this paper, we discuss pragmatic issues related to component-based programming using C++ mixins. We explain surprising interactions of C++ features and poli- cies that sometimes complicate mixin implementations, while other times enable additional functionality without extra effort. 1 Introduction Large software artifacts are arguably among the most complex products of human intellect. The complexity of software has led to implementation methodologies that divide a problem into manageable parts and compose the parts to form the final prod- uct. Several research efforts have argued that C++ templates (a powerful parameteriza- tion mechanism) can be used to perform this division elegantly. In particular, the work of VanHilst and Notkin [29][30][31] showed how one can implement collaboration-based (or role-based) designs using a certain templatized class pattern, known as a mixin class (or just mixin). Compared to other techniques (e.g., a straightforward use of application frameworks [17]) the VanHilst and Notkin method yields less redundancy and reusable components that reflect the structure of the design. At the same time, unnecessary dynamic binding can be eliminated, result- ing into more efficient implementations.
    [Show full text]
  • Interface Evolution Via Virtual Extension Methods Brian Goetz Fourth Draft, June 2011
    Interface evolution via virtual extension methods Brian Goetz Fourth draft, June 2011 1. Problem statement Once published, it is impossible to add methods to an interface without breaking existing implementations. (Specifically, adding a method to an interface is not a source- compatible change.) The longer the time since a library has been published, the more likely it is that this restriction will cause grief for its maintainers. The addition of closures to the Java language in JDK 7 place additional stress on the aging Collection interfaces; one of the most significant benefits of closures is that it enables the development of more powerful libraries. It would be disappointing to add a language feature that enables better libraries while at the same time not extending the core libraries to take advantage of that feature1. V1 of the Lambda Strawman proposed C#-style static extension methods as a means of creating the illusion of adding methods to existing classes and interfaces, but they have significant limitations – for example, they cannot be overridden by classes that implement the interface being extended, so implementations are stuck with the “one size fits all” implementation provided as an extension2, and they are not reflectively discoverable. 2. Virtual extension methods3 In this document, we outline a mechanism for adding new methods to existing interfaces, which we call virtual extension methods. Existing interfaces can be augmented without compromising backward compatibility4 by adding extension methods to the interface, whose declaration would contain instructions for finding the default implementation in the event that implementers do not provide a method body.
    [Show full text]
  • Dynamic Interfaces
    Dynamic Interfaces Vasco T. Vasconcelos Simon J. Gay Antonio´ Ravara Departamento de Informatica´ Department of Computing Science SQIG at Instituto de Telecomunicac¸oes˜ Faculdade de Cienciasˆ da University of Glasgow, UK Department of Mathematics, IST, Universidade de Lisboa, Portugal [email protected] Technical University of Lisbon, Portugal [email protected] [email protected] Nils Gesbert Alexandre Z. Caldeira Department of Computing Science Departamento de Informatica´ University of Glasgow, UK Faculdade de Cienciasˆ da [email protected] Universidade de Lisboa, Portugal [email protected] Abstract 1. Introduction We define a small class-based object-oriented language in which Standard class-based object-oriented languages present the pro- the availability of methods depends on an object’s abstract state: grammer with the following view: an object is declared to belong to objects’ interfaces are dynamic. Each class has a session type which a certain type, and the type defines various methods; it is therefore provides a global specification of the availability of methods in possible at any time to call any of the methods described in the type. each state. A key feature is that the abstract state of an object However, there are often semantic reasons why it is not appropriate may depend on the result of a method whose return type is an to call a particular method when the object is in a particular inter- enumeration. Static typing guarantees that methods are only called nal state. For example: with a stack, one should not attempt to pop when they are available.
    [Show full text]
  • Create Mixins with Interfaces and Extension Methods by Bill Wagner
    Create Mixins with Interfaces and Extension Methods by Bill Wagner Mixins are small utility classes that define some useful functionality that will usually become part of something larger. For example, a class that implements a serial number to uniquely identify an object, or a timestamp that reports when an object was created. In C++, these mixin classes would be created using regular class definitions, and larger classes that wanted to use the mixin behavior would simply inherit from the mixin, in addition to any base classes it needed. Because the .NET Framework does not support multiple inheritance, we’ve typically used interface to define mixins. That works, but it’s not as powerful. One of the limitations of using interfaces to define mixin behavior is that every class that implements an interface must reimplement every method defined in that interface. That leads many developers to creating minimal interface definitions. (IEqualityComparer<T> has one method, IComparable<T> has only method). In those instances, the interface’s full functionality is completely defined in those small methods. But, what about cases where your interface can, or should, contain many more methods in order to support the developers that want to use the interface? That’s a perfect use case for extension methods. By creating extension methods using the interface, you can inject many more methods into the public definition of the interface, without forcing every developer to re-create those methods whenever he or she implements that interface. I’ve created a simple example based on strings that represent file paths. I often write classes that contain files or directories, usually for offline caches, or similar needs.
    [Show full text]
  • Variable-Arity Generic Interfaces
    Variable-Arity Generic Interfaces T. Stephen Strickland, Richard Cobbe, and Matthias Felleisen College of Computer and Information Science Northeastern University Boston, MA 02115 [email protected] Abstract. Many programming languages provide variable-arity func- tions. Such functions consume a fixed number of required arguments plus an unspecified number of \rest arguments." The C++ standardiza- tion committee has recently lifted this flexibility from terms to types with the adoption of a proposal for variable-arity templates. In this paper we propose an extension of Java with variable-arity interfaces. We present some programming examples that can benefit from variable-arity generic interfaces in Java; a type-safe model of such a language; and a reduction to the core language. 1 Introduction In April of 2007 the C++ standardization committee adopted Gregor and J¨arvi's proposal [1] for variable-length type arguments in class templates, which pre- sented the idea and its implementation but did not include a formal model or soundness proof. As a result, the relevant constructs will appear in the upcom- ing C++09 draft. Demand for this feature is not limited to C++, however. David Hall submitted a request for variable-arity type parameters for classes to Sun in 2005 [2]. For an illustration of the idea, consider the remarks on first-class functions in Scala [3] from the language's homepage. There it says that \every function is a value. Scala provides a lightweight syntax for defining anonymous functions, it supports higher-order functions, it allows functions to be nested, and supports currying." To achieve this integration of objects and closures, Scala's standard library pre-defines ten interfaces (traits) for function types, which we show here in Java-like syntax: interface Function0<Result> { Result apply(); } interface Function1<Arg1,Result> { Result apply(Arg1 a1); } interface Function2<Arg1,Arg2,Result> { Result apply(Arg1 a1, Arg2 a2); } ..
    [Show full text]
  • Using the Bridge Design Pattern for Osgi Service Update
    Using the Bridge Design Pattern for OSGi Service Update Hans Werner Pohl Jens Gerlach {hans,jens}@first.fraunhofer.de Fraunhofer Institute for Computer Architecture and Software Technology (FIRST) Berlin Germany Abstract In the OSGi framework, components cooperate by sharing service objects. The suggested way to replace a service by a newer version consists of updat- ing its containing components which requires a temporary shutdown of the component. Special care must be taken to avoid dangling references to old service instances. As this appears to be an overly expensive strategy, we describe the use of the well-known Bridge design pattern to decouple service replacement from component updates. Instead of registering services only references to instances of automatically generated bridge classes are registered. This solves not only the problem of dangling references but also avoids stopping and starting de- pendent bundles. 1 Introduction The Open Service Gateway Initiative (OSGi)[1] is a consortium that has specified a JavaTM component framework[2] for delivering, activating, and replacing services over wide-area networks to local-area networks and devices. Since OSGi server im- plementations can be quite small, it is a good candidate when looking for supporting runtime evolution in embedded systems. OSGi components interact by sharing so-called service objects. Services are reg- istered by one component and referenced by others. A major problem of OSGi com- ponent exchange at runtime is the replacement of service objects. Shutting down all dependent components and restarting the replaced sub-system, as recommended by OSGi, seems overly expensive. In this paper, we describe the use of the well-known Bridge design pattern to decouple service replacement from bundle updates.
    [Show full text]
  • Objectives: Interfaces [From Sun's Java Tutorial] Interfaces in Java
    Chulalongkorn University Name _____________________ International School of Engineering Student ID _________________ Department of Computer Engineering Station No. _________________ 2140105 Computer Programming Lab. Date ______________________ Lab 9 – OO Concept (Episode III) Objectives: • Understand the concept of interface • Understand interfaces in Java • Be able to define a class that implements an interface. Interfaces [from Sun’s Java Tutorial] There are a number of situations in software engineering when it is important for disparate groups of programmers to agree to a "contract" that spells out how their software interacts. Each group should be able to write their code without any knowledge of how the other group's code is written. Generally speaking, interfaces are such contracts. For example, imagine a futuristic society where computer‐controlled robotic cars transport passengers through city streets without a human operator. Automobile manufacturers write software (Java, of course) that operates the automobile—stop, start, accelerate, turn left, and so forth. Another industrial group, electronic guidance instrument manufacturers, makes computer systems that receive GPS (Global Positioning Satellite) position data and wireless transmission of traffic conditions and use that information to drive the car. The auto manufacturers must publish an industry‐standard interface that spells out in detail what methods can be invoked to make the car move (any car, from any manufacturer). The guidance manufacturers can then write software that invokes the methods described in the interface to command the car. Neither industrial group needs to know how the other group's software is implemented. In fact, each group considers its software highly proprietary and reserves the right to modify it at any time, as long as it continues to adhere to the published interface.
    [Show full text]