Most compilers for OO languages on personal computers are now supplied with "class libraries". In addition to those provided with compilers, there are many other class libraries that are either available from commercial suppliers or which exist as public domain code (usually accessible from archive sites on the Internet). Most of the public domain class libraries are for C++ on Unix, with a few for C++ on IBM-PC operating systems.
Some of these class libraries are simply collections of supposedly useful components. The classes in these libraries will typically define "abstract" (programmer defined) data types. Instances of these classes that can be used to manage particular resources. For example, a library might provide a class that represents a kind of "sparse array manager". An instance of this class could be created, in a client program, to provide an initially empty array to which elements could be added, accessed, modified, or removed without the client programmer having any need to be concerned with storage management issues or the coding of efficient access methods. As another example, a library class might simply provide a "wrapper" around some system data, for example the data defining the time and date. The library class would provide several alternative ways of accessing the time data (e.g. as a string, as millisecond count, or whatever).
The majority of classes in such a library will be "concrete" (i.e. directly instantiatable) with minimal or no provision for further extension or specialization. As well as libraries providing standard utilities (e.g. a "date" class), and data structures (e.g. a "sparse array" class), there are similar but more specialized class libraries. For example, a library might contain a set of classes that facilitate the use of "sockets" in a distributed Unix environment.
Although such class libraries are useful, they do not make a dramatic impact on program development. (The last time that creating a linked-list was a significant part of your work was probably back in first year university when you were writing your first programs in Pascal.) While it may take you only an hour or so to write your own "class date" and "class LinkedList", it is often better to use the classes from a library. The library classes will have been thoroughly tested and shown to perform correctly whereas it is quite likely that a hurriedly implemented version will contain errors in the handling of less common cases.
Libraries with classes that are designed to be extended or specialized by client programmers do have a more significant impact on the costs of developing new applications. The classes in these libraries will for the most part be "partially implemented abstract classes". Each class will define some concept (abstract type) and specify its behaviours. Default implementations of many of the behaviours may be provided, while the implementation of others will be "deferred" (i.e. left as "pure virtual functions" in C++). In some cases, the designer would have been able to define sensible default implementations for all the behaviours of a class. Any such class will be instantiatable, but will usually have provision for further specialization by subclassing. The designer of each library class will have given careful consideration to the needs of programmers who must implement derived classes. So, protected access functions would typically be provided for most (maybe for all) private data members (or the data members might be given protected access status). The majority of the member functions would be declared as being virtual; and, of course, the library classes would all have virtual destructors.
Such libraries are most commonly encountered as "GUI libraries" (Graphics User Interface libraries). These libraries are inherently platform specific (though some commercial suppliers can provide equivalent libraries for popular platforms such as Unix/X-Windows and IBM-PC). The classes define the various types of visual element from which an interface can be constructed. Thus, there might be a set of classes that help handle scrollable views that are too large to be displayed in their entirety. Such a set would include classes that can be instantiated to provide various forms of scroll-bar that control movement, and a "scroller" class that maintains a coordinate frame and interacts with the scroll-bars. A programmer employing such a class library would probably be able to use the scroll-bar class unchanged. The scroller class might be abstract, with some member functions left as pure virtual functions. The programmer creating a new application would then create a specialized subclass of class Scroller, providing definitions for all pure abstract functions as well as adding new functionality and, possibly, replacing some inherited virtual functions.
Class libraries like these GUI libraries can significantly enhance programmer productivity. The ways in which instances of different classes interact will all have been sorted out, thus saving the application programmer from having to do a lot of design work. Typically, there are default implementations for the vast majority of the member functions of the various classes. Consequently, instead of having to code up an entire interface, the application programmer need only implement those functions that are inherently application-specific (the pure virtual ones) along with any others whose default implementations are considered to be unsatisfactory. Furthermore, the use of standard classes enhances consistency among different products because applications built using the same GUI classes will tend to have the same "look and feel".
Code reuse can be maximized through the exploitation of "framework class libraries". A framework can be viewed as providing a skeleton application that can be extended and specialized through class inheritance. This skeleton will be constructed using instances from a large set of classes. These classes will involve many collaborations; they are much more strongly interrelated than the relatively simple classes in a basic GUI library. Typically, a program built using a framework will involve an "application" object that works with "document" objects that interact with "views". The collaborations among instances of these classes are often complex. For example, the application might detect that a window was moved and determine that it has to request a view to update itself; the view would find that it needs to communicate with the document to get data drawn; the document must then obtain, from the view, details of the display area so that it can identify the particular data that are visible and must be redrawn.
The "application", "document" and "view" classes in a framework library will be partially implemented abstract classes. While many of the behaviours of these classes, and patterns of interactions among instances of these classes, can be identified, actual details of implementation of some behaviours have to be deferred and left for definition in derived subclasses. It is not uncommon for these classes to have one hundred or more different member functions; most of which will have default implementations.
MacApp-1.0 (circa 1986) was one of the earliest of these frameworks. It was created to facilitate the implementation of programs (applications) for Macintosh computers. It had been noted that, excluding games and other special programs, all the early Macintosh programs could be conceived as involving: i, an "application" that handled interaction with users and managed "documents", ii, one, or more, documents that managed the run-time data structures representing the information manipulated by the user, and that organized data transfers to and from disk files, iii, views of the data, and iv, application specific data structures (e.g. "paragraphs" in a word-processor, "records" in a database, or graphics elements in a MacDraw-like graphics editor). The first three of these four parts were essentially the same irrespective of the application. Inevitably, very similar code was being reimplemented in each new program.
It was realized that if suitable abstractions could be found, much of the standard code could be provided in a library (with the proposed standard Macintosh look and feel actually implemented correctly for once). For example, every Macintosh application had had to include an "event-loop" that received mouse-down, key-stroke, update, and other "events" from the underlying operating system and which distributed these to other components in the code for handling. This standard code could be provided as a "Run()" method for an "application" class. This Run() method would sort out the events, passing updates to appropriate "view" objects, resolving mouse-downs into menu requests (that might be handled by "views", or "documents", or by the application object itself) and drawing actions (that would be handled by views). The general behaviour of an "application" object, and its modes of interaction with "views" and "documents" could be almost completely characterized with default implementations provided for all required functions.
The general behaviours of "documents" could also be characterized. Documents handle some menu requests, determine how much disk storage is needed for saved data, and transfer data to files. Of course, it is not always possible to provide a useful default implementation. A "document" must be able to accept a "DoWrite" message - but what it writes is obviously program- specific. A document class could be defined, but many of its methods were, necessarily, deferred. A programmer implementing a new program for the Macintosh would have to create a specialized subclass of "class document" that provided definitions for all these deferred methods.
MacApp has evolved substantially between version 1 and the current version 3 (and its implementation language has switched from Object Pascal to C++). As well as proving a fairly useful development aid for the Macintosh platform, MacApp served as a model for many other framework libraries.
ET++ is a public domain class library for C++/Unix environments. Its initial structure was based on MacApp-2 (with C++ substituted for Object Pascal) but it has evolved into a functionally-richer and generally more sophisticated system. (Like much public domain software, there are bugs in ET++ and it will occasionally crash or freeze; but the same can be said of several costly commercial software packages.) Both Borland's OWL class library and Microsoft's Foundation Classes (MFC) are based in part on MacApp concepts as reimplemented for IBM-PC with the Windows operating system. These libraries, particularly Borland's, are now generally more advanced than MacApp in the use that they make of C++.
When applications are created using these frameworks, the programming style is very much one of "programming by difference". A "chemistry editor application" is just like a standard application except that it creates "chemistry-documents" rather than plain "documents". So, the programmer changes the DoMakeDocument() method in a ChemApplication class derived from the standard Application class. A "chemistry-document" is just like a standard document, save that it has some data structure representing a molecule, its DoRead() and DoWrite() methods actually involve data transfers, and it creates views of its data rather than blank views. So, the programmer creates a new ChemDocument class derived from the library class Document, adds some data fields and data manipulation methods, and provides implementations for deferred functions like DoRead(). The amount of code that must be written for the new application is significantly reduced. (Most of these class libraries seem to come with an example of a quite sophisticated text-editor. The code for this editor program will comprise less than one hundred lines; everything will be done by creating instances of standard window classes, text-handler classes etc.) A further advantage of using the libraries is that the programmer is able to focus more on, and spend more time on application-specific issues because so much the user interface, i/o, storage-management, and other components are provided by classes from the library.
These frameworks differ in detail. But, they are sufficiently similar in overall structure that basic principles learnt from one framework will be relevant to the others. Of course, mastery of any one framework only comes with months of usage.
Although framework class libraries, and the slightly simpler GUI libraries, can be extremely useful, their size and complexity makes usage difficult for new programmers. Before a programming team can create a new application, the individual programmers must become familiar with the classes in the library and the ways in which they interact.
For example, a programmer might choose to have a pointer to a "view" in the objects that represent data (molecules, paragraphs, pictures or whatever), and therefore would write code that places such links in data objects as they are read in from a file. This would work - provided that the required views existed before the data objects were read from the file (otherwise an invalid pointer value would be recorded in each data object). How could the programmer know whether the code is correct? Somehow, that programmer must first realize that there is a potential problem, and then be able to determine whether "Document::DoMakeViews()" is executed before or after "Document::DoReadData()".
Conventional subroutine libraries can be documented by just listing the arguments and result types of each routine and providing a paragraph of explanation. Similar documentation can be provided for class libraries with a note describing the class as a whole and short paragraphs describing each member function. But such documentation doesn't really help that much because it does not reveal the pattern of dynamic interactions among instances of different classes.
More specialized documentation tools are required. The most common tool is a "class browser". A browser allows the source code of a class library to be examined. While a conventional editor can be used to view code, it presents information in terms of files containing program statements; the presentation from a browser is in terms of the classes. A browser can display hierarchical relations among classes, present class declarations, and show method definitions. In complex class hierarchies, a browser can show where a virtual method is introduced in a hierarchy and where it has been redefined in derived classes. The display of a class can show just the features that it defines, or all its features as obtained through inheritance. The browser will typically be able to find all places where a particular method is invoked. Using a browser, a programmer who has some basic familiarity with the class library can rapidly tease out details of how instances of particular classes might interact and so be able to determine how to extend the interactions when additional processing is desired.
The next four chapters explore some of the class libraries and their support environments. Chapter 7 provides a brief overview of some of the available libraries and includes pictures illustrating features of typical OO development environments. Chapters 8 illustrates simple use of class libraries to create a program that allows some data to be viewed in different ways. Implementations using Borland's OWL library, ET++, Symantec's Think Class Library, and MacApp are available; most of the code fragments shown are from either the MacApp ot ET++ implementations. Chapter 9 reviews a number of the more advanced facilities commonly available in framework class libraries; while Chapter 10 presents the analysis and design for a specialized cut-and-paste graphics editor that can be built using these libraries.