Dr. Dobb's Journal November 1997
Dear DDJ,
The article "Design Guidelines for Is-A Hierarchies," by John A. Grosberg (DDJ, June 1997) is outstanding, but may not go far enough in its recommendations. John has described an excellent technique for validating object models. However, I believe that he could have made his technique stronger by identifying partially overlapping sets in Venn diagrams as warning signals of an incomplete analysis.
I subscribe to the idea that multiple inheritance is a technique to be avoided where possible, and should almost never be used in the logical modeling of a subject area. I understand that the use of multiple inheritance in implementation may be the most effective technique available, so I restrict my comments to logical modeling.
Specifically addressing the example in Figure 8, the Venn diagram depicting Mammal and Egg Laying as overlapping subsets of Animal forces the creation of a multiply inherited subclass in the object model. While Mammal and Egg Laying may be valid subsets of Animal, they are not comparable for the purpose of dividing the class of Animals. Specifically, an Animal is a Mammal if it feeds its young with milk from mammary glands. This attribute of an Animal is entirely independent of the type of birth implied by Egg Laying. One alternative classification could use the subsets Live Birth and Egg Laying to partition on a common attribute and create disjoint subsets.
In general, subclasses of a base class based on orthogonal criteria are likely to represent an error in analysis and should be reexamined. Most likely, some business rule that more clearly describes the partitioning has not been explicitly stated. Since this condition will appear in a Venn diagram as overlapping sets, this should be a warning flag to the modeler.
The specific criteria for creating subclasses will be dependent on the subject area and the type of behavior desired by the user of the application. In the terminology of Figure 8, is the intent to classify instances by the feeding of young or the method of birth? By clearly identifying the criteria for membership in a subclass, the modeler explicitly states the business rules driving the application.
Martin Aavik
mraavik@hewitt.com
John responds: Although I agree that multiple inheritance should be used as little as possible, I don't think it should be ruled out altogether. Martin's critique of the overlapping Mammal and Egg Laying subsets of Animal in Figure 8 is valid: There are definitely two different "rules" applied to partition the Animal set in that example. A correct model should use only one rule to partition a class or set. Martin's point that overlapping sets should be examined to ensure that they resulted from applying a single partitioning rule is good advice. But using a single rule won't guarantee nonoverlapping sets.
Take this example. Say that we are interested in animals again, and in particular, we want to identify their habitats. Let's assume that there are only three general habitats: Air, Land, and Water. These three values (for our purposes) partition the habitat class without overlap. And, if all we wanted to do was to associate each animal with its habitat, we could add a "habitat" attribute to the animal class and not need to subclass it. As soon as we do that, we must account for the fact that some animals have multiple habitats. Instead of just three values, we have (abstractly) a minimum of seven: Air, Land, Water, AirLand, AirWater, LandWater, AirLandWater. But if we are interested in representing the different behaviors associated with their habitats (flying, walking, swimming), we must use subclasses. We then have these choices (there are other choices but there's no need to discuss them here): either a. divide the Animal class directly into seven concrete subclasses avoiding multiple inheritance, or b. use multiple inheritance with the abstract subclasses AirAnimals, LandAnimals, and WaterAnimals leading to the seven concrete subclasses as diagrammed in Figure 9 of my article. The first choice doesn't allow any factoring of functionality among the classes. Nor does it allow for any polymorphism at any level below Animal. Either option is valid, but of course my preference would be for the second option.
Dear DDJ,
Eugene Eric Kim's "News & Views" on Ada (DDJ, August 1997) is, I believe, a misinterpretation of the true position. You'll find some resources addressing the Paige memorandum at http://www.adahome.com/articles/1997-05/po_memoweight.html. The memorandum requires software language choice to be made using a rational process, which has to consider many factors. Clearly if it's not appropriate to use Ada, it shouldn't be used; but equally, many of us would be reluctant to fly in the 777 if its avionics were programmed using Visual C++. Perhaps it's a good thing that the certification requirements make it unlikely that that will happen.
Simon Wright
simon@pogner.demon.co.uk
Dear DDJ,
As a long-time participant on the ISO/ANSI C++ Standard committee, I read Al Stevens' September 1997 "C Programming" column with some bemusement.
Two kinds of articles typically appear: Those written by volunteers helping to prepare the standard for release, which provide concise and accurate information; and the rest. Sadly, Al's column is among the latter.
I can't help with Al's dyspepsia, but I would like to correct some of his errors that could confuse readers.
First, compilers that implement partial specialization, and other advanced features, are readily available (see http://www.edg.com). Second, Al has written about ostream::write for a long time; however, that function's interface was never very portable. Wise programmers use the stable and portable streambuf::sputn for low-level output instead. Third, anybody who uses Al's idiom
namespace name {
#include <header.h>
}
invites trouble; certainly no competent compiler vendor would use it.
Finally, nothing in the current Draft forbids vendors from placing C library names in the global scope; it only requires that those names (also) appear in namespace standard. Furthermore, the only changes to old C headers needed were done by all vendors long ago: Declare using Standard C (not K&R) notation, and observe some discipline about use of #define. Beyond that, C++ wrappers for these "legacy" headers, to declare the names required in namespace standard, suffice. (I will be happy to assist any worried vendor in conforming.)
I feel for Al's problems in writing "portable" books, but those seem more his problems than DDJ readers'. Explaining how to use Standard C++ to full advantage will be a big job. Dyspepsia and misinformation can only make it less fun.
Nathan Myers
http://www.cantrip.org/
Al responds: Nathan's "sadly" adverb suggests that only committee members should be permitted to or are qualified to comment publicly on committee activities. Surely he has not forgotten the lunch he shared with Bjarne Stroustrup and me where we agreed that trade journalists should refrain from committee participation in order to preserve objectivity.
Re: "dyspepsia." I had no difficulty digesting the Draft; just staying awake.
I disagree that one cannot write istream::read and ostream::write functions with void* arguments since it's already been done with simple inline member functions that call the char* specialized functions. Nathan's challenge to the namespace idiom is not backed up with any argument of substance; he merely says it "invites trouble." Do us a favor, Nathan; share your knowledge; say why.
Certainly the draft does not forbid vendors from (also) putting C stuff in the global scope or anywhere else, but it does not say that you must, which encourages disparate implementations from different vendors depending on where they stand on the issue. The purpose of a Standard is to tell implementers what to do, not what not to do.
Finally, anyone who thinks that an author's problems are not those of the readers could spend some time reading my e-mail to correct that misunderstanding.
Dear DDJ,
It was interesting to see Richard Tichler's exemplary finger-pointing letter in the September issue as to who may have been responsible for my Y2K credit card problem, which I described in my letter in the May, 1997 issue of DDJ.
As a customer, frankly I couldn't care less whose computer was at fault. As a programmer, I can only comment that there is a proven level of inactivity on this question that will wind up costing some people a lot of money and making some lawyers very rich.
I might add as a sequel to my letter, that a week or so after the mess happened, I received a spanking new Eurocard via an express registered letter with an expiration date in 1999 instead of the original one with Year 2000. Presumably this was quicker than fixing the software! If one assumes that Eurocard had to supply new cards to only 1/36th of their users, the mind boggles at what that must have cost them given the millions of cards they service. My "Year 2000 Eurocard" has gone into my collection of valuable treasured curiosities.
The new 1999 card had a new number, although it's hard to understand why that was necessary. So I had to send snail mail letters to all suppliers from who I buy regularly via credit card and who don't have facilities for receiving encrypted credit card information via e-mail informing them of the change. That was additional time, trouble, and expense for me.
All appears to have calmed down for the moment. I don't look forward to what may happen when my 1999 card expires in February of that year, but I'm hoping for the best.
Irwin Scollar
al001@rs1.rrz.uni-koeln.de
DDJ