Several guidelines are directed at the issue of maintainability. Maintainable code is easy to change to meet new or changing requirements. Maintainability plays a special role in reuse. When attempts are made to reuse code, it is often necessary to change it to suit the new application. If the code cannot be changed easily, it is less likely to be reused.
There are many issues involved in software reuse: whether to reuse parts, how to store and retrieve reusable parts in a library, how to certify parts, how to maximize the economic value of reuse, how to provide incentives to engineers and entire companies to reuse parts rather than reinvent them, and so on. This chapter ignores these managerial, economic, and logistic issues to focus on the single technical issue of how to write software parts in Ada to increase reuse potential. The other issues are just as important but are outside of the scope of this book.
One of the design goals of Ada was to facilitate the creation and use of reusable parts to improve productivity. To this end, Ada provides features to develop reusable parts and to adapt them once they are available. Packages, visibility control, and separate compilation support modularity and information hiding (see Guidelines 4.1, 4.2, 5.3, and 5.7). This allows the separation of application-specific parts of the code, maximizes the general purpose parts suitable for reuse, and allows the isolation of design decisions within modules, facilitating change. The Ada type system supports localization of data definitions so that consistent changes are easy to make. Generic units directly support the development of general purpose, adaptable code that can be instantiated to perform specific functions. Using these features carefully, and in conformance to the guidelines in this book, produces code that is more likely to be reusable.
Reusable code is developed in many ways. Code may be scavenged from a previous project. A reusable library of code may be developed from scratch for a particularly well understood domain: such as a math library. Reusable code may be developed as an intentional byproduct of a specific application. Reusable code may be developed a certain way because a design method requires it. These guidelines are intended to apply in all of these situations.
The experienced programmer recognizes that software reuse is much more a requirements and design issue than a coding issue. The guidelines in this section are intended to work within an overall method for developing reusable code. This section will not deal with artifacts of design, testing, etc. Some research into reuse issues related specifically to the Ada language can be found in AIRMICS (1990), Edwards (1990), and Wheeler (1992).
Regardless of development method, experience indicates that reusable code has certain characteristics, and this chapter makes the following assumptions:
This chapter should not be read in isolation. In many respects, a well-written, reusable component is simply an extreme example of a well-written component. All of the guidelines in the previous chapters apply to reusable components as well as components specific to a single application. The guidelines listed here apply specifically to reusable components.
In this chapter...
8.1 Understanding and Clarity
8.1.1 Application-Independent Naming
8.1.3 Generic Formal Parameters
8.2.1 Named Numbers
8.2.2 Unconstrained Arrays
8.2.4 Subtypes in Generic Specifications
8.2.5 Overloading in Generic Units
8.2.6 Hidden Tasks
8.3.1 Complete Functionality
8.3.2 Generic Units
8.3.3 Using Generic Units to Encapsulate Algorithms
8.3.4 Using Generic Units for Abstract Data Types
8.3.6 Private and Limited Private Types
8.4.1 Using Generic Parameters to Reduce Coupling
8.4.2 Coupling Due to Pragmas
8.4.3 Part Families
8.4.4 Conditional Compilation
8.4.5 Table-Driven Programming
understanding and clarity