Lecture
Benefits
Adherents of object-oriented technology usually name two of its main advantages. First, greater competitiveness, thanks to predictability, reduced development time, and great flexibility of the product. Second, the problems being tackled may be so complex that no alternative solutions remain.
Chapter 2 stated that the use of the object model makes it possible to carry over into a program the five attributes of well-structured complex systems. The object model forms the conceptual framework of the notation and of the process of object-oriented development; thus we obtain these benefits directly from the method as well. Advantages were also noted that follow from the fact that the object model (and hence the development process):
The study of numerous cases from practice supports these conclusions; it is especially often pointed out that the object approach can reduce development time and code size [19, 20, 21].
Risks
In speaking of the dark side of object-oriented technology, two issues must be considered: performance and start-up costs. Compared with procedural languages, object-oriented languages definitely introduce additional overhead for passing a message from one object to another. As was pointed out in Chapter 3, when calling methods that are not found and bound statically at compile time, the running program must dynamically look up the required method by the class of the receiving object. Studies show that, in the worst case, a method call takes 1.75-2.5 times longer than an ordinary procedure call [22, 23]. On the other hand, observations show that when methods are called, dynamic lookup is actually necessary in about 20% of cases. In strongly typed languages the compiler can often determine which calls may be bound statically and generate a procedure call for them instead of a dynamic lookup.
Another cause of reduced performance lies not so much in the nature of object-oriented languages as in the way they are used in the object-oriented development process. As has been said many times, object-oriented technology gives rise to multilayered systems of abstractions. One consequence of this layering is that each method turns out to be very small, since it is built on lower-level methods. Another consequence of layering: sometimes methods serve only to gain access to an object's protected attributes. The result is far too many calls. A method call at the highest level of abstraction usually entails a cascade of other calls; methods at the upper levels call methods at the lower levels, and so on. For applications in which time is a limited resource, too large a number of method calls is unacceptable. Again, on the positive side, such layering aids understanding of the system; some complex systems cannot even be approached unless one begins by designing the layers. We recommend first designing a system with the desired functional properties, and then identifying the bottlenecks. Often they can be "opened up" by declaring the corresponding methods as inline (thereby gaining time), by "cleaning up" the class hierarchy, or by breaking the encapsulation of a class's attributes.
A similar risk of performance loss arises from the large amount of inherited code. A class lying deep in the inheritance structure may have many superclasses; when the program is linked, the descriptions of all of them must be loaded. For small applications this may in practice mean that deep class hierarchies should be avoided, because they require an excessive amount of object code. The problem can be somewhat mitigated by using highly developed compilers and linkers that are able to eliminate useless portions of the program.
One more source of problems for the performance of object-oriented programs is their behavior in a system with paged memory. Most compilers allocate memory in segments, placing each compiled module (usually a file) in one or more segments. This presupposes locality of most references: procedures in one segment mainly call procedures in the same segment. In large object-oriented systems things are not like this. The code of each class is placed in a separate file, and since its methods make intensive use of the methods of other (especially higher-level) classes, their execution involves intensive segment switching. This behavior contradicts what most compilers expect of programs, especially in systems with a pipelined processor and paged memory. This is another example of why the logical and physical aspects of a design must be separated. If a program runs too slowly because of excessively frequent page switching, one can try changing the physical placement of classes within modules. This is a design decision concerning the physical model of the system - it will not affect the logic of the program.
Finally, one further component of risk is the dynamic allocation and destruction of objects. Dynamic allocation of memory from the "heap" entails additional computational costs compared with placing data on the stack and (of course) with static reservation at compile time. In many systems this causes no practical problems, but sometimes the additional overhead is impermissible. Simple solutions exist: give up dynamic creation of objects and allocate them all in advance, or replace the standard memory allocation algorithm with one specially adapted to your needs.
And again on the good side: the positive properties of object-oriented systems often repay all the troubles listed above. For example, Russo and Kaplan report that the performance of a C++ program is often higher than that of its functional equivalent in C. The gain, they believe, is connected with the use of virtual functions, thanks to which one can save on type checking and omit many control constructs. In our experience, the code of an object-oriented program is indeed usually shorter.
For some projects the start-up costs of moving to object-oriented technology may turn out to be insurmountable. As with any change of technology, money will have to be invested in purchasing new development tools. Moreover, if some object-oriented language is being used by the organization for the first time, then there is no domain-specific groundwork for reuse either. In short, one has to start everything over from the beginning, or find some way of using existing programs within an object-oriented environment. Finally, the first attempt at object-oriented development will almost certainly fail if appropriate training has not been carried out. Object orientation is not "just another" programming language that can be learned on a three-day course or from a book. As we have repeatedly pointed out, it takes time to master object-oriented design as a new world view, which must be assimilated by developers and managers alike.
Summary
Comments