References and Footnotes

Subtyping, Subclassing, and Trouble with OOP

 

Liskov Substitution Principle (LSP)

If for each object o1 of type S there is another object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2, then S is a subtype of T.
Barbara Liskov, "Data Abstraction and Hierarchy," SIGPLAN Notices, 23,5 (May 1988)

see also

If type T denotes a set of values that carry their own behavior, and if values of type S can override some of T values behavior, the LSP is undecidable. Indeed, a mechanical application of LSP must at least be able to verify that all methods overridden in S terminate whenever the corresponding methods in T terminate. This is generally impossible.
On the other hand, if T denotes a set of (structured) data values, and S is a subset of these values -- e.g., restricted by range, parity, etc. -- the LSP is trivially satisfied.
   

Subtyping vs. Subclassing

W.R. Cook, W.L.Hill, P.S. Canning, "Inheritance Is Not Subtyping," In: Carl A. Gunter and John C. Mitchell. Theoretical Aspects of Object- Oriented Programming. MIT Press. ISBN 0-262-07155-X.

Sidebar: "Inheritance: Structural or Behavioral Conformity?" In: "Executable Object Modeling with Statecharts," David Harel and Eran Gery, IEEE Computer, Vol. 30, No. 7, July 1997, pp. 31-42.
   

On understanding of types...

Luca Cardelli, P. Wegner, "On Understanding Types, Data Abstraction, and Polymorphism," ACM Comp. Surveys, 17(4):471-522, Dec. 1985

see also
Date, C., Darwen, H, Foundations for Object/Relational Databases, Addison-Wesley, 1998.
   

C++ isn't merely an OO language

However, the bottom line is that these techniques [templates and overloading] allow you to write efficient, type-safe, and generic code. People familiar with functional languages will note that these techniques are similar to techniques pioneered in those languages.
...

However, not every concept naturally and usefully fits into a hierarchy, not every relationship among concepts is hierarchical, and not every problem is best approached with a primary focus on objects. For example, some problems really are primarily algorithmic. Consequently, a general-purpose programming language should support a variety of ways of thinking and a variety of programming styles. This variety results from the diversity of problems to be solved and the many ways of solving them. C++ supports a variety of programming styles and is therefore more appropriately called a multiparadigm, rather than an object-oriented, language (assuming you need a fancy label).

Examples of designs that meet most of the criteria for "goodness" (easy to understand, flexible, efficient) are a recursive descent parser, which is traditional procedural code. Another example is the STL, which is a generic library of containers and algorithms depending crucially on both traditional procedural code and on parametric polymorphism.

I find languages that support just one programming paradigm constraining. They buy their simplicity (whether real or imagined) by putting programmers into an intellectual straitjacket or by pushing complexity from the language into the applications. This is appropriate for special-purpose languages, but not for general-purpose languages.

Bjarne Stroustrup, "The Real Stroustrup Interview", IEEE Computer, vol. 31, No. 6, June 1998, pp. 110-114.
   

Problems with OOP

Another problem with OO languages is their emphasis on inheritance. Implementation inheritance, in which one class borrows code that was written for another class, is a bad idea that makes software harder to manage and reuse. It binds the implementations of classes together so that neither class can be understood without the other. A subclass cannot be understood without knowing how the inherited methods are implemented in its superclass, and a superclass cannot be understood without knowing how its methods are inherited in subclasses. In a complex class hierarchy, no individual class can be understood without understanding all the other classes in the hierarchy. Even worse, a class cannot be separated from its hierarchy for reuse. Multiple inheritance makes these problems even worse. Implementation inheritance causes the same intertwining and brittleness that have been observed when goto statements are overused.
John K. Ousterhout, "Scripting: Higher-Level Programming for the 21st Century", IEEE Computer, March 1998, pp. 23-30.
 
Inheritance means that in order to understand the behaviour of one object, I have to understand the behaviour of all its ancestors first.

Inheritance means that one is never quite sure whether it's appropriate to call a method defined in a superclass, for fear that it won't interact correctly with the intended use of the object. Inheritance means that if I want to change the superclass of an object, I probably can't, as there will be a host of other modules that have come to rely on methods specific to its ancestors. Inheritance means that my program might raise a type-error exception at some unexpected moment.

And most importantly (in my view), inheritance makes for programs that are almost unreadable. What does the following Java class do?

        class MyClass extends AnotherClass
        {
          public boolean aMethod()
          { return true; } 
	}

