The most commonly reused software product is source code, which is the final and most important product of software development. In addition to code, any intermediate life cycle products can be reused, which means that software developers can pursue the reuse of requirement documents, system specifications, modular designs, test plans, test cases, and documentation in various stages of software development.
Reusable software development knowledge and experience exists at different abstraction levels: the architecture level, the modular design level, and the program (or code) level. Research on software architecture is currently aiming to define different software architecture styles for different families of software systems [Perry and Wolf, 1992]. A software architecture style describes the formal arrangement of architectural elements, and can be reused by software developers to construct their new software systems once the style is well defined [Shaw and Garlan, 1996,Taylor et al., 1996]. For example, the domain-independent multifaceted architecture is an architecture style for domain-oriented design environments, which has been reused in and refined through the development of many generations of design environments for different domains [Fischer, 1994].
Reusable knowledge on modular design can be codified in design patterns [Alexander et al., 1977] and frameworks. A design pattern is the description of a solution to recurring problems. It specifies a problem to be solved, a solution that has stood the test of time, and the context in which the solution works [Gamma et al., 1994]. Design patterns provide a common vocabulary for software developers to discuss their designs and can be passed from one developer to another developer for reuse. The concept of framework comes from object-oriented programming languages [Fischer et al., 1995]. A framework describes the interaction pattern among a set of collaborative classes or objects, and can be represented as a set of abstract classes that interact with each other in a particular way [Johnson, 1997]. Programmers can reuse frameworks directly in their development after providing implementations for those abstract classes. Framework reuse is a mixture of knowledge reuse and code reuse.
Programming knowledge at the level of code is represented as program plans that can also be reused by programmers if a suitable representation form is defined [Rich and Waters, 1988].
The generation-based approach reuses the process of previous software development efforts, often embodied in computer tools that automate a part of the development life cycle [Henderson-Sellers and Edwards, 1990]. This approach weaves domain knowledge and programming knowledge into a very high-level programming language (VHLL), which is then converted to executable systems by a VHLL compiler or an application generator. Because VHLLs have a higher abstraction level than most high-level languages (HLLs), such as Java and C, they are relatively closer to programmers' informal requirements. They are meant for programmers to describe what the computer program does instead of how it is implemented. Compilers of VHLLs directly convert the VHLL programs into executable programs in HLLs. Lex and Yacc in Unix are two well-known examples; other research prototypes include SETL [Dubinsky et al., 1989] and PAISLey [Zave and Schell, 1984]. Unlike VHLL compilers, which make the conversion from VHLL programs to HLL programs in one step, application generators often use a series of transformation rules to transform VHLL programs into HLL programs. A transformation rule maps a program in one abstraction level to a semantically equivalent but more computationally efficient program [Feather, 1989]. Transformation-based application generators allow programmers to control which transformation rule is applied when several applicable rules exist [Biggerstaff, 2000]. Problems with the generation-based approach are the following:
The composition-based approach reuses existing software products in a new system to avoid repetitive work. As mentioned in the previous section, many types of software products can be reused. However, because this research focuses on the reuse of components, the discussion here is limited to component reuse, although many problems and solutions discussed can be extrapolated to the reuse of other software products. Component reuse is also known as component-based development. Based on the role that components contribute to the programming process, component reuse is further divided into three categories.