Feature-oriented programming
≈ 10 min read
Names in other languages
No names in other languages are held for this entry yet.
Article bodies are English and are not machine-translated. A name in another language is not a translation of the article.
In computer programming, feature-oriented programming (FOP) or feature-oriented software development (FOSD) is a programming paradigm for program generation in software product lines (SPLs) and for incremental development of programs.
In computer programming, feature-oriented programming (FOP) or feature-oriented software development (FOSD) is a programming paradigm for program generation in software product lines (SPLs) and for incremental development of programs. p 1 = j + f -- program p 1 has features j and f p 2 = j + h -- program p 2 has features j and h p 3 = i + j + h -- program p 3 has features i, j, and h A GenVoca model of a domain or software product line is a collection of base programs and features (see MetaModels and Program Cubes). The programs (expressions) that can be created defines a product line. Expression optimization is program design optimization, and expression evaluation is program generation. Note: GenVoca is based on the stepwise development of programs: a process that emphasizes design simplicity and understandability, which are key to program comprehension and automated program construction. Consider program p 3 above: it begins with base program h, then feature j is added (read: the functionality of feature j is added to the codebase of h), and finally feature i is added (read: the functionality of feature i is added to the codebase of j•h). Note: not all combinations of features are meaningful. Feature models (which can be translated into propositional formulas) are graphical representations that define legal combinations of features. Note: A more recent formulation of GenVoca is symmetric: there is only one base program, 0 (the empty program), and all features are unary functions. This suggests the interpretation that GenVoca composes program structures by superposition, the idea that complex structures are composed by superimposing simpler structures. Yet another reformulation of GenVoca is as a monoid: a GenVoca model is a set of features with a composition operation (•); composition is associative and there is an identity element (namely 1, the identity function). Although all compositions are possible, not all are meaningful. That's the reason for feature models. GenVoca features were originally implemented using C preprocessor ( #ifdef feature ... #endif ) techniques. A more advanced technique, called mixin layers, showed the connection of features to object-oriented collaboration-based designs. Algebraic Hierarchical Equations for Application Design (AHEAD) generalized GenVoca in two ways. First, it revealed the internal structure of GenVoca values as tuples. Every program has multiple representations, such as source, documentation, bytecode, and makefiles. A GenVoca value is a tuple of program representations. In a product line of parsers, for example, a base parser f is defined by its grammar g f , Java source s f , and documentation d f . Parser f is modeled by the tuple f=[g f , s f , d f ]. Each program representation may have subrepresentations, and they too may have subrepresentations, recursively. In general, a GenVoca value is a tuple of nested tuples that define a hierarchy of representations for a particular program. Example. Suppose terminal representations are files. In AHEAD, grammar g f corresponds to a single BNF file, source s f corresponds to a tuple of Java files [c 1 ...c n ], and documentation d f is a tuple of HTML files [h 1 ...h k ]. A GenVoca value (nested tuples) can be depicted as a directed graph: the graph for parser f is shown in the figure to the right. Arrows denote projections, i.e., mappings from a tuple to one of its components. AHEAD implements tuples as file directories, so f is a directory containing file g f and subdirectories s f and d f . Similarly, directory s f contains files c 1 ...c n , and directory df contains files h 1 ...h k . Note: Files can be hierarchically decomposed further. Each Java class can be decomposed into a tuple of members and other class declarations (e.g., initialization blocks, etc.). The important idea here is that the mathematics of AHEAD are recursive. Second, AHEAD expresses features as nested tuples of unary functions called deltas. Deltas can be program refinements (semantics-preserving transformations), extensions (semantics-extending transformations), or interactions (semantics-altering transformations). We use the neutral term “delta” to represent all of these possibilities, as each occurs in FOSD. To illustrate, suppose feature j extends a grammar by Δg j (new rules and tokens are added), extends source code by Δs j (new classes and members are added and existing methods are modified), and extends documentation by Δd j . The tuple of deltas for feature j is modeled by j=[Δg j ,Δs j ,Δd j ], which we call a delta tuple. Elements of delta tuples can themselves be delta tuples. Example: Δs j represents the changes that are made to each class in s f by feature j, i.e., Δs j =[Δc 1 ...Δc n ]. The representations of a program are computed recursively by nested vector addition. The representations for parser p 2 (whose GenVoca expression is j+f) are: p 2 = j + f -- GenVoca expression That is, the grammar of p 2 is the base grammar composed with its extension (Δg j +g f ), the source of p 2 is the base source composed with its extension (Δs j +s f ), and so on. As elements of delta tuples can themselves be delta tuples, composition recurses, e.g., Δs j +s f = [Δc 1 ...Δc n ]+[c 1 ...c n ]=[Δc 1 +c 1 ...Δc n +c n ]. Summarizing, GenVoca values are nested tuples of program artifacts, and features are nested delta tuples, where + recursively composes them by vector addition. This is the essence of AHEAD. The ideas presented above concretely expose two FOSD principles. The Principle of Uniformity states that all program artifacts are treated and modified in the same way. (This is evidenced by deltas for different artifact types above). The Principle of Scalability states all levels of abstractions are treated uniformly. (This gives rise to the hierarchical nesting of tuples above). The original implementation of AHEAD is the AHEAD Tool Suite and Jak language, which exhibits both the Principles of Uniformity and Scalability. Next-generation tools include CIDE and FeatureHouse. Feature-Oriented Model-Driven Design (FOMDD) combines the ideas of AHEAD with Model-Driven Design (MDD) (a.k.a. Model-Driven Architecture (MDA)). AHEAD functions capture the lockstep update of program artifacts when a feature is added to a program. But there are other functional relationships among program artifacts that express derivations. For example, the relationship between a grammar g f and its parser source s f is defined by a compiler-compiler tool, e.g., javacc. Similarly, the relationship between Java source s f and its bytecode b f is defined by the javac compiler. A commuting diagram expresses these relationships. Objects are program representations, downward arrows are derivations, and horizontal arrows are deltas. The figure to the right shows the commuting diagram for program p 3 = i+j+h = [g 3 ,s 3 ,b 3 ]. A fundamental property of a commuting diagram is that all paths between two objects are equivalent. For example, one way to derive the bytecode b 3 of parser p 3 (lower right object in the figure to the right) from grammar g h of parser h (upper left object) is to derive the bytecode b h and refine to b 3 , while another way refines g h to g 3 , and then derive b 3 , where + represents delta composition and () is function or tool application: b 3 = Δb j + Δb i + ( ( g h ) ) = ( ( Δg i + Δg j + g h ) ) There are \tbinom{4}{2} possible paths to derive the bytecode b 3 of parser p 3 from the grammar g h of parser h. Each path represents a metaprogram whose execution generates the target object (b 3 ) from the starting object (g f ). There is a potential optimization: traversing each arrow of a commuting diagram has a cost. The cheapest (i.e., shortest) path between two objects in a commuting diagram is a geodesic, which represents the most efficient metaprogram that produces the target object from a given object. Note: A “cost metric” need not be a monetary value; cost may be measured in production time, peak or total memory requirements, power consumption, or some informal metric like “ease of explanation”, or a combination of the above (e.g., multi-objective optimization). The idea of a geodesic is general, and should be understood and appreciated from this more general context. Note: It is possible for there to be m starting objects and n ending objects in a geodesic; when m=1 and n>1, this is the Directed Steiner Tree Problem, which is NP-hard. Commuting diagrams are important for at least two reasons: (1) there is the possibility of optimizing the generation of artifacts (e.g., geodesics) and (2) they specify different ways of constructing a target object from a starting object. A path through a diagram corresponds to a tool chain: for an FOMDD model to be consistent, it should be proven (or demonstrated through testing) that all tool chains that map one object to another in fact yield equivalent results. If this is not the case, then either there is a bug in one or more of the tools or the FOMDD model is wrong. Note: the above ideas were inspired by category theory. ==Metamodels== Feature-oriented software development (FOSD) is a general paradigm for software generation, where a model of a product line is a tuple of 0-ary and 1-ary functions (program transformations). This page discusses a more abstract concept of models of product lines of product lines (PL**2) called metamodels, and product lines of product lines of product lines called meta-metamodels (PL**3), and further abstract concepts. A metamodel is a model whose instances are models. A GenVoca model of a product line is a tuple whose components are features (0-ary or 1-ary functions). An extension (a.k.a. delta or refinement) of a model is a "meta-feature", which is a tuple of deltas that can modify an existing product line by modifying existing features and adding new features. As a simple example, consider GenVoca model M that contains three features a-c: M = [ a, b, c ] Suppose meta-model MM contains three meta-features AAA-CCC, each of which is a tuple with a single non-identity feature: \begin{align} MM & = [ AAA, BBB, CCC ] \\ & = [ [a,0,0], [0,b,0], [0,0,c] ] \end{align} where 0 is the null feature. Model M is constructed by adding the meta-features of MM, where + is the composition operation (see FOSD). \begin{align} M & = AAA + BBB + CCC & \text{expression} \\ & = [a,0,0]+[0,b,0]+[0,0,c] & \text{substitution} \\ & = [a+0+0, 0+b+0, 0+0+c] & \text{composition} \\ & = [a,b,c] & \text{simplification where } 0+x=x+0=x \end{align} MM models a product line of product lines (PL**2). That is, different MM expressions correspond to GenVoca models of different product lines.
Text derived from https://en.wikipedia.org/w/index.php?oldid=1371634398 under CC BY-SA 4.0; modifications have been made.