Many problems require recursively speci ed types of data and a collection of tools that operate on those data. Over time, these problems evolve so that the programmer must extend the toolkit or extend the types and adjust the existing tools accordingly. Ideally, this should be done without modifying existing code. Unfortunately, the prevailing program design strategies do not support both forms of extensibility: functional programming accommodates the addition of tools, while object-oriented programming supports either adding new tools or extending the data set, but not both. In this paper, we present a composite design pattern that synthesizes the best of both approaches and in the process resolves the tension between the two design strategies. We a l s o show h o w this protocol suggests a new set of linguistic facilities for languages that support class systems.
Evolutionary Software DevelopmentProgramming practice frequently confronts programmers with the following design dilemma. A recursively de ned set of data must be processed by s e v eral di erent tools. In anticipation of future extensions, the data speci cation and the tools should therefore be implemented such that it is easy to 1. add a new variant of data and adjust the existing tools accordingly, a n d 2. extend the collection of tools. Ideally, these extensions should not require any c hanges to existing code. For one, source modi cation is cumbersome and error-prone. Second, the source may not be available for modi cation because the tools are distributed in the form of object code. Finally, i t m a y be necessary to evolve t h e b a s e This dilemma manifests itself in many di erent application areas. A particularly important example arises in the area of programming languages. Language grammars are typically speci ed via BNFs, which denote recursively de ned data sets. Language-processing tools recursively traverse sentences formed from the grammar. In this scenario, a new form of data means an additional clause in the BNF new tools must be able to traverse all possible elements of the (extended) grammar.Unfortunately, p r e v ailing design strategies do not accommodate the required evolution:The \functional" approach, which is often realized with conventional procedural languages, implements tools as procedures on recursive t ypes. While this strategy easily accommodates the extension of the set of tools, it requires signi cant source modi cations when the data set needs to be extended. The (standard) \object-oriented" approach de nes a recursive set of data with a collection of classes, one per variant (BNF clause), and places one method per tool in each c l a s s . I n the parlance of object-oriented design patterns 13], this approach i s k n o wn as the Interpreter pattern. The problem it poses is dual to the problem of the functional approach: variants are easy to add, while tool additions require code modi cations. If the collection of tools is large, the designer may also use the Visitor pattern, a variant o f t h e Interpreter...