Path: utzoo!utgpu!news-server.csri.toronto.edu!mailrus!cs.utexas.edu!tut.cis.ohio-state.edu!att!dptg!pegasus!psrc From: psrc@pegasus.ATT.COM (Paul S. R. Chisholm) Newsgroups: comp.lang.c++ Subject: object-oriented design (was Re: are 'friend's really necessary ??) Summary: software design is still tough! Message-ID: <4568@pegasus.ATT.COM> Date: 27 Mar 90 03:56:32 GMT References: <169@pollux.kulcs.uucp> <10589@alice.UUCP> <1082@targon.UUCP> <626@ksr.UUCP> Organization: AT&T Bell Laboratories Lines: 110 (I tried to be careful about attribution; I apologize if I goofed.) In article <169@pollux.kulcs.uucp>, herman@kulcs.uucp (Herman Moons) writes: > I don't know whether this question appeared earlier on the net. (*sigh*) I don't suppose anyone's collecting frequently asked questions (and their answers) . . . Also, please note that this whole discussion deals only with the abstract data typing features of C++, not the object-oriented features. > Are there any *good* reasons for having the friend concept in C++ ? In article <10589@alice.UUCP> ark@alice.UUCP (Andrew Koenig) writes: > Sure. One of the most common is when you're writing several > interrelated classes. In article <1082@targon.UUCP>, ruud@targon.UUCP (Ruud Harmsen) writes: > Only too true. And isn't this also the fundamental weakness of the > object oriented concept? For in the real world, and so in any > realistic information system describing a part of that real world, > *nearly all* classes are interrelated to *nearly all* other > classes. Classes often only make sense just because of their > relations to other classes. So if you have to use friends for that, > everyone will be anybody's friend, and as a result of all this > friendship, a *real* project in an OO-language tends to become just > the same mess as it does in a traditional language, like C. As Dr. Koenig pointed out in a later article, "interrelated" means "the implementation of one thing depends on the *implementation* of another thing". A "thing" in this case may be a whole class. If you're careful, only a few functions in class B (e.g., member function foo and static member function bar) will need to know about the implementation of class A; in which case, only B::foo and B::bar will need be friends of A. This is a Good Thing; it specifically limits what software can mess with an A, and what code must be looked at when the implementation of A changes. There's still a limitation, in that B::foo and B::bar must be visible to A to be friends of A. That implies that one class's private functions can only be friends of another class if the functions are public (or possibly protected), or if the whole first class is a friend of the second class. (I *assume* the visibility rules apply to friendship.) In article <626@ksr.UUCP>, reg@ksr.UUCP (Rick Genter) writes: > As one who does have experience with OOT and with complicated > applications, I (unfortunately) have to agree with the gist of this > assessment. . . . > Note that these [hard applications] can be made to work, but at a > significant performance penalty. The penalty is not the penalty of > a single virtual method invocation vs. a single function call; I > grant that that is (usually) insignficant. But often what happens > is that a method will invoke several other methods, each of which > will invoke other methods, and so on and so on. Suddenly that > insignificant overhead becomes quite significant. This has nothing to do with object-oriented design or programming; it has to do with data abstraction, and with structuring software into layers. (I assume that you're talking about function call overhead per se, and not function invocation vs. virutual method invocation. The difference is still trivial, especially if you add in the comparisons that would otherwise need to be made.) Granted, almost all object- oriented designs will have layering; but so will almost all non-trivial designs, OO or otherwise. One of the highlights of C++ is that it allows trivial layers to have trivial cost (i.e., a layer that just invokes another layer can be implemented with an inline function). > It seems to me that a study needs to be performed not on how to make > everything OO, but on how to make composite designs work: i.e., how > do I easily integrate my OO UI with my procedural data-flow > analysis. What, ho! "Composite design" is a collection of guidelines to follow when designing software: to maximize the strength (or "cohesion") of modules, and to minimize the coupling between modules. These principles are as applicable to OOD as any other design approach, and I strongly recommend all of the following references: L. L. Constantine, G. J. Meyers, and W. P. Stevens, "Structured Design", IBM SYTEMS JOURNAL, vol. 13, no. 2, pp. 115-139. Glenford J. Myers, RELIABLE SOFTWARE THROUGH COMPOSITE DESIGN, New York: Petrocelli/Charter, 1975. Edward Yourdon and Larry L. Constantine, STRUCTURED DESIGN: FUNDAMENTALS OF A DISCIPLINE OF COMPUTER PROGRAM AND SYSTEMS DESIGN, Englewood Cliffs, N.J.: Prentice-Hall, 1979. The last is in some sense the most complete. It also describes what has since been known as "structured design", or the Yourdon half of the Yourdon/DeMarco methodology that underlies almost all CASE tools. One starts by drawing dataflow diagrams; then one picks the "central transform" in the diagram, making that the root of a tree, and mechanically transforming the diagram into a tree. (The result, according to a comment from my CASE instructor, does *not* produce designs that have high cohesion and low coupling; but I have no reference other than this heresay.) While the method sounds reasonable, I've never been able to non-trivially decompose an interactive application into a dataflow diagram. Thus, Rick's comment about dataflow diagrams and OO user interfaces baffles me. Paul S. R. Chisholm, AT&T Bell Laboratories att!pegasus!psrc, psrc@pegasus.att.com, AT&T Mail !psrchisholm I'm not speaking for the company, I'm just speaking my mind.