
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 reflect the structure of the design. At the same time, unnecessary dynamic binding can be elimi- Combinations of C++ features, like inheritance, nated, resulting into more efficient implementa- templates, and class nesting, allow for the expres- tions. Unfortunately, this method resulted in very sion of powerful component patterns. In particular, complex parameterizations, causing its inventors to research has demonstrated that, using C++ mixin question its scalability. classes, one can express layered component-based designs concisely with efficient implementations. The mixin layers technique was invented to address In this paper, we discuss pragmatic issues related to these concerns. Mixin layers are mixin classes component-based programming using C++ mixins. nested in a pattern such that the parameter (super- We explain surprising interactions of C++ features class) of the outer mixin determines the parameters and policies that sometimes complicate mixin (superclasses) of inner mixins. In previous work implementations, while other times enable addi- [4][25][26], we showed how mixin layers solve the tional functionality without extra effort. scalability problems of the VanHilst and Notkin method and result into elegant implementations of 1Introduction collaboration-based designs. Large software artifacts are arguably among the This paper discusses practical issues related to most complex products of human intellect. The mixin-based programming. We adopt a viewpoint complexity of software has led to implementation oriented towards C++ implementations, but our methodologies that divide a problem into manage- discussion is not geared towards the C++ expert. able parts and compose the parts to form the final Instead, we aim to document common problems product. Several research efforts have argued that and solutions in C++ mixin writing for the casual C++ templates (a powerful parameterization mech- programmer. Additionally, we highlight issues that anism) can be used to perform this division ele- pertain to language design in general (e.g., to Java gantly. parameterization or to the design of future lan- guages). Most of the issues clearly arise from the In particular, the work of VanHilst and Notkin interaction of C++ features with the constructs [30][31][32] showed how one can implement col- under study. The discussion mainly stems from laboration-based (or role-based) designs using a actual experience with C++ mixin-based imple- certain templatized class pattern, known as a mixin mentations but a few points are a result of close class (or just mixin). Compared to other techniques examination of the C++ standard, since they refer (e.g., a straightforward use of application frame- to features that no compiler we have encountered works [17]) the VanHilst and Notkin method yields implements. Even though we present an introduc- less redundancy and reusable components that tion to mixins, mixin layers, and their uses, the pri- 1. We gratefully acknowledge the sponsorship of Microsoft Research, the Defense Advanced Research Projects Agency (Cooper- ative Agreement F30602-96-2-0226), and the University of Texas at Austin Applied Research Laboratories. 1 mary purpose of this paper is not to convince To give an example, consider a mixin implement- readers of the value of these constructs. (The ing operation counting for a graph. Operation reader should consult [4], [25], [26], [27], or [30] counting means keeping track of how many nodes for that.) and edges have been visited during the execution of a graph algorithm. (This simple example is one We believe that the information presented here rep- of the non-algorithmic refinements to algorithm resents a valuable step towards moving some pow- functionality discussed in [34]). The mixin could erful programming techniques into the mainstream. have the form: We found that the mixin programming style is quite practical, as long as one is aware of the possi- template <class Graph> class Counting: public Graph { ble interactions with C++ idiosyncrasies. As C++ int nodes_visited, edges_visited; compilers move closer to full implementation of public: the language standard (e.g., some compilers Counting() : nodes_visited(0), already support separate template compilation) the edges_visited(0), utility of such techniques will increase rapidly. Graph() { } node succ_node (node v) { nodes_visited++; 2 Background (Mixins and Mixin Layers) return Graph::succ_node(v); } The term mixin class (or just mixin) has been over- edge succ_edge (edge e) { loaded in several occasions. Mixins were originally edges_visited++; explored in the Lisp language with object systems return Graph::succ_edge(e); like Flavors [21] and CLOS [18]. In these systems, } ... mixins are an idiom for specifying a class and }; allowing its superclass to be determined by linear- ization of multiple inheritance. In C++, the term By expressing operation counting as a mixin we has been used to describe classes in a particular ensure that it is applicable to many classes that (multiple) inheritance arrangement: as superclasses have the same interface (i.e., many different kinds of a single class that themselves have a common of graphs). We can have, for instance, two different virtual base class (see[29],p.402).(Thisisnot the compositions: meaning that we will use in this paper.) Both of Counting< Ugraph > counted_ugraph; these mechanisms are approximations of a general and concept described by Bracha and Cook [6]. The Counting< Dgraph > counted_dgraph; idea is simple: we would like to specify an exten- for undirected and directed graphs. (We omit sion without pre-determining what exactly it can parameters to the graph classes for simplicity.) extend. This is equivalent to specifying a subclass Note that the behavior of the composition is while leaving its superclass as a parameter to be exactly what one would expect: any methods not determined later. The benefit is that a single class affecting the counting process are exported (inher- can be used to express an incremental extension, ited from the graph classes). The methods that do valid for a variety of classes. need to increase the counts are “wrapped” in the mixin. Mixins can be implemented using parameterized inheritance. The superclass of a class is left as a VanHilst and Notkin demonstrated that mixins are parameter to be specified at instantiation time. In beneficial for a general class of object-oriented C++ we can write this as: designs [30]. They used a mixin-based approach to implement collaboration-based (a.k.a. role-based) template <class Super> designs [5][15][16][22][30]. Role-based designs class Mixin : public Super { are based on the view that objects are composed of ... /* mixin body */ }; different roles that they play in their interaction with other objects. The fundamental unit of func- tionality is a protocol for this interaction, called a 2 collaboration. The mixin-based approach of Van- laboration are represented by inner classes of the Hilst and Notkin results in efficient implementa- layer. Inheritance works at two different levels. tions of role-based designs with no redundancy. First, a layer can inherit entire classes from its Sometimes, however, the resulting parameteriza- superclass (i.e., the parameter of the layer). Sec- tion code is quite complicated (i.e., many mixins ond, inner classes inherit members (variables, need to be composed with others in a complex methods, or even other classes) from the corre- fashion). This introduces some scalability prob- sponding inner classes in the superclass layer. This lems (namely, extensions that instantiate template dual application of inheritance simplifies the parameters can be of length exponential to the implementation of collaboration-based designs, number of mixins composed—see [25]). To make while preserving the benefits of the VanHilst and the approach more practical, by reducing its com- Notkin method. An important source of simplifica- plexity, mixin layers were introduced. Because tions is that inner classes of a mixin layer can refer mixin layers are an incremental improvement of unambiguously to other inner classes—the layer the VanHilst and Notkin method, we only discuss acts as a namespace. implementing collaboration-based designs using mixin layers. We illustrate our point with an example (presented in detail in [25]) of a collaboration-based design Mixin layers [25][26][27] are a particular form of and its mixin layers implementation. (Full source mixins. They are designed with the purpose of code is available, upon request.) This example pre- encapsulating refinements for multiple classes. sents a graph traversal application and was exam- Mixin layers are nested mixins such that the ined initially by Holland [16] and subsequently by parameter of an outer mixin determines the param- VanHilst and Notkin [30]. This application defines eters of inner mixins. The general form of a mixin three different algorithms on an undirected graph, layer in C++ is: all implemented using a depth-first traversal: Ver- tex Numbering numbers all nodes in the graph in template <class NextLayer> depth-first order, Cycle Checking examines class ThisLayer : public NextLayer { whether the graph is cyclic, and Connected public: Regions classifies graph
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages11 Page
-
File Size-