Next: Creating an Object-Oriented Software System---The AIPS++ Experience
Previous: Controlling Foreign Tasks with the IRAF cl
Table of Contents --- Search --- PS reprint


Astronomical Data Analysis Software and Systems V
ASP Conference Series, Vol. 101, 1996
George H. Jacoby and Jeannette Barnes, eds.

Subject-Oriented Programming

James M. Coggins

Department of Computer Science, University of North Carolina At Chapel Hill

Abstract:

Object-Oriented Programming is enabled by advances in compiler technology and programming language design supporting encapsulation and inheritance. This technical adjustment has had a surprisingly broad impact on strategies for design and development of software. This paper explains what Object-Oriented Programming is, why it has attracted so much interest, and then critically examines its impact. The conclusion is that the optimal use of OOP occurs when application clients are empowered to contribute to the inspection, testing and development of the software they need, in a strategy I call Subject-Oriented Programming. The paper concludes by examining what the next important advance in software technology is likely to be.

1. Introduction

Object-Oriented Programming (OOP) refers to a set of conventions for organizing medium-to-large scale software systems that are enabled by certain technical innovations in programming languages. This paper will review the development of OOP, introduce the key concepts of encapsulation and inheritance, and discuss the potential strategic value and limitations of OOP. The paper concludes by considering what the next big advance in software technology is likely to be.

2. What is Object-Oriented Programming?

Object-Oriented Programming has been described as being ``in the 1980's what `structured programming' was in the 1970's'' (Rentsch 1982). Everybody believes in it, products claim to support or use it, everybody claims to practice it (though they practice it differently) and nobody knows exactly what it is. Advertising hype and overclaiming by enthusiasts tend to make ``object-oriented'' little more than a high-tech synonym for ``good''.

Object-oriented programming is a code packaging convention that imposes structure on medium-to-large software systems using the notions of encapsulation and inheritance. This convention provides several useful software structuring innovations. First, it provides a useful definition of module that is supported by syntactic structures in the programming language and checked by the compiler. Second, it establishes an organizing principle for project decomposition (minimizing communication and dependencies among modules). Third, it enforces a useful formal separation, supported by the programming language syntax, between architecture, implementation, and realization (Brooks 1995). All three of these innovations were described in classic papers by Parnas (1972, 1976) that enunciated the intellectual foundation for what became OOP.

It is possible, in principle, to adopt OOP for systems written in languages that do not directly support object-oriented constructs. Experience reported at this meeting indicates that object-oriented organizational concepts are proving useful in projects being developed in FORTRAN. It is easy to adopt the encapsulation techniques of object-oriented design when writing software in any language. Inheritance is much more difficult to implement in non-object-oriented languages. As with structured programming, however, there are great advantages in having a language embody and enforce the conventions. C++ supports object-oriented programming in the familiar notation and environment of C (Stroustrup 1991).

OOP is following the pattern of structured programming: at first a topic for debate among programming language researchers, it became a topic of study in graduate school, then migrated into upper-division undergraduate courses, and finally into introductory courses. Now, many computer science students do not know what structured programming is because it has been fully integrated into how they learned programming. Gotos are not misused because they are never taught. OOP is now beginning to be used in introductory programming courses at many universities. OOP is on its way to becoming, during this decade, the way we naturally program and teach programming.

2.1. The Evolution of Object-Oriented Programming

OOP is the latest of a long series of technological developments in programming language and translator technology that have led to improved programming methodologies [cf. Stroustrup 1987]. Each new methodology was in its day a great conceptual breakthrough. The hype accompanying OOP also has a long tradition, but the accessibility of object-oriented languages and techniques to the massive personal computer market has intensified the hype about OOP. This section reviews this history to show that object-oriented design, far from being a conceptual breakthrough, is actually a normal evolutionary development of programming methodology.

Technological developments in programming languages lead to new styles of expression that we call programming methodologies. The development of assemblers made possible symbolic naming, especially symbolic addressing, which led to relocatable code. The source code of a relocatable program defines a whole family of programs that differ according to their relocation constants.

Procedural programming was enabled by the development of closed subroutines. The ability to isolate name spaces and to explicitly indicate information transfers through argument lists and common block declarations permits a partial separation of concerns between implementors and users. Scoping was an intellectually deep and technically intricate development in compiler technology that initiated the notion of multiple name spaces.

The convention of data hiding, supported by the technical innovation of compiled libraries and link editors, allows a partial separation of concerns between architects and implementors but provides limited flexibility for users.

