
Challenge Problems for Separation of Concerns Jonathan Aldrich Department of Computer Science and Engineering University of Washington Box 352350, Seattle, WA 98195 USA [email protected] Abstract A number of techniques have been proposed to achieve a better separation of concerns in programming systems. How does one evaluate the benefits and drawbacks of the various alternatives, and offer guidance to the designers of future systems? This paper proposes a set of challenge problems for separation of concerns, each of which deals with different types or dimensions of concerns. Drawing from my experience with large, high-level object-oriented systems and from the separation of concerns literature, this paper classifies separation of concerns problems into a number of categories and chooses representative examples from each. I intend to continue this work by evaluating a range of current systems using these problems as benchmarks, and then using this experience to design better support for separation of concerns in the context of high-level object-oriented languages like Cecil. 1 Challenge Problems Challenge problems have long been useful in evaluating program design and implementation techniques. Parnas [P72] proposed the KWIC system as a benchmark to evaluate designs for ease of change, and showed that many kinds of change were easier in designs that used information hiding as a criterion, as opposed to a straightforward top-down functional decomposition. Object-oriented languages support good designs in the KWIC system and many others. However, other kinds of problems are harder to modularize with current language technology. A set of challenge problems is needed to pinpoint the weaknesses of current systems and evaluate techniques for a more clean separation of concerns. In this section, this paper proposes a set of problem categories that capture the wide range of separation of concerns problems in the literature and in practical experience. For each category, a representative challenge problem is chosen and other problems from the literature are mentioned. There is not enough space for a complete specification of each challenge problem, but the brief outlines given should be enough to capture many of the central issues in each problem category; future work includes more precise descriptions of these problems. The categories each encompass a significant range of problems and are largely orthogonal, but some overlap is justified because the different causes or rationales for problems in different categories may require different solutions, in general. 1.1 Functional Concerns A functional concern is a piece of functionality provided for a client. The client may be the user, another program, or even another component of the same program. In an ideal decomposition, a functional concern could be isolated to a single module. However, standard object-oriented decomposition can prevent the programmer from encapsulating a piece of functionality in a single module. In some cases, a functional concern may be spread among several objects. In other cases, a large object may deal with several different functional concerns, which are grouped into one object because they all operate on a single set of data. Because mainstream object-oriented languages require a module to be an object, they cannot modularize many functional concerns well. A challenge problem for modularizing functional concerns is separating different kinds of operations on a parse tree, a concern that has been suggested in the literature [TOHS99] and has come up in my own compiler work at the University of Washington. A good modularization would separate the methods and data members needed for each operation on the parse tree into its own module, so that one module would contain all the methods for type checking, another for tree display, etc: Statement.typecheck() { ... } (in typechecking module) Expression.typecheck() { ... } Object Aggregation/ Model Store Translation Coordinator Layer Economic Economic Spatial Submodel Augmentations Queries Actor Demographic Submodels Queries Households Submodel Query Buildings Location Grid Results Transportation Submodel Businesses Environmental Augmentations Updates Water Quality Economic Submodel Augmentations ... Figure 1. UrbanSim Architecture Other modules, organized by class as in conventional systems, would contain the core data structure & methods for each class in the parse tree. The Cecil language [C92] designed at UW does not have a module system, but because Cecil has “open objects” it is possible to add methods and members to a class from outside that class’s definition file. Thus, it is possible to encapsulate all the methods for performing one operation in a file devoted to a particular functional concern. This problem is also solved well in the Hyper/J [TOHS99] and AspectJ [K00] systems, which provide different ways to group methods by functionality rather than by class. Other problems in the literature include the various actions of a bottle deposit machine like depositing and printing a receipt [RA92], various composable pieces of data structure functionality such as searching and allocation [SB98], user interaction concerns such as directory listings and error messages in an FTP server [LM99], and many others. 1.2 Program Organization Program organization refers to the large-scale structure of the program, at the level of large interacting groups of objects. My interest in this concern arose from difficulty understanding Vortex [DDG+96], a compiler written in 100,000 lines of high-level Cecil code, without any documentation of the application’s control-flow or module structure. Large applications often have a large-scale structure (or software architecture) in order to separate concerns at the highest level of the application; however, because the source code doesn’t deal with any unit larger than a single object, this organization is rarely apparent from browsing the source code. This concern also arises when a single library supports a family of applications that are built by choosing a customized subset of objects and hooking them together to accomplish the desired behavior. Such program configurations are often awkward to specify in conventional object- oriented languages. Large-scale concerns like program organization are complimentary to smaller-scale issues like functional concerns, and play a similar role at a higher level of abstraction. The challenge problem was inspired by an application simulating urban development over time [NBW00]. Figure 1 shows UrbanSim’s software architecture. In order to provide a good structure for the simulation, a shared object store represents the current state of the simulation, and several independent model components implement various aspects of the simulation, such as economics, transportation, and demographics. This application structure is similar to the blackboard software architecture [GS94]. The challenge problem is therefore to explicitly represent a blackboard architecture, with an explicit connection diagram showing how the modules interact with a shared data store. The system should enforce the application constraint that the modules do not directly communicate, but only make modifications to the shared data. It should be easy to make changes like setting up another data store in the same program with a different set of simulation modules. Ideally, a tool would also be provided to graphically visualize the program structure. Other program organization problems include the other common architectural styles in Garlan & Shaw’s catalog [GS94], including pipe & filter, event-driven, and layered architectures. The abstraction and vertical extension techniques in the role-model work [RA92] can also be thought of as separating program organization concerns at design time. 1.3 Global Properties Global properties are notoriously difficult to enforce in a modular way using existing technologies. Typically, custom code must be added at every point where the global property could be changed to ensure that the required property continues to hold. This makes it difficult to change system-wide properties, or to implement them in a different way. It may also be tough to guarantee that all possible places where the property could be violated have been found. Examples of global properties include aliasing properties that prevent a private object reference from escaping a particular module [NVP98], various security properties, constraints that relate the values of variables spread throughout the program, global variables or constants, and synchronization between threads in a multithreaded system. My previous work in compiler analyses for eliminating unnecessary synchronization [ACSE99] was largely inspired by a desire to support cleaner synchronization specifications in an efficient way. Global property concerns are closely related to model checking and type system design. Constraints are very useful in specifying flexible graphical user interfaces [B93] and are a good challenge problem for separation of global property concerns. The programmer should be able to declaratively specify linear constraints and inequalities between ordinary floating-point program variables: constraint(window.right + offset < graphic.left); When the value of one variable changes over the course of program execution, violating a constraint, an off-the-shelf constraint solver is invoked to find variable values that maintain the constraints, ideally leaving the trigger variable’s value unchanged.
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages6 Page
-
File Size-