A Hybrid School
Approach
Sanjay Bhansali of Electrical Engr. and Computer Washington State University bhansali @ eecs.wsu.edu
a hybrid project that
ongoing engineering
approach addresses
task. The approach
to software reuse in an a challenging software is driven
by an architectural
design and makes use of both code components synthesis
technology.
choosing
the
We describe
reuse
strategy
criteria
for
and program
that were used in
different
parts
of
the
application and argue that to be successful a reuse strategy must be driven by the needs of an application program
instead of adapting a software development strategy around a reuse program.
1 Introduction Ever [1],
since
software
reasons
cited
issues
are quite
more
has remained
for its failure
non-technical obstacles
its inception
reuse
when
two
decades
an elusive
encompass
[2-4].
critical
than
Although trying
both
ago
goal.
The
technical
and
non-technical to institutionalize
reuse in an organization, the focus in this paper is on some of the technical issues that come into play when deciding on a software reuse strategy. A considerable literature exists on the many different approaches to software reuse (e.g. [5-7]). This paper is not intended to contribute to this literature by proposing a new technique, tool, or methodology. Instead, it describes a hybrid software reuse strategy, incorporating ideas that have been proposed earlier, in a challenging software engineering project. The contribution of the paper is in elucidating criteria that have been used in resolving trade-offs between different reuse techniques, and in determining what makes a particular reuse strategy effective, software
1.1
Geometric
constraint
Science
constraints between them, find a configuration, i.e. position, orientation, and dimension, of the geoms that satisfies all the constraints. Solving this problem is an integral task for constraint-based sketching and design, geometric modeling for computer-aided design, kinematics analysis of robots and other mechanisms, and describing mechanical assemblies. There are several ways of solving this problem; our approach has been inspired by a recently developed technique based on symbolic reasoning about geometry [8]. This approach employs a set of specialized routines that specify how to change the configuration of a geom using a fixed set of operators and the available degrees of freedom of a geom, so that a new constraint is satisfied while preserving the geom’s prior constraints. The resulting algorithm has polynomial time complexity and is more efficient than general-purpose constraint satisfaction algorithms. However, the success of this approach depends on one’s ability to construct a complete set of routines to handle all constraints on all geom types. The number of routines needed grows geometrically as the number of geoms and constraints between them increase. Worse, the complexity of the routines increases exponentially since the various constraints interact in subtle ways creating a large number of special cases that need to be individually handled. It is conceivable to throw many different programmers, each concentrating on writing specialized routines for a subset of the geoms and constraints, and then integrate the system since the various routines are independent of each other. However, such an approach is economically unjustified and is simply wasteful because much of the intellectual activity performed by programmers is similar; it would be much more efficient if this shared knowledge could be reused so as to eliminate duplication of effort by different programmers and thus enhance the overall productivity of the team. We will describe the approach to reuse that we have taken in this project, the rationale for the decisions, and the driving forces that dictated our choices.
Abstract We describe
to Software Reuse
satisfaction.
It is somewhat difficult
to gauge the effectiveness of a reuse strategy in an academic setting because of the logistics of applying it to really large projects where the pitfalls of seemingly simple reuse strategies get exposed. Therefore, it is particularly important to choose a realistic problem involving a significant amount of code to validate any reuse technique. The problem that our group is addressing is a complex, real-world problem, involves a considerable amount of coding, and would be difficult to justify economically without reuse to improve productivity. The problem can described as follows: given a collection of geometric bodies (called georn,s) and a set of
2. Hybrid
approach
to reuse
Specifically, we will describe how architecture-driven reuse, code component reuse, and program synthesis technology have been integrated to yield a cost-effective reuse strategy.
2.1
Architecture-driven
reuse.
By architectural design we mean the high-level decomposition of a system into subsystems together with the interface between the subsystems. In earlier work, several researchers including the author, have advocated that software architectures be used as a foundation for software reuse [9- 11]. This affords reuse at the level of entire
Permission to copy withoutfee all or part of this material is granted provided that the copies are not made or distributed for direct commercial advantage, the ACM copyright notice and the title of the publication and its date appear, and notice is given that copying is by permission of the Association of Computing Machinery.To copy otherwise, or to republish, requires a fee and/or specific permission. SSR ’95, Seattle, WA, USA 0 1995 ACM 0-89791 -739-1 /95/0004 ...$3.50
215
systems
rather
than
individual
code
components
and
up. One of the reasons why architecture based reuse issuperior to reuse of other artifacts, is that the architectural design is one of the most stable aspect of a software system. Although each module comprising a software system may change as a result of specification changes, the overall organization of the subsystems, the high-level functional and behavioral description of each subsystem, and the interface between the subsystems, remains constant. From a reuse perspective the key advantage to be gained from this observation is that we can create reusable libraries of modules that conform to the high-level functional and behavioral description of an architectural module. These modules have a much better chance of being reused than an unstructured collection of code components that has been thrown together in a library. To illustrate this point consider three different architectural designs shown in Figure 1 for a kinematics simulation application program that uses geometric constraint satisfaction as the underlying enabling technology. Design 1 uses a numerical package to iteratively solve a system of equations derived from the given constraints. This design has the advantage that it can be used to solve any set of constraints that can be expressed as a set of mathematical equations. However, because of performance reasons the simulation data has to be computed off-line and then interpreted to generate a simulation run. Design 2 uses symbolic algebraic manipulation to reduce a set of equations to create a compiled program for a particular geometric topology. Once that is created, the simulation can be run interactively for different simulation parameters. However, for different geometric topologies, the equations need to be re-compiled making the approach unsuitable for interactive applications. Design 3, that represents our approach, uses a set of specialized routines (we call them plan fragments to be consistent with earlier terminology) to solve constraints incrementally and since it is very efficient can be used to support interactive applications. (The drawback is that only those constraints for which the corresponding plan fragments are present in the plan-fragment library can be handled.) It is obvious that although the three designs all belong to the same application domain and address the same problem, there is very little in the way of sharable modules between them (excluding parts of the user interface). Any attempt to reuse modules in this application area outside the scope of the architectural design would not be successful. ourselves to one On the other hand, if we restrict therefore
has a better
chance
of
scaling
Constraints +
Iterative
simulation
Solver
\
be much more likely to be reused. The architectural design also makes
aspects
of the design
will
benefit
from
it clear
Display +%
I
(a) Design 1
I
I Compiled solution
4
q Interpreter
Simulation User
inputs
Interface
Simulation
-%
Results
(b) Design 2
Constraints
Application Geometric
User Interface
Program
constraint Engine
update
Actions
I
Q
[
I
I
Pkml?ragmentLibrary
(c) Design 3
which
reuse and which
Program
Data
architectural design, we could create modules that are closely related, will be inter-operable with each other, and will
Application
inputs
Figure 1. Three different architectural
will
designs for the
geometric constraint satisfaction problem
not. For example, in Design 3, it is clear that the geometric constraint engine is a relatively stable part of the system and is not likely to change. The user interface and the plan libraries on the other hand are expected to evolve as more complex geometries and constraints are added. Therefore,
most of the reuse effort interface
216
and plan library
should
be expended
subsystems.
on the user
2.2
Reuse
of
code
itself can be based on theorem proving (e.g. [13]), transformational system (e.g. [14]), or planning (e.g. [15]). The criteria to be used for using a program synthesis system include: ● How easy is it to specify a computation in the specification language? ● How much effort will it take to identify, represent, and debug the necessary domain knowledge? ● How complex is the program synthesis process? ● How much of the programming task can be automated using the program synthesis system? From these criteria, we can deduce that a program synthesis approach would be most effective for those parts of the system where a large number of similar modules are written with some variations, all the modules are based on a relatively small amount of domain specific knowledge, and the modules are complex enough that writing, testing, and debugging them requires significant effort. In our application, the various plan fragments meet these criteria quite well. To write these plan fragments, programmers have to.reason about the effect of various operators on the constraint associated with various geoms, the intersection of various loci (that represent a set of valid solutions), and the occurrence of boundary conditions (e.g. when the intersection of two lines is a line or null instead of a point). We have identified all these different kinds of knowledge used by programmers and are currently implementing a planning based program synthesizer that uses this knowledge to automatically y generate the plan fragment logic. The planner takes a specification of a plan fragment as input and produces a plan fragment as output, The specification is given by simply listing the set of invariants on a geom, and the new constraint to be achieved. The planner then constructs a search tree by applying actions that preserve some invariants while achieving some new one, until it finds a state where all existing invariants and the new constraint are satisfied. The sequence of actions from the root to the solution state forms the skeletal plan fragment. This is then further elaborated to take exception conditions into account. The program synthesizer is not completely automatic. For example, certain exception conditions are automatically identified by the planner, but a programmer still has to write the code fragment describing how exception conditions are handled. Further details of this process can be found in [16]. In this application, the use of a program synthesizer has several advantages: ● It reduces the effort on the part of the programmer who simply writes the specification of the desired plan fragment (and certain exception conditions that are currently not handled by the planner). The specification is typically 20-100 times shorter than the corresponding plan fragment. ● It reduces errors in the plan fragment thus reducing the amount of effort expended in validating plan fragments. ● It results in more consistent behavior of the system, since any heuristics that are used get shared by all the plan fragments. For example, when choosing from among multiple solutions, the same strategy is used and
components
An architecture context is not enough to ensure that software reuse will be successful. In [7], Krueger states an important principle about software reuse: For a software reuse technique to be effective, it must reduce the cognitive distance between the initial concept
of
a
system
and
its
final
executable
implementation. Cognitive “intellectual to the next.”
distance effort
is
meant
required
to
be
a measure
to take a software
An implication
of the above
of
the
from one stage principle
is that
only if the effort to identify, understand, and integrate a code component is sufficiently small so that programmers opt to reuse rather than rewrite the code fragment. This explains why the best known successes of code components has been in applications where one-word abstractions are enough to describe components (e.g. numerical analysis libraries and statistical packages). The abstractions in these applications are universally understood by programmers because of deeply ingrained and shared application domain terminology. Indeed, in many cases programmers don’t need to be told about the specific routines that are available and seem to know what kinds of routines they can expect to find in the library. It is important to keep this principle in mind when adopting a reuse strategy based on code component reuse. In our application, we use code component reuse in only one part of the system - a module containing subroutines that measure relationships between geometric objects, e.g. distance-between -point-and-line, line-line-intersection, and tangent-from-point. The meaning of these terms are thoroughly familiar to all programmers based on their extensive exposure to high school geometry; thus, very little intellectual effort is expended in understanding the functionality of the subroutines (we provide an informal description with each code fragment to explain the input and output arguments that each routine takes; however, no further formal description is required). We believe that this process of identifying areas where there is a shared understanding and terminology and exploiting them for reuse opportunities has a much greater chance of success than designing sophisticated classification and retrieval schemes for a library composed of unfamiliar code components. code component
2.3
Program
reuse will
be effective
Synthesis
A quite different and powerful form of reuse is obtained by employing a high-level specification language in which a what needs to be computed; a programmer specifies program synthesis system is then used to automatically generate executable code that describes how the computation is done. The artifact being reused in program synthesis is that is required to map a high-level the domain knowledge specification into executable code patterns. This knowledge is encoded as part of the program synthesis system in the form of inference rules, transformational rules, or as a domain theory [12]. The program synthesis mechanism
217
applied
consistently
programmer ● It
to all plan
requirements
change.
needs to be changed constraints. changes
fragments
instead
applying a different heuristic. makes it easy to maintain the
This
For example, to handle
would
require
suppose
3D constraints a major
to each and every plan fragment
obtained when the approach is scaled up to handle more complex constraints. We expect significantly higher productivity, fewer errors, and more maintainable code using our approach.
of each
system
when
that the system instead
revision
of 2D
References
requiring
in the system.
But
1.
only the relevant rules need to be changed and the new plan fragments would be automatically synthesized. The rules are difficult to write and we have found that it is necessary to spend some effort in debugging the rules. However, we estimate that the effort to write and debug rules is still an order of magnitude less than writing and debugging code. Clearly, the program synthesis technology being used here is highly domain-specific and would not be applicable to all domains (for examples of the use of this technology to other software engineering related tasks see [15, 17]). The contribution of our work lies is describing what criteria we used in choosing a program synthesis technology (e.g. the existence of a small number of operators, the interaction of a small number of constraints to create combinatorial number of cases), For other applications, other program synthesis technology might be more appropriate and it would be up to the reuse implementor to make a judicious choice. with
~.
a program
synthesizer,
2. 3.
McIlroy, M. D., Mass produced software components, in Software Engineering: Report on a conference by Science Committee, P. Naur and B. the NATO Randell, Editors. NATO Scientific Affairs Division: Brussels, Belgium, 1968: p. 138-150. of software reuse. Computer, Jones, C., Economics 27(7), 1994: p. 106-107. of reuse: new Bollinger, T. B., The economics approaches
4.
5.
6. 7.
Conclusions
8.
We have described a complex software engineering application and the reuse strategy that we are pursuing to develop the software in a cost-effective manner. The points that have been made in the ~aDer are summarized below: ● A reuse strategy mus~ ~e driven by the needs of an application program instead of adopting the software development strategy around a reuse program. ● The architectural design of an application should form the basis for determining which aspects of the system would benefit by reuse. Modules that are stable or one of a kind are not likely to benefit by reuse and the reuse effort should be targeted to other parts of the system. ✎ Code component reuse should be restricted to those parts where there is a shared understanding of terms so that simple abstractions are enough to describe the components. ✎ Program synthesis technology should be considered for those aspects of the system ~hat have a large number of similar modules with small variations between them. Other criteria like the complexity of the program synthesis process, the difficulty of domain knowledge acquisition, and the degree of automation should dictate whether the program synthesis approach would be costeffective. We are currently applying the reuse strategy described in this paper in our project. Initial estimates suggest that the application of this approach for fairly complex geom and set of constraints would require almost the same effort as designing without reuse (this is because the development of the reuse technology would require considerable effort). The time for testing and debugging is estimated to be much shorter. However, the real benefits of this approach will be
9.
10.
to
Proceedings
of the
12. 13.
14.
15.
16.
17.
assistant process.
Workshop
Architectures.,
assessing
cost.
on Domain-Specific
that
Software
supports the soflware SIGSOFT/SIGPLAN
in ACM
Engineering Development
218
and
Engineering Institute, 1990. design idioms for software Shaw, M. Heterogeneous architecture. in 6th International Workshop on Software Specification and Design. Como, Italy, 1991. Theories Smith, D.R. and M.R. Lowry, Algorithm and Design Tactics. Kestrel Institute, 1989. The deductive Manna, Z. and R. Waldinger, foundations of computer programming: AddisonWesley, 1993. implementation: an Balzer, R., Transformational example, IEEE Transactions on Software Engineering, 7(1), 1981: p. 3-13. of UNIX Bhansali, S. and M.T. Harandi, Synthesis programs using derivational analogy. Machine Learning, 10(1), 1993: p. 7-55. from first Bhansali, S. and G.A. Kramer. Planning principles for geometric constraint satisfaction. in Proceedings of AAAI-94. Seattle, WA: AAAI Press/MIT Press, 1994. intelligent Huff, K.E, and V.R. Lesser, A plan-based Software
11.
modelling
Information and Software Technology, 36(8), 1994: p. 475-484. Proceedings of the Sixth Annual Workshop on So~tware Reuse. IEEE Computer Society Technical C~mmittee on Software Engineering, 1993. Tracz, W., ed. Software Reuse: Emerging Technology. IEEE Computer Society Press: Los Alamitos, CA, 1988. Biggerstaff, T.J. and A.J. Perlis, eds. Software Reusabili~, Vol. 1 & 2. Addison-Wesley, 1989. Reuse. ACM Computing Krueger, C. W., Software Survey, 24(2), 1992: p. 131-182. Constraint Engine. Kramer, G. A., A Geometric Artificial Intelligence, 58(1-3), 1993: p. 327-360. synthesis using generic Bhansali, S., Software architectures. Automating Software Engineering, 1(3), 1994: p. 239-279.
Symposi~m Environments.
on
development Software
Practical
Boston, MA,
Software
1988.