Data abstraction extends the data hiding concept by providing support in the programming language for user-defined data types. With data abstraction, the organizing principle for developing large systems is encapsulation: a complex collection of data is defined as a single user-defined type with a single name. The abstract data type and the procedures that operate on it becomes the operational definition of a module.

Structured programming, a statement-level code organizing discipline, and the associated stepwise refinement design method were brought to general attention at about the same time as was data abstraction. All of these ideas were introduced and implemented in the design (and marketing) of the programming language Pascal.

The term ``object-oriented programming'' is often used as a synonym for data abstraction, but the term properly refers to the use of class hierarchies and inheritance to make explicit commonalities among abstract data types. Classes encapsulate data and the procedures that operate on the data together, providing a higher degree of abstraction for system management and integration, but this is an enhanced aspect of data abstraction, not the defining property of object-oriented programming.

2.2. Encapsulation

When using OOP, logically related data and operations are packaged together (encapsulated) in a class. It is often useful to think of a class as a user-defined data structure combined with the procedures that will operate on that data structure. (Other metaphors, such as process encapsulations (enzymes), device encapsulations, or interface encapsulations may be more appropriate (Coggins 1992).)

The external documentation for a class need only to describe the publicly accessible procedures; the encapsulated structure is not relevant to users of the class. This contrasts with many C libraries in which complicated data structure definitions involving unions and structs must be created and manipulated to use the library. Hiding these irrelevancies minimizes dependencies in the user's code on internal structures of classes, simplifies the nature and content of class documentation, and permits changes in the implementations of classes without requiring changes to the user code.

An instance of a class is called an object. The variables defined in an object represent the state of that object independent of other objects of the same class and permit different objects to display different behaviors. The class definition specifies both the memory structure and the set of allowed operations for objects of the class.

The operations (methods, member functions) defined for a class are invoked on an object by sending a message to the object (or ``invoking a member function of the class''). The message names what is to be done; how the operation is to be performed is reserved to the implementor and isolated in the class implementation.

Classes and types are declarations that are instantiated as objects and variables. However, the object-oriented programming constructs are more than a renaming of familiar ideas: Classes organize data and code jointly.

Encapsulation is familiar to most programmers who have worked with C or Pascal. The additional aspects of encapsulation provided by object-oriented languages are usually easy to assimilate and use in one's own practice almost immediately. Inheritance, on the other hand, is much more subtle and more difficult to learn to use well.

2.3. Inheritance

Object-oriented design permits class definitions to be hierarchically organized, leading to a powerful and subtle programming technique called inheritance. With inheritance, the data and member functions can be inherited by classes derived from the base class. (In object-oriented programming literature, the terms base class and derived class are synonyms of superclass and subclass, respectively.)

Inheritance allows code and data structure definitions to be shared among classes with similar structure. This sharing can be motivated by top-down or bottom-up considerations. In top-down inheritance, the base class defines an ideal or minimal version of a class; derived classes provide elaboration or specialization of the base class. The subclass definitions need to specify only those aspects of the subclasses that differ from those of the base class. Member functions defined in the base class may be redefined in the derived class to handle peculiarities of the derived class.

Alternatively, inheritance can be motivated by bottom-up concerns. Commonalities from a number of different, separately-defined classes are factored out from them to form a base class. The base class may be of little interest to users but may provide conceptual and coding simplifications for the library implementor. The components of the original classes that do not factor out to the base class become the variations implemented in the derived classes by redefinition of base class member functions or additions of data structures or member functions.

Sometimes a class is defined simply to hold structures common to several subclasses; no objects of this base class will ever be defined. Instantiation of this base class can be explicitly forbidden; such a class is called an abstract base class.

Sometimes a base class needs to be able to accept messages that must be interpreted in different ways by its subclasses. For example, if the subclasses display themselves in different ways, then different display functions will be required for each subclass. In order for the base class to receive the messages at all, the messages must be declared in the base class. However, the base class' display procedure must be overridden in different ways by each subclass. The virtual function mechanism allows the base class to receive a message for which the interpretation must be supplied by a subclass. With virtual functions, an object may be known to be some kind of image but whether it is actually a FITS image or a GIF image might be unknown at compile time. If appropriate virtual functions are defined in the image class, the selection of the appropriate code to execute will be determined at run time based on the real (sub) class of the object that is receiving the message. Thus, programs can be written using a pointer to an image object without knowing whether the actual object will be a FITS image or a GIF image.

3. A Critique of Object-Oriented Programming and Design

Software development is a difficult intellectual and social activity, but coding is not where the real challenge of software development lies. The hard problems are the larger questions like, ``What software does the client need?'' ``How does what the client needs differ from what the client wants?'' ``What functions must the software support?'' ``How should the software interact with its intended social, political, and regulatory environment?'' ``How should the software be organized into modules?'' ``What user interface is best for the intended users?'' ``What are the key concepts that should be implemented as a software library?'' These questions are not answerable in software: they require a combination of human, systemic, and technical reasoning, negotiation and debate, measurement and evaluation. The people capable of developing useful answers to these questions require broad technical backgrounds, analytical minds, human insight, and often political acumen.

3.1. Does Object-Oriented Programming Address These Essential Questions of Software Development? No.

OOP is a coding discipline: a collection of mechanisms, rules, and pragmas governing the structure of small-to-medium sized bodies of code. If coding were the most significant problem in software development, then OOP might have a chance to provide large productivity enhancements. Unfortunately, the larger, essential questions above are not coding issues. However, side effects of OOP reach many parts of the software development process, making the impact of OOP greater than might have been expected of a technical programming language enhancement.

By teaching programmers good software design strategies and practices (explicit public interfaces, constructors and destructors, decoupling and cohesion), by performing more comprehensive consistency checks on implementations earlier in the development process, by providing an easy-to-use, reliable mechanism for implementing dynamic binding (a consequence of inheritance), and by rewarding effective designs with easier development and maintenance and (especially in C++) low performance costs (Coggins 1993), OOP has the side effect of improving the average sophistication and quality of code produced by a typical programmer, thereby enhancing the net productivity of the typical programmer. This is an important effect, but every enhancement in programming language technology has correctly made the same claims. The claims of OOP are no more earthshaking or life-changing than the claims of its predecessors.

The pattern of these programming language advances is to enable programmers to work with code bodies that represent application concepts at higher levels of abstraction. Abstraction is often a buzzword among the programming language intelligentsia. Let me be specific: a programming language provides superior support for abstraction if it enables a single name to refer to a larger, more complex body of code (Zimmer 1985). In assembly languages, a name could refer only to one memory location. With the enhancements through the years, a name could refer to a sequence of instructions, any variable passed as a parameter, a collection of data structures, and now with OOP, a name can refer to a complex data structure and the procedures that manipulate it.

Naming is a powerful tool. Classes enable a programmer to encapsulate under a single name the structure and behavior of whole concepts---protocols, algorithms, processes, and ordinary things. With inheritance, a programmer can engage the representations of several concepts and customize their union to express a new concept. The potential to write object-oriented code was present in C, but the mechanisms required to implement OOP, especially inheritance, were difficult and messy to use.

3.2. Is Object-Oriented Programming a Revolutionary Advance in the Way Software is Developed? No.

OOP does not by itself make the coding task easier: significant simplification of the coding task requires environment and library support. OOP does not add anything that could not and did not exist before OOP appeared. A programmer so inclined could have implemented these structuring techniques in older languages, and in fact, some did.

The word ``paradigm'' is frequently used in conjunction with OOP to evoke the spirit of Thomas Kuhn's landmark The Structure of Scientific Revolutions (1970). OOP fails to meet Kuhn's criteria defining a ``paradigm shift''. OOP arose as ``normal science''---as a natural extension to concepts that had existed before. OOP is good; OOP is an important enhancement to programming methodology, but it is not really new, it is certainly not a new paradigm, and it is not revolutionary.

The object-oriented language Smalltalk (Goldberg & Robson 1983) provides a revolutionary combination of a graphical user interface and a powerful and flexible interpretive programming environment. These innovations are often mistakenly associated with OOP, and the reputation of OOP is often enhanced by the association.

OOP also benefits from miscellaneous programming language enhancements implemented in object-oriented languages. C++ benefits from important miscellaneous enhancements not really related to OOP: strong typing; function overloading; placing declarations anywhere; C++-style comments; reference arguments to procedures and reference return values; const declarations; simpler, cleaner storage management using new and delete operators; and inline specifications. These enhancements make C++ a better language than C independent of the OOP enhancements, but the benefits of these enhancements are often not distinguished from the benefits of OOP.

Fred Brooks' (1995) metaphor of the ``silver bullet'' is often invoked to describe the benefits of OOP. Brooks says there does not appear to be a silver bullet to kill the software productivity monster, and there probably cannot be one because of the inherent difficulty of the essential questions of software design. Brooks holds some hope for significant, order-of-magnitude effects from OOP, but not much (he is often misquoted on this point).

The incidental problems (Brooks' ``accidents'') of software development are substantial, but they still do not address the essential difficulty of software development. However, the new tools are so exciting that it is easy to lose perspective (ProgramNow 1992).

3.3. Can Object-Oriented Programming Have a Long-term Strategic Impact on Software Development? Yes.

Any technology that can raise the average sophistication and quality of code produced by a typical programmer offers massive potential benefits to the software industry. OOP and related techniques provide a number of potential short-term benefits for software development, but this kind of benefit has been realized before with every programming language enhancement. OOP has no hope of providing order-of-magnitude enhancements in the total software process by itself. There may be some hope of significant long-term improvements, however, if the technical enhancements of OOP are combined with management and design methods that address long-term strategic issues within a software organization.

Managers and programmers together must establish realistic expectations for OOP. While learning C++ or any other OO language does not involve any revolutionary change, there are new concepts and features to learn and new mechanisms to master. C++ trainers generally agree on the time frame for introducing C++ to a programming shop. In a week, programmers can use C++ as a better C. In 2--3 weeks, programmers can effectively use classes without inheritance. In a month, programmers can master inheritance enough to use it in some small examples. Then, programmers need about 6 months for practice and advanced study of class design and the effective uses and pitfalls of inheritance and other advanced features. After this period of study, programmers are ready to develop C++ libraries of their own. Attempts to develop large C++ applications without this period of study and experimentation have resulted in some widely known failures. The best programming organizations will reform management strategies along with adopting OOP at the technical level. Management reform is needed in the following areas: measuring productivity (counting lines of code is meaningless in well-formed object-oriented systems); monitoring assignments of tasks or modules to people; procedures for review and assessment of module and subsystem interfaces; planning for earlier, longer design phases and many fewer, much shorter, smaller meetings once coding begins; and planning for the crucial capital investment in class libraries.

OOP will not make developing your first project faster, nor your second. But with a good strategic core class library, later applications within the same family will be developed quicker and more reliably. When fully adopted, OOP helps managers by focusing attention on crucial design issues, avoiding distraction by trivialities, defining effective modules, and defining and managing clean software and user interfaces.

Class libraries are the culture medium in which applications grow. This could have been said of traditional procedure libraries, also, but it is easier to use class libraries in more diverse circumstances than traditional procedure libraries. Because class libraries can be extended and modified through inheritance rather than by rewriting, it is now feasible for a software shop to develop a core class library to support the family of applications it intends to develop. This core library is a capital investment in future products of the organization. Like all capital investments, such a core library must be focused on the objectives and future plans of the organization. Its structure is, in effect, a statement of what the organization is about. Effort must be devoted toward maintaining and upgrading this core library with the costs amortized over future products to be constructed using the library. Clearly, management must modify some software accounting procedures and reward policies for the core library to remain the vital heart of the organization's software effort.

The core class library is the key to optimally leveraging OOP. The core library is the heart of the proprietary software infrastructure of the organization. Such a library defines the organization's internal development strategy, its market focus, its in-house capabilities, its approach to its work, its view of the field, and the state of its art. The core library is a central strategic corporate asset, along with the vision of top management and the talent of the programming staff. Only by building from the capabilities of a central, core class library embodying the vision and approach of the organization will OOP be able to produce anything near the order-of-magnitude benefits and gigantic quality improvements for which its most ardent supporters hope. Without this strategic approach, OOP provides only a minor technical improvement over familiar procedure libraries and little improvement in overall software quality.

The long-term, strategic impact of OOP will be realized only when the focus of class library development is raised to the strategic software objectives of an organization.

3.4. What are the Main Weaknesses of Object-Oriented Design and Programming?

There are three main weaknesses to the current formulation of object-oriented design and programming.

First, OOP tends to encourage bottom-up design. That is, programmers are tempted to define classes in libraries based on what is convenient to implement rather than based on the capabilities that are needed to advance their or their employers' real objectives. Without direction from customers and their needs, class libraries tend to become bloated lists of capabilities hardly more useful than the massive procedure libraries they made obsolete. Keeping libraries small and focused is the best way to ensure the relevance of the library. Keeping the focus of class development client-driven rather than capability driven is the best way to avoid cumbersome behemoth classes and massive, ineffective libraries.

Second, OOP tends to encourage toolkits of tiny classes (Coggins 1992). Short-sighted library designers aim to develop a set of tiny tools from which supposedly large applications are constructed. Such libraries tend to become populated with many small encapsulation which provide small benefit to their clients. Such toolkits are a pipe dream that won't go away. The vision of implementing a megalibrary containing every imaginable data structure attracts many naive programmers.

Third, OOP provides no good answer to the problems of asynchronous I/O or concurrent processing, as occurs in user interfaces. User interface libraries that present a monolithic inheritance hierarchy are almost universally acknowledged failures. User interface libraries based on X or Motif are simply too massive for any specific community of programmers. The author's research library, IGLOO, presents a new model of a small, focused user interface library with limited but carefully selected flexibility that meets the needs of a specific user community.

The way to fully realize the potential of OOP is to aim toward high-level classes of fairly large granularity that address substantial needs of identifiable clients. This development strategy has a crucial side effect that is in fact the most important potential benefit of OOP: when classes are written in this way, they are at a high enough level of abstraction that clients can contribute to the design, inspection, and testing of their software. By enlisting this whole new, well-motivated labor force, OOP might yet lead to a resolution of the continuing ``software crisis''. This collaborative approach to software design is the strategy I call ``Subject-Oriented Programming''.

4. After Object-Oriented Programming

A real computing revolution is happening now, one that does involve a paradigm shift in Kuhn's sense---one that involves new ideas, whole new systems of thought, a break with past norms and issues---but the revolution involves distributed systems and bit-mapped graphics displays and the enabling technology of faster, smaller computer chips. OOP is riding the coattails of this real revolution.

How can we tell that bit-mapped graphics and distributed systems are real revolutions? Because there are things we can do, study, and use now that did not exist before. There are job descriptions, vocabularies, problems, departments, and budget codes specific to these revolutionary technologies that not only are truly new, but that could not have been filled by people trained under the old ways of doing things. Compared to these true revolutions, OOP is a minor technical correction.

Bit-mapped graphics and distributed computing together allow an individual to work on many computers at once, in diverse locations, and to view text and graphics from all of those locations at once. Bit-mapped graphics made possible new user interfaces that have made computers accessible to many more people; this diffusion of computing technology is a societal revolution, not just a revolution in computing. Collaboration technology is just beginning to unlock the possibilities of the combination of bit-mapped graphics and distributed computing and is the software subfield riding the shock wave of this hardware-enabled revolution.

OOP has appropriately benefited from the real revolution. The software for controlling bit-mapped graphics and distributed computing is complex, but most of it maps nicely into classes. (Asynchronous real-time events are still something of a problem, but not an intractable one.) Class libraries of various kinds for controlling networks, distributed systems, and bit-mapped graphics have been developed experimentally and will eventually make the breakthrough technologies usable by non-expert programmers.

New advances such as Java, a programming language based on C++ but that is built with an understanding of the World Wide Web, is opening a new frontier of distributed computation that is of truly revolutionary importance. The astronomy community has experienced the power of the Web, but when the distributed computing concepts are integrated into the field's basic software models, tremendous advantages in portability, access, and parallelism will be forthcoming.

References:

Brooks, F. P. 1987, ``No Silver Bullet: Essence and Accidents in Software Engineering,'' IEEE Computer, 20(4), April 1987

Brooks, F. P. 1995, The Mythical Man-Month: Essays in Software Engineering, Twentieth Anniversary Edition, (Addison-Wesley: Reading, MA)

Coggins, J. M. 1992, Designing C++ Libraries, The C++ Journal, 1(1) 25

Coggins, J. M. 1993, ``Speed of C++: Myths, Data, and Skepticism,'' The C++ Report, 5(1), January 1993, 25

Goldberg, A. & D. Robson 1983, Smalltalk-80: The Language and its Implementation, (Addison-Wesley, Reading, MA)

Kuhn, T. S. 1970, The Structure of Scientific Revolutions, Second Edition, Enlarged, (University of Chicago Press)

Parnas, D. L. 1972, ``On the Criteria to be Used in Decomposing Systems into Modules,'' Communications of the ACM, 15(12), Dec 1972, 1053

Parnas, D. L. 1976, ``On the design and development of program families,'' IEEE Transactions on Software Engineering, 2(1), March 1976, 1

ProgramNow 1992, Towering over the Landscape, interview with Bertrand Meyer, ProgramNow, Intra Press, Intra House, London, March 1992, 48

Rentsch, T. 1982, ``Object-Oriented Programming,'' SIGPLAN Notices, 17(9), September 1982, 51

Stroustrup, B. 1987, ``What is Object-Oriented Programming?,'' Proceedings of the First European Conference on Object-Oriented Programming (ECOOP), Paris

Stroustrup, B. 1991, The C++ Programming Language, Second Edition, (Addison-Wesley: Reading, MA)

Zimmer, J. A. 1985, Abstraction for Programmers, (McGraw-Hill: New York)


Next: Creating an Object-Oriented Software System---The AIPS++ Experience
Previous: Controlling Foreign Tasks with the IRAF cl
Table of Contents --- Search --- PS reprint
Wed Jul 3 07:32:56 MST 1996