With the growing demand for software systems that can cope with the increasingly diverse tasks of information processing, it is tempting for a software company to find ways to reduce the production costs of a new code project. One of the most obvious ways to do this is to increase the degree to which code from other projects can be reused.
With that in mind, two of the more common questions to arise when programmers design a new system are:
- How extensible should the system be?
- How extensible can I make the system?
Reusing code is best done if the original system was designed to be extensible. Otherwise, the difficulties of reusing code can easily negate any productivity gained. But, designing for extensibility adds in all sorts of new considerations to software design.
In this article, I'll discuss some of the ways in which a software system can be made extensible for future projects.
Before going any further, let me clarify that I'm not advocating design for extensibility in all cases, or even in most cases. Many of the design choices that facilitate extensibility will often hinder other considerations, such as performance or testability. The most testable systems are often the simplest ones, but designing for extensibility can often add a great deal of complexity to a system.
Fortunately, there are also times when the most extensible design is also the simplest, but such an alignment of considerations is all too rare.
For this reason, I suggest employing strategies for extensibility only when you are certain that the advantages will outweigh the costs incurred. This usually means that you know the system will be extended in a certain way.
Often, in the extreme programming literature, the addition of extensibility is compared to the purchase of a stock option: you purchase the option early so you can easily extend the system at a later date. If you eventually exercise this option, you can win big-time.
But if you never exercise the option, then you're out the cost of the option with nothing to show for it. So, "Buyer beware!"
Next, let's look at the various ways in which the term extensibility is defined. When discussing the extensibility of a program, there are essentially three different types of extensibility to which we are referring -- black box extensibility and two types of white box extensibility. Figure 1 illustrates the differences in extensibility type.
Black box extensibility refers to the ways in which a program can be extended without directly extending the original code. This is done usually through the use of a configuration language or wizard that leads you through the extension of the system.
One example is a tax program that includes a configuration language for specifying the various tax forms. When the government issues new forms, the system can be extended simply by specifying the structure of the new forms in the configuration language.
Black box extensibility is most applicable to the study of proprietary components and frameworks in which the business model of the original development team requires both that:
- The program is proprietary (not open source)
- External developers have some degree of flexibility in customizing the functionality of the component
Programs that allow for user-defined scripts or macros (such as Emacs, MS Office, and the like) are examples of systems with black box extensibility.
White box extensibility, in contrast, refers to the ways in which a program can be extended by modifying or adding to the source code. I like to distinguish two subcategories of white box extensibility: open box and glass box.
When modification of the original source code is allowed, I call the system open box extensible. Of course, in principle, such a program may be arbitrarily extended, but not all extensions are of equal difficulty.
The study of open box extensibility is concerned primarily with how to facilitate various kinds of extensions, given the ability to change the program when necessary. This is exactly the form of extensibility most relevant to a development team when producing the next version of their own product.
In some cases, this type of extensibility may also be of interest to developers attempting to take advantage of existing open-source software. But extending an open-source system in this way is riddled with problems.
The most glaring problem is what to do when the "official" maintenance team decides to release a new version of the software. Fusing their changes with yours can be difficult and time consuming. Even if the system is modular enough that the actual code you've changed doesn't conflict, it is difficult to be sure that no assumed invariants of the new code are broken by your changes (although this problem can be ameliorated to a large extent if the code is shipped with unit tests).
Glass box extensibility refers to the ways in which a software system can be extended when the source code is available for viewing, but not modifying.
Because of the problems discussed above with altering externally maintained open-source code, it is advisable to use only glass box extensions on such code whenever possible. A great example of a popular, glass box extensible system is JUnit. Every unit test can be viewed as an extension of the original code base.
Figure 1. Each approach depends on how accessible the code is to the extender

These various types of extensibility are each useful in certain contexts, some of which I've mentioned. For example, in the case of proprietary software in which "outside" developers are allowed to extend the program (but without viewing the underlying code), the black box scheme is appropriate.
When the underlying code is open for viewing or modification, one of the white box approaches is appropriate.
Each situation, of course, has its own ramifications for software design. Still, in a given system, more than one form of extensibility may be employed.
In the next installment, I will continue by exploring the issues involved with white box extensibility. In future articles, I will illustrate examples of systems that use more than one type of extensibility.
- The ACM Web site article "Object-Oriented Framework Development" discusses the application of various kinds of reuse in frameworks.
- The JUnit home page provides links to many interesting articles discussing program testing methods, as well as the latest version of JUnit.
- If you have a question about programming extensibility into your Java applications, stop by the multi-topic forum on developerWorks entitled "The Java filter" hosted by seasoned developer Joe Sam Shirah.
- Read all of Eric's Diagnosing Java code articles.
- Find more Java technology resources on the developerWorks Java technology zone.
Eric Allen has a bachelor's degree in computer science and mathematics from Cornell University and is a PhD candidate in the Java programming languages team at Rice University. Before returning to Rice to finish his degree, Eric was the lead Java software developer at Cycorp, Inc. He has also moderated the Java Beginner discussion forum at JavaWorld. His research concerns the development of semantic models and static analysis tools for the Java language, both at the source and bytecode levels. Eric has also helped in the development of Rice's compiler for the NextGen programming language, an extension of the Java language with generic run-time types. Contact Eric at eallen@cs.rice.edu.




