Path: utzoo!utgpu!jarvis.csri.toronto.edu!clyde.concordia.ca!uunet!microsoft!jimad From: jimad@microsoft.UUCP (JAMES ADCOCK) Newsgroups: comp.object Subject: Re: Comments on OOP style Message-ID: <10527@microsoft.UUCP> Date: 9 Feb 90 19:51:34 GMT References: <135300027@p.cs.uiuc.edu> <135300028@p.cs.uiuc.edu> Reply-To: jimad@microsoft.UUCP (JAMES ADCOCK) Organization: Microsoft Corp., Redmond WA Lines: 65 In article <135300028@p.cs.uiuc.edu> johnson@p.cs.uiuc.edu writes: > >Rereading in the morning the message I sent last night, it is clear that >I was harder on jimad@microsoft than I intended to be. He raises important >points about good designs being changeable and that one class shouldn't >access too many other classes. I disagreed with his numbers because of >the fact that standard and often used classes are almost invisible to >the expert. Thus, accurate design rules will be much more complex than >the ones that he was proposing. However, the general idea is certainly >valid. > Well, let me make it perfectly clear that I don't claim there are any "hard" numbers, and I don't know all the answers here. In the classes I've seen, if they are dependent on a couple dozen other classes, they are a disaster. Likewise if they have about 100 methods, they are a disaster. My first test nowadays of the "goodness" of a set of classes is to try to draw a dependency chart of the classes: 1) If you can't draw a dependency chart [because the design is so obscure, or so convoluted], the design is bad. 2) If the resulting graph looks bad, the design is bad [I claim.] A bowl of spaghetti is a bowl of spaghetti, whether implemented via control flaw [sic] or class declarations. 3) If you include dependencies on global classes, or global decisions in general, the graph is going to look bad. There are maybe two answers to this a) take global classes, global decisions [global whatevers] as a given and leave them off the chart or b) decide globals of any kind are bad, and try to program to avoid them. BUT: We are all use to taking a few globally used primitive types are a given, and use them throughout our programming: ints, chars, 32bit-floats, 64bit-floats, strings?, etc. Is this good or bad? Should these "primitive" types count on our dependencies chart? Or could it be that the continued global use of primitive types is an indication of our immaturity in OOP? --And that when we become more competent in OOP we will develop more powerful classes to do our jobs, and leave the primitives behind? I don't know. I think I may claim the later. Q: What does it take to make a good looking interdependencies graph? A: A given class must typically not depend on more than a half dozen other classes. Q: When does a class "depend" on another class? A: I don't know a single right answer for this. If C depends on B depends on A, but B's dependence on A is strictly encapsulated, then C should not be considered directly dependent on A. Presumably C can be understood without referring to A's code. But in a final executable executing C *is* going to be dependent on A. And, at least in C++ [and presumably in some other OOPLs] compiling C is going to require the compiler first to read in parts of the definition of B and A. Ideally, in a well designed language, if B strictly encapsulated its dependency on A [made it private] then compilation of C would only require knowledge of the definition of B, not also of A. In short, one can come up with several different dependency charts depending on what definition of "dependency" one is interested in. And they could all be valid ways of looking at *differing* problems of interdependency.