The answer is: it's impossible to tell without looking at all its superclasses. It might be overriding aMethod in AnotherClass, which might subtly alter the progress of some algorithm implemented by AnotherClass. Or perhaps some other object might dynamically check for the presence of aMethod and check its value if so. But without excellent documentation (not likely!) or access to all the source code, that code is completely opaque. The function of the code accomplished is by implication rather than by action [emphasis added]. And in my experience, a lot of OO code looks very similar to the above. Write some code, cross your fingers and hope it gets called...

Roger Peppe <rog-at-vitanuova.com>. Originally appeared in an IT Forum Plan 9/Inferno Programming. Quoted by permission.

The point made in two previous quotations receives a surprising corroboration, from a staunch C/C++ programmer. In his regular "C Programming" column in December 2000 issue of Dr.Dobb's Journal (Quincy 2000: Customizing the Print Dialogs, pp. 129-139), contributing editor Al Stevens describes tribulations of making a simple change in a OO (MFC) program. The whole article is well worth reading. Its conclusion offers a rather surprising advice:

Between getting the button installed, integrating the dialog, and fixing the phantom checkbox gotcha, I had a lot of false starts and made a lot of false turns during what ought to have been a simple job -- adding a checkbox to a dialog.... All the books that promise in their titles and on their back covers to reveal so-called secrets of Win32 MFC programming reveal very few actual secrets. Mostly what they do is explain how to write programs that stay within the boundaries that the designers of the Win32 API and MFC assumed you could live with. Usually I find those boundaries pertain only to the most trivial of applications, which is what books tend to use as examples, anyway. But when you want to push the envelope, break the bonds of convention, and escape those boundaries, forget the books. Your best bet is to trace the MFC source code and see what it's doing.
To add a simple checkbox to the standard MFC PrintDialog Al Stevens indeed had to examine -- reverse engineer, to be precise -- a large portion of the MFC code that deals with instantiating and operating PrintDialogs.

See also

Luca Cardelli, "Bad Engineering Properties of Object-Oriented Languages"
http://www.acm.org/pubs/citations/journals/surveys/1996-28-4es/a150-cardelli
 
Stephen C. Johnson, "Objecting to Objects,"
Invited Talk, Winter 1994 USENIX Conference, January 17 - 21, 1994, San Francisco, CA
http://www.usenix.org/publications/library/proceedings/sf94/full_papers/johnson.html
 
Shajan Miah, "Critique of the Object Oriented Paradigm: Beyond Object-Orientation," 14th May, 1997
http://members.aol.com/shaz7862/critique.htm

This and the next article put OOP claims to an experimental test. The proponents of OO argue that OO paradigm helps writing good software. The total time to develop an application that passes quality controls, the number and the rate of defects, the amount of time it takes to fix them -- are all measurable quantities. There should therefore be possible to experimentally compare OOP with alternative methodologies.
Granted, there is no such person as an "average programmer". By the same token, there is no "average patient". Response of each individual to a drug is unique. Nonetheless there are standard techniques -- clinical trials and statistical methods -- that can ascertain with confidence if a particular drug is effective in fighting a particular disease. Similar testing techniques can be applied to software engineering.
This and the following article report on such tests. They found out that OOP, compared to other methodologies, hurts rather than helps programmer's productivity. This is an experimental result.
 

Hatton, L., "Does OO sync with how we think?"
IEEE Software , Volume: 15 Issue: 3 , May-June 1998, pp. 46 -54.
From the abstract: "Is object orientation an imperfect paradigm for reliable coding? Worse, does it focus on the wrong part of the life cycle? The author thinks so and explains why."

Remark: Basically the biggest difficulty with OO is inheritance, especially implementation inheritance. Overriding and extending behavior requires a programmer to determine and keep in mind all the various ways a parent object may be used. This requirement may stretch human capacity. Humans can hold in their short-term memory roughly 7 pieces of information.
 

Scott N. Woodfield, "The Impedance Mismatch Between Conceptual Models and Implementation Environments"
Proceedings of the ER'97 Workshop on Behavioral Models and Design Transformations: Issues and Opportunities in Conceptual Modeling 6 - 7 November 1997, UCLA, Los Angeles, California.

Remark: Furthermore, most of the OO languages are not faithful to the OO concept. For example, an object is usually an instance of a class. That is, an object cannot change its class during a lifetime. Consider an object representing a person. Consider classes 'persons under 21 years of age' and 'adults'. An object of an underage class cannot later become an adult. The underage object needs to be destroyed and an 'adult' class object instantiated. So much for the claim that OOP accurately models reality: on his 21st birthday, some capacities of the person surely change; yet a person at the age 21 +1 day remains basically the same person (character, name, color of eyes, names of the parents, school attending, etc) as he was at the age 21 -1 day.

 

Johnson, R.A. "The Ups and Downs of Object-Oriented Systems Development"
Comm. ACM 43(10), October 2000, pp. 69-73.

The paper reports the results of essentially an opinion poll, which found that the majority of 150 polled software developers think highly of OOP. However, the very same paper says, "while opinions concerning the benefits of OOSD [Object-Oriented Software Development] abound in OO literature, there is little empirical proof of its superiority." Is OOP an article of faith then?

 

Henry F. Ledgard, "Technical opinion: The emperor with no clothes"
Comm. ACM, 44(10), October 2001, pp. 126 - 128.

The article explains well-known theoretical problems with OOP (e.g., the "yo-yo" trouble). The thrust of the paper however is on productivity failure and on the reluctance of OOP proponents to back their enthusiasm with hard, empirical data.

"Numerous articles have been published in many periodicals, from IEEE Software and ACM journals, to Business Week and the Wall Street Journal. Mountains of PR suggest the great productivity improvements we could expect from OOP technology. Every programmer concerned about this technology learned to embrace this view. The truth is, the productivity improvements never happened. In fact, studies have shown software productivity as a whole has been in a decline for more than a decade. The five years prior to 1996 (the heydays of OOP), a period of general growth, software productivity was negative, more negative than any other industry [2]."
...

"What is most interesting is that no one appears to be talking in terms of productivity (for an exception, see [1]). They are all lost in the mazes of theoretical beauty of their creations. According to quality control expert Deming, if you can't measure it, you can't improve it. So why is it so difficult to bring computer science into the world of hard science and to start measuring the real results of some of these hypotheses?"

 

J.F. Pane, C.A. Ratanamahatana, and B.A. Myers, "Studying the Language and Structure in Non-Programmers' Solutions to Programming Problems"
International Journal of Human-Computer Studies, vol. 54, no. 2, February 2001, pp. 237-264. http://www-2.cs.cmu.edu/~pane/IJHCS.html
"Cypher and Smith (1995) found in user studies that inheritance hierarchies cause difficulty for children. Even among professional programmers, researchers have found that full-edged object-oriented programming is not necessarily natural (Deetienne, 1990; Glass, 1995)."

 

Benjamin C. Pierce, Robert Harper, "Advanced module systems (A guide for the perplexed)"
ICFP'00 Invited talk, Montreal, Canada, September 17-21, 2000. http://www.cis.upenn.edu/~bcpierce/papers/modules-icfp.ps

OOP is often considered a module system: a class is a namespace for its members. As the paper notes, "If a module provides just one abstract type X, and the types of all the operations have the form X -> T or T -> X (with X not in T), then we can re-organize the module as an object." The paper goes on to explain that OOP as a module system cannot express generic inter-module references, which matter in some real examples.

 

David Lorge Parnas, "On the Criteria To Be Used in Decomposing Systems into Modules." Commun. ACM, v15, N12, 1972, pp. 1053-1058.
The paper introduces ``module-oriented programming'', which is claimed to provide most of the benefits usually attributed to OOP (see e.g., a letter from the reader Rodney M. Bates, Comm. ACM, April 2005, p. 11).

 

Kambayashi, Y., and Ledgard, H., "The separation principles: A programming paradigm."
IEEE Software, v.21, No. 2, pp. 78-87, Mar-Apr 2004.

"In a real-world example, a 2004 study [the above citation] suggested that the separation of data and actions -- contrary to the philosophy of the OO paradigm -- may be better suited to many business applications than other problem-solving paradigms." Quoted from Chenglie Hu, "Dataless objects considered harmful". Comm. ACM, v48, No. 2, pp. 99-101, Feb 2005.


   

Complete code that accompanies the articles

http://okmij.org/ftp/packages/subclassing-problem.tar.gz
   

Functional C++

Brian McNamara and Yannis Smaragdakis,
http://www.cc.gatech.edu/~yannis/fc++/
 


Last updated May 5, 2005

This site's top page is http://okmij.org/ftp/

oleg-at-okmij.org
Your comments, problem reports, questions are very welcome!