Lecture
In earlier generations of programming languages, a development team needed only a minimal set of tools: an editor, a compiler, a linker, and a loader - that was all that was usually required (and, most often, all that was available). A particularly fortunate team might acquire a code debugger. Complex problems have radically changed this picture: trying to build a large software system with a minimal set of tools is equivalent to attempting to erect a multistory building by hand.
The object-oriented approach has also changed a great deal. Traditional development tools focus solely on the program text, but object-oriented analysis and design bring key abstractions and mechanisms to the fore, and we need tools that work with richer semantics. In addition, to accelerate object-oriented development driven by the macro process, we need tools that can speed up the development cycles, especially the edit/compile/execute/debug cycle.
It is important to choose tools that scale well. A tool that is convenient for a lone programmer writing a small application is not always suitable for producing complex systems. In fact, every tool has a threshold beyond which its capabilities are exceeded: its virtues are outweighed by its clumsiness and sluggishness.
Kinds of Tools
We distinguish at least seven different kinds of tools for object-oriented development. The first tool is a system with a graphical interface that supports the object-oriented notation presented in Chapter 5. Such a tool can be used during analysis, to capture the semantics of scenarios; in the early stages of development, to convey the strategic and tactical decisions made during design; and to coordinate the actions of the designers. A tool of this kind will be useful throughout the entire life cycle and during the maintenance of the system. In particular, we believe it is possible to recover many important aspects of an object-oriented system from the program text. This capability of a tool system is very important: with traditional CASE tools, a developer may create wonderful pictures only to discover that they are out of date, because the programmers manipulate an implementation that is not reflected in the design. Recovering the design from the code reduces the likelihood that the documentation will fall out of step with the implementation.
The next tool that is important for object-oriented development is a browser, which shows the class structure and the module architecture of the system. A class hierarchy can become so complex that it is difficult even to locate all the abstractions that were introduced during design, or to identify candidates for reuse [16]. While studying a fragment of a program, a developer may need to look at the class definition of some object. Having found that class, he will probably have to look into the description of one of its superclasses. While examining that superclass, the developer may want to make changes to the class interface, but in that case he will have to study the behavior of all its clients. This analysis becomes especially cumbersome if it is applied to files, which represent the physical rather than the logical aspects of the design. For this reason a browser turns out to be a very important tool of object-oriented analysis and design. Browsers exist, for example, in the Smalltalk environment. Similar facilities, though of varying quality, are also available for other object-oriented languages.
Another kind of tool that is very important, if not absolutely essential, is an incremental compiler. The method of evolutionary development that is applied in object-oriented programming requires a compiler that can compile individual declarations and statements. Meyrowitz observes that "UNIX, with its orientation toward batch compilation of large program files into libraries that are then linked with other fragments of code, does not provide the necessary support for object-oriented programming. It is utterly unacceptable to spend ten minutes on compiling and linking in order to change the implementation of a method, and to spend a whole hour on compiling and linking merely to add a new field to a top-level superclass! For rapid debugging, methods and field definitions must be compiled incrementally" [17]. Such compilers exist for many of the languages described in the appendix. Unfortunately, most implementations contain traditional batch-oriented compilers.
We also believe that nontrivial projects need debuggers that can work with the semantics of classes and objects. When debugging programs one often needs information about the instance variables and class variables for a given object. Traditional debuggers for non-object languages know nothing about classes and objects. Thus, in trying to use a standard C debugger for a C++ program, a developer will be unable to obtain all the information needed to debug an object-oriented program. The situation is especially critical for object-oriented languages that support several threads of control. During the execution of such a program, several active processes may be running at one and the same moment. Naturally, a debugger is required that would allow one to monitor each individual thread and the interaction of objects across threads.
In the category of debugging facilities we also include such tools as stress testers, which exercise programs under critical conditions of limited resources, and memory analysis tools, which detect violations of memory access (writing into forbidden areas of memory, reading from uninitialized areas, reading or writing beyond the bounds of an array).
Large projects require configuration management and version control tools. As mentioned earlier, the best units for configuration management are class categories and subsystems.
Another tool that we consider important for object-oriented development is a class librarian. Many of the languages mentioned in this book come with standard libraries, or libraries for them can be purchased separately. As a project develops, the class library grows, augmented by new domain-specific software components suitable for reuse. The library quickly grows to such a size that developers cannot find the class they need. One of the reasons for the library's rapid growth is that a class may have several implementations with different time and space semantics. If the expected cost (usually exaggerated) of locating a component is higher than the expected cost (usually understated) of creating that component anew, all the point of reuse is lost. For this reason it can be important to have at least some minimal library tool that would allow a developer to search for classes and modules satisfying various criteria, and to enter useful classes and modules into the library as they are developed.
One more type of tool that we consider useful for certain systems is a graphical user interface generator. For systems in which the volume of interaction with the user is large, it is better to have a special tool for creating dialogs and windows interactively than to program everything from scratch. The code generated by such a system can then be linked with the rest of the object-oriented system and, if necessary, adjusted by hand.
Organizational Implications
The need for powerful tools leads to the appearance of two special positions on the staff of an organization engaged in software system development: the reuse engineer and the toolsmith. Among other things, the duties of the former consist of maintaining the project's class library. Without active effort it can become a boundless wasteland of classes turned to junk, into which not one of the developers will want to look. It often happens that developers must be encouraged to borrow existing components, or prevented from reinventing the wheel; this too is part of the reuse engineer's task. The duties of the toolsmith include creating new domain-specific tools and reworking existing tools for current needs. For example, an entire system of tests may be required to check certain aspects of the user interface, or a more specialized class browser. The toolsmith eases his own work by designing and developing tools using components already placed in the class library. They can be put to use in new developments as well.
A manager with limited means may complain that good tools, reuse engineers, and toolsmiths are an unaffordable luxury. For some projects - yes. However, all of this often gets done one way or another, but in an unplanned, ineffective manner. We advocate spending explicitly on tools and personnel, in order to make this activity more focused and effective and to increase the value of the organization as a whole.
Comments