Previous | Table of Contents | Next |
Although object-oriented techniques may be easy to apply in real life, they can be frustratingly difficult to discover in computer programs. In real life the boundaries between objects are obvious and clear-cut. People are different from and interact with each other, balls bounce, birds fly, trees grow. The interfaces between physical objects are sharp and definable. When pondering the interaction between a baseball and the bat that hits it, we do not ask which object has the responsibility for determining that a collision has taken place or which object should control the change of state that occurs when they intersect.
But such decisions are the heart and soul of object-oriented design. In this respect, the process of object-oriented design is closer to the smooth functioning of an organization, such as a committee or club. Here the separation of responsibilities between, for example, the president and the vice-president may not be so clear-cut as the separation of responsibilities between a ball and a bat. Tracing the flow of interactions so that all necessary tasks are performed, all contingencies are predicted, and no one person (or object) is overburdened by too much work can be frustratingly difficult, both in real life and in object-oriented programming.
Much of the recent work in object-oriented design, such as the unified modeling language, as well as work in object-oriented structuring, such as the design patterns movement, can be seen as an attempt to provide guidelines that help determine how to divide responsibilities between many agents.
Alan Kay, considered by many to be the father of object-oriented programming, identified the following characteristics as fundamental to OOP (Kay, 1993):
Having tried to convince the reader that object-oriented programming is a revolutionary idea, totally unlike anything that has come before, I will now endeavor to show that it is really evolutionary, clearly following on the heels of a long tradition of previous abstraction techniques.
From the beginnings of computer science it has been clear that the major difficulty in the development of large systems is not algorithmic, but is, rather, communication. Fred Brooks, in 1975, expressed it this way:
Since software construction is inherently a systems effortan exercise in complex interrelationshipscommunication effort is great, and it quickly dominates the decrease in individual task time brought about by partitioning. Adding more men then lengthens, not shortens, the schedule. (Brooks, 1975)
Over the years, programmers and language designers have developed a number of abstraction techniques to help control the flow of information between various parts of a large software system, as well as between the various members of a software development team. Symbolic assembly languages, for example, enabled the programmer to think about operations by name, rather than by numerical address. High-level languages freed the programmer from tasks such as register allocation and management. Procedures separated the naming of a task to be performed from the steps used in the achievement of the task, and started the long progression of information hiding mechanisms. Procedures by themselves cannot be used to hide information that must be shared between two or more routines. Block-scoped languages, such as Algol, were one attempt to solve this problem; modules were a slightly later and more successful mechanism.
David Parnas (1972), who popularized the notion of modules, described the following two principles for their proper use:
This philosophy is much like the military doctrine of need to know, and should be etched on the inside of the eyelids of every good object-oriented programmer. When objects interact with each other, they should be tied together with the weakest strings possible.
Although modules provided an adequate mechanism for information hiding, they did nothing to deal with the problem of object creation. Imagine a module for manipulating complex numbers, for example, with the limitation that only one location can hold a number. Such a system would hardly be useful. A natural next step, therefore, was the development of the idea of an abstract data type. An abstract structure type (AST) provides the data-hiding benefits of a module and extends it with the ability to stamp out multiple copies of values. In a certain sense, an object is simply an abstract data type. People have said, for example, that Smalltalk programmers write the most structured of all programs because they cannot write anything but definitions of abstract data types. It is true that an object definition is an abstract data type, but the notions of object-oriented programming build on the ideas of abstract data types and add to them important innovations in code sharing and reusability.
Previous | Table of Contents | Next |