Path: utzoo!attcan!uunet!seismo!sundc!pitstop!sun!decwrl!labrea!rutgers!deimos!uxc!uxc.cso.uiuc.edu!m.cs.uiuc.edu!p.cs.uiuc.edu!johnson From: johnson@p.cs.uiuc.edu Newsgroups: comp.lang.c++ Subject: Re: Current O-O Languages as Software E Message-ID: <77300016@p.cs.uiuc.edu> Date: 18 Nov 88 18:31:00 GMT References: <5155@thorin.cs.unc.edu> Lines: 106 Nf-ID: #R:thorin.cs.unc.edu:5155:p.cs.uiuc.edu:77300016:000:6125 Nf-From: p.cs.uiuc.edu!johnson Nov 18 12:31:00 1988 Claim: (by some unknown person) dynamic binding at run time allowed architecture and implementation to be more independent of each other in practice, therefore the Smalltalk model would be better for large-system development than the Simula model. I agree with the first part of the statement, but C++ provides dynamic binding at run time, so the last half is a non sequitur. >If you prototype using Smalltalk, you adopt the Smalltalk object hierarchy >as your architectural tools/metaphors/thought patterns. You also adopt >the underlying implementations, but they can be thrown out or redone >later. By adopting the Smalltalk environment, you might be >starting off your architectural design effort by putting on a >straitjacket and blindfold. Anything works for small projects. For >large projects the fit of mental models, architecture, and language >abstractions needs to be tighter in order to manage and control the >project. I believe that this fit can be made tighter by designing >abstractions (classes) to fit the project, not twisting the mental >model to fit a predefined hierarchy. This is the '80's version of the >top-down heuristic: > Let the implementation conform to the conception. There seem to be several misunderstandings of Smalltalk here. Smalltalk certainly does not force anyone to use existing classes. People use them because they are well designed. People use classes for control structures, arithmetic, data structures (collections), and user interface design. There really aren't many application specific classes. Any large project will require the creation of many new classes, i.e. you will have to invent your own abstractions and implement them. Most of these classes are universally needed and well done. The main exceptions are the graphics and user interface classes, which were very well designed for 1980, but are showing their age. However, people don't seem to see much need in redesigning the collection classes. It seems to me that you are arguing against reuse. I find that hard to believe. It is very hard to write reusable code, and trying to reuse code that is not reusable is no fun. However, it is possible for code to be reusable, and Smalltalk is an example. Smalltalk programmers reuse code because that is the easiest way to develop a high-quality product. In my opinion, if you aren't interested in reuse then you shouldn't bother with object-oriented programming. However, I'll assume that are you interested in reuse. As a project grows, class hierarchies get extended. This usually results in bad class hierarchies, so eventually they get reorganized. One could claim that you should just have designed them right to begin with, but hind-sight is always so wonderful. The problem is how to get hind-sight, and the solution is to go build something (wrong). I claim that no good designer is going to find a class hierarchy a straight-jacket, because if it is not working then it will be changed. There are several situations where reuse can cause problems. One is where you program instead of thinking. Thinking is always a good idea, and I push prototyping as an aid to thinking, not as a replacement to it. Another is where you start with a bad package and so have to spend a lot of time fixing it. If there is a better package available, this is a complete waste of time. However, if you are using the only one available then reading somebody else's code prevents you from learning by an even harder way. (I am assuming that the writer of the package that you are using is at least as good a designer as you are, and that the problems with the package are due to narrowness of vision, and not incompetance.) Although prototyping without thinking can cause problems, thinking without prototyping is more common and also causes problems. I have seen people debate for weeks about some point that could be solved in a couple of days by experimentation. It is a lot easier to debate about an algorithm once it is written down, at least people are arguing about the same thing. There should be much, much, much more reuse in software systems. We don't keep inventing new abstractions for arithmetic, why should we be doing it for everything else? It is clear that it takes a long time to come up with good abstractions, so new areas, like user interface design, go through a lot of fermet until they mature. However, eventually we figure out what we are doing and then we can quit throwing out our old software can can just reuse it for awhile. There are lots of areas of CS that are well enough understood that we should be able to standardize them. This includes many areas in operating systems (scheduling, file systems), areas in business (general ledger, receivables, payables), and a lot of graphics. Then people can write books about these abstractions and we can just use them. In a couple of years C++ will have just as large a class library as Smalltalk, maybe larger. Lots of companies are already developing their own. Nobody will force you to use them, but the high-quality libraries will have lots of users. >>My type system for Smalltalk is much more flexible than the one for C++. >>I am curious about Dr. Coggins's explanation of why C++ is not as good >>for reuse, and wonder how types fit in to it. >The question is whether the flexibility in the type system afforded by >late dynamic binding is ultimately an advantage (by virtue of its >additional support for abstracting architectures independent of >implementations) or ultimately a disadvantage (by delaying detection >of errors and in fact not detecting as errors some things that in fact >are errors). One of the purpose of a type system is to detect errors at compile-time. A type system for an object-oriented language, for example, should prevent any "message not understood" errors at run-time. I don't see why late binding itself prevents the detection of errors. As I said earlier, C++ virtual functions provide late binding, and the type system for C++ ensures that an object understands the messages sent to it.