Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!csd4.milw.wisc.edu!uxc!deimos.cis.ksu.edu!rutgers!att!westmark!mole-end!mat From: mat@mole-end.UUCP (Mark A Terribile) Newsgroups: comp.lang.c++ Subject: Re: objective C Message-ID: <176@mole-end.UUCP> Date: 8 May 89 07:10:19 GMT References: <2614@ssc-vax.UUCP> <3180@stpstn.UUCP> <15327@gryphon.COM> <1562@sw1e.UUCP> Organization: mole-end--private system. admin: mole-end!newtnews Lines: 165 ... The question is Objective-C .vs. C++ -- does the type structure of C++ prevent you from re-using (inheriting from) things for which you don't have the entire source code (but for which you do have the class declaration, presumably in .h file)? ... ``No'' was the first answer proposed ... ... ``Yes'' I declared, since all that is necessary to write a class derived from the given class, and to link that class in, is the stuff in the class declaration. > Ummm, I think you got that backwards. ... The terminology used in Brad's > description can be rather confusing. Let me try again and see (1) if I can > describe it well and (2) just how much I can get flamed ... > Suppose you're provided with class 'sprocket' which someone else wrote. ... > Now, lets look at where strong typing restricts things ... > If class 'sprocket' takes arguments, then it must decide upon the types of > the arguments that it takes. Assume that 'sprocket' takes at least one > object as an argument. C++ requires that you provide a type for that > argument in the form of a formal parameter in the .h and .c files. This > restricts you to a member of that class or one of its sub-classes (nothing > new here). But lets look at a pretty generic member function (method) like > 'print' or 'display'. You could easily expect to create classes not derived > from the same superclass and have them incorporate a 'print' method (or > 'display' or whatever). ... C++ requires that if ``sprocket'' requests something of an object that has been passed to it, that object has been declared to have that capability (that member function must exist for the class of which the object is an instance). Yes. > Yet C++ requires you to make a choice when writing the supplier as to what > classes are valid objects ... The programmer of ``sprocket'' must declare what he will accept, and the things that he (or his class) will accept must have a set of capabilities (member functions) which includes all that will be asked of them. > ... This means that the person writing the code for the supplier must decide > a priori what tasks 'sprocket' might be usefull in solving. But the whole > point of writing suppliers it to avoid making decisions about what kinds of > problems can be solved with code for 'sprocket' and instead let the client > programmer look at available classes and decide what to use. This is getting pretty close to one of the uses of Multiple Inheritance. If I have a Doojigger which I want processed by a Sprocket, then Doojigger has to somehow inherit the capabilities that Sprocket will use. If it doesn't, I'm free (using MI) to quickly wrap a derived class around Doojigger recasting the operations that are needed into those that are available. This means I have to do a little work. In return, I am guaranteed that I won't get a runtime error from the method dispatch system. In code that I am building into a product, I think the tradeoff is appropriate. It also means that the Sprocket must get its ``print'' from a visible, if not standard, set of declarations. The first part is easy; the second is significantly harder. It's less of a problem in a large project that has its own standard environment or in a case where you've bought a complete bunch of goodies from one software author/vendor. > ... Furthermore, the 'precompiled classes' scenario prevents this option > anyway since you can't control the inheritance tree of the precompiled > classes you (theoretically) buy from some software vendor. ... This > severely limits the reusability of the code for 'sprocket'. Again, MI does provide a solution. > Now, before you get out your flame-throwers, let me reiterate that I realize > that there are advantages to OO other than reusability. In particular, > encapsulation helps tremendously with debugging, correctness, and I'm sure > there are others I've missed. ... You've got the big ones. I think that you are underrating them, however. It's nice to have a force multiplier for little bits of effort. It's nice not to have to write even ten lines of (declared as such) interface code between old and new. On the other hand, in the real world of large products, ten lines of code is a drop in the bucket. If with ten lines of code, we can improve the reliability of the software by even five percent, we've won--big. Reliability of delivered software is the greatest problem we face, and by far. Does ``portability'' mean ``runnable unchanged'' or ``relatively easy to get running, even if a few changes are needed'' ? I contend that the latter definition is valuable, *IF* we can identify the changes reliably. The same can be said of ``reusability.'' I'm not so worried about software re-use. Most large systems have been recoded piecemeal dozens of times, each change introducing bugs because there were never definite guidelines to use in creating the original structure or in making changes that might or might not violate whatever conceptual structure the program had. We are already paying costs far greater than that of coding a simple type at need. I've seen managers who wouldn't know good programming style if it chained them to a desk and did a striptease scream ``no goto's'' because that's accepted good practice. OOP has the potential for the same, usually beneficent effects. (The existance of certain brain-damage in LINT provides a counter-example.) There are also two ways to view OOP. One is to view it as a way to build programs from existing pieces; the other is to view it as a way to organize the structure of a problem so that a well-structured program may be written. Objective-C stresses the first. Re-usability because it's there stresses the first. C++ stresses the latter. The low overhead of member functions and the ability to write operators make *expression* of the problem more rewarding than parts-bin assembly. Both approaches have their place, but on the large scale, I think that the latter is the way to get programs for which the efforts of ``testers'' (whether they be provers, reviewers, walk-through teams, or old-fashioned ``bang-on-it-until-it-breaks'' boredom specialists) will more rapidly converge on a program which for which liability can be risked when it is placed in the hands of thousands of customers. > However, *IMHO*, reusability provides the greatest potential benefits in > the long run if we can develop techniques to support it. As I said before, I place reliability first. If we can make it reliable cheaply, we can make it more cheaply than if we make it and then spend money making it reliable. > ... Okay, maybe the strong typing of objects helps in other ways (I'm not > convinced of that yet); ... I am. Getting it right in concept and reliable in fact are more important to me. A program that is not reliable is a legal, ethical, and moral liability; if it's so unrealiable that it has to be tweaked over hundreds of times because it was put together from the parts that were there, rather than built from parts whose correct relationship to each other was established, it's a financial liability as well. Those finances finance our paychecks. It's accepted that every stage of development through which a problem persists increases the cost of fixing the problem by at least an order of magnitude. Thinking out how to string together parts that need an Adapt-O-Kit costs more than getting the parts right; finding a problem in a review or walk- through costs more than finding it in code on the programmer's desk; finding it in testing costs still more; finding it in initial field testing costs even more. Depending on the nature of the product, one of the later steps in delivery may be worth two orders of magnitude in cost. > ... maybe multiple-inheritance will help change fix the problem I've > described above. I don't know. Again, anyone care to comment? It can. There will be some execution cost. In a quick-and-dirty slaptogether it probably doesn't matter. In a program where it does matter, getting the pieces right should be counted part of the cost of getting the thing right altogether. Oh, and if the C++ templates can be implemented (3.0 ?) they will probably improve the situation still further. > Brian R. Gilstrap Southwestern Bell Telephone > #include -- (This man's opinions are his own.) From mole-end Mark Terribile