Book Reviews


Plug and Play Programming

reviewed by Tom Nelson


Tom Nelson is an independent programmer and technical writer. His current interests are systems programming for DOS/Windows and OOP designs expressed in C++. He may be reached at 5004 W. Mt. Hope Rd., Lansing, MI 48917. Telephone (517) 322-2072.

It's an open secret in many programming circles that Object-Oriented Programming hasn't delivered on its promise to permit the construction of fully reusable and extensible software modules. Although C++ may come close to these goals at present, it still can't demand unconditional surrender. However, the problem isn't entirely the fault of language shortcomings, as many suppose. Some of the blame can be placed on the way many programmers commonly approach program design. If you're willing to re-learn some of these approaches and perform some additional legwork, many OOP languages in use today provide sufficient tools to build programs from interchangeable and reusable components.

This is the basic philosophy behind Plug and Play Programming by William Wong. This book introduces the concept of software plugs: interfaces that provide a standard way to make well-defined connections between software components or objects. By rigorously outlining these connections as an initial step in your design procedure, you can significantly control the growth of program complexity. Defining a class in C++ lets you specify a public interface for an unrestricted number of clients of any type; software plugs go one better and allow direct control over what type(s) and how many clients the class can have.

With plugs, you can no longer call member functions directly. Instead, all your calling code ever sees of another class object is the plug interface. This restriction provides a complete compilation firewall against any changes you make within an object or component. Well-defined connections between components let you plug in a new component any time with no changes to existing client code.

Content Synopsis

An introductory section in the book explains the basic concept behind software plugs. This section goes into considerable depth in drawing an analogy between plug-based software construction and connecting (plugging) computer hardware components together. Computer hardware is designed so that only components of specific types can be plugged together. For example, you can't plug a keyboard into a parallel port or (even worse) a wall outlet since the plug won't match the socket. Software plugs work the same way in restricting what component types you can connect (plug) together. You can't arbitrarily plug two component objects together until you've built a rigorous, type-specific connection between them. Furthermore, you can't use a component until you've plugged it into a type-compatible socket object using operator<= (representing the male end of a plug).

Chapter 1 provides an overview of conventional program construction and shows how it can result in software that is hard to change and maintain. The chapter reveals a few more details of software plug design and use, and how program construction benefits as a result. Several short code examples show what it's like to define and plug two simple objects together.

Chapter 2 discloses even more features about plugs and their implementation. This chapter discusses the DECLARE_CONNECTION macro, which you use to declare a pair of classes that make a connection (one plug and one socket). DECLARE_CONNECTION is actually the tip of an iceberg that hides a somewhat complex class hierarchy and no small amount of associated code. This hierarchy establishes and maintains the actual connection using a pair of hidden pointers to either side. Your application code thus has no direct access to these pointers or to member functions on the other side of the connection. You must define this plug interface for each connection you make. In many cases the interface will consist of simple relay functions that merely transfer your call to the other side.

The next three chapters cover some actual plug applications. Chapter 3 also introduces the concept of components, which are class objects that contain at least one plug (or socket). You can build specialized components such as adapters, filters, tees, and merges, which are useful in many situations. Chapters 4 and 5 cover plug interfaces to Windows controls using the MFC library. Plugs can go a long way in reducing the complexity of Windows programming.

One of the more intriguing uses of plugs arises when debugging a plug-based application, a topic covered in Chapter 6. The basic idea here is to insert a tee filter between two components in order to monitor function calls across the connection. The filter gathers trace information that you can save on file or display in a window. Application code need never know that you've installed a filter.

Chapter 7 covers components and compound plugs, topics introduced way back in Chapter 3. Compound plugs act something like strip outlet boxes. Chapter 8 looks at dynamic plugs, which are allocated dynamically from the heap. Dynamic plugs also free themselves automatically, which effectively eliminates one source of memory leakage. Other topics presented are a general discussion of component- and plug-based program construction and the modification of existing programs with plugs. Several appendices discuss contents of the plugs.hpp header file, plug-based class libraries, and the implementation of plugs in Smalltalk and Borland Object Pascal. The book includes a disk containing necessary header files and (some) example code.

Commentary

The intended audience for this book, in the author's words, is the C++ programmer "gearing up to tackle a large project." You should not consider this book if you're unfamiliar with C++ and OOP, even though the book contains some initial background information on OOP concepts and an appendix entitled "A C++ Primer." Those who need a primer should keep this book on the shelf for the time being while learning more about C++ from more complete source material; intermediate and more advanced users won't need this background.

The author does a good job of introducing the plug concept early in the book, using analogy. He also takes pains to introduce more advanced topics gradually. The early chapters contain many small "foobar" code examples to illustrate his current points. However, I found it somewhat difficult to relate each of these small examples to the whole.

The first realistic examples appear in chapters 4 and 5, where the author discusses plugs in relation to Windows controls. These examples are fairly complex, especially in relation to the over-simplified examples that preceded them. This sudden jump in complexity may further frustrate your efforts to grasp the whole, if you weren't able to do so earlier. You're out of luck if you've had no exposure to Windows or event-driven programming.

Using plugs also forces several trade-offs that the book fails to discuss. The trade-offs generally involve efficiency vs. reusability. Each plug connection you declare carries with it a fair amount of code when templates are expanded for each class type listed in the DECLARE_CONNECTION macro. The plug and play method also slows functions calls, albeit slightly, since you can only call another object indirectly via a plug connector. There's also a fair amount of work involved in writing the connection interfaces, which may eventually make you pine for the good old days of direct calls. The result, however, is fully reusable and interchangeable software components.

The author claims that plugs are "going to revolutionize object-oriented programming." Possibly, but considering the advertising and editorial content of current programming journals, it's getting off to a rather slow start. I feel the technique as presented is too unwieldy to ever enjoy extensive use, despite undeniable advantages. Perhaps some developers could put it to good use as an in-shop coding standard. Its use as a more comprehensive standard, however, may have to wait until some future programming language emerges (possibly a distant descendant of C++) that includes direct support for the ideas implemented here.

Conclusion

In summary, this book presents a technique well worth exploring, especially for any large development project in C++. In addition to module reusability and other advantages, a major plus is the ability to insert instrumented debugging code across a plug connection with no recompilation of the code under test.

The book appears to be well organized and generally accurate, with coverage of most topics. Despite the method's advantages, however, this book falters in presentation. Although the author plainly makes an effort to explain his points in prose, the rather weak code examples dilute the book's overall impact and understandability. Foobar is fine for the odd code fragment, but when lengthy examples appear with class names like ForwardingFoobarPlug or FooBarTraceClass2, this usage has gotten out of hand.

I would like to have seen the main elements of the plug concept distilled into a fully-worked, real-world example of manageable size in an early chapter. Perhaps even better, the author could have selected one or two actual application projects as examples (such as a database manager or text editor) and developed them throughout to improve the book's unity, while focusing on various aspects of them in light of the topic under discussion.

Title: Plug and Play Programming: An Object-Oriented Construction Kit
Authors: William Wong
Publisher: M&T Books, 1993
Pages: 484
Price: $39.95
ISBN: 1-55851-302-7