Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!nbires!hao!hplabs!tektronix!uw-beaver!cornell!rochester!ritcv!cci632!rb From: rb@cci632.UUCP (Rex Ballard) Newsgroups: net.arch Subject: Re: Missionary Position .vs. 69 Message-ID: <237@cci632.UUCP> Date: Sun, 20-Jul-86 22:34:20 EDT Article-I.D.: cci632.237 Posted: Sun Jul 20 22:34:20 1986 Date-Received: Tue, 22-Jul-86 00:54:01 EDT References: <2900019@ztivax.UUCP> <858@ucbcad.BERKELEY.EDU> Reply-To: rb@ccird1.UUCP (Rex Ballard) Organization: CCI, Rochester Development, Rochester, NY Lines: 112 Summary: Getting connected. In article <858@ucbcad.BERKELEY.EDU> faustus@ucbcad.BERKELEY.EDU (Wayne A. Christopher) writes: >In article <2900019@ztivax.UUCP>, david@ztivax.UUCP writes: >> In other words, a bottom up design allows the top levels (the "user" >> language) to work better, and to be more flexible: the user is not >> tied to one language which may be applicable to one use, but can >> develop or choose other languages which have better primitives for the >> problem at hand. There seems to be an opinion here that primitives are a feature of language rather than of system/application/design. This is a problem. >> (slight pause to don flame-proof suit) >> >> Top-down sucks, bottom up is better. > >What sort of silly comment is this? There is no such thing as "bottom >up" or "top down" design -- there is good design and there is bad >design, and a good designer will think about his problem from an >overall standpoint (top down) and then based on this, create the >primitives that are needed (bottom up). >If you design programs by >indiscriminately creating primitives without any thought about what >they are to be used for, or if you think only in terms of high-level >algorithms and don't think about your low-level representations until >you are forced to, you are going to write a bad program. > > Wayne Unfortunately, in many systems, the designer comes up with a cute design like this. ------------ ------------ |get record| ----> |print record| ------------ ------------ | | ------------- record file ------------- What happened to open, read, block, deblock, flush, lock,...? And of course, each member of the record, which may contain as many as 100 fields, flags, and states, must be accessed and manipulated. They end up getting written into the "get record" routine. The end result is that "get record" becomes a 2000 line "superfunction". Later on, someone else needs to get records from the record file but doesn't want the record stripped of information. So he copies "get record" and hacks to his hearts delight. To make it really interesting, imagine a "file driver" which requires special ioctl calls, or worse, a non-unix system or network comm program that requires direct manipulation of hardware registers. In no time at all, the design becomes a maintenence nightmere that no one can touch. Now, since the users needs must change, "record file" structure must change as well. What could have been a 10 line change in one place, may become a 200 line change in 20 or 30 places. The fundamental problem is one of communications and design cycle. In many cases, a system analyst or system designer spends months writing the design documents, and then "hands it over" to the implementors. Eventually, the implementation design is returned in the form of general documentation, and none of this "duplication" is discovered until the maintenence team begins to discover them. Even then, each member of this team may only see two or three of these "duplicates" in his scope of duties. It is only when they get reassigned to several tasks, over several years, that they realize how much effort is spent on duplicate primitives. The biggest problem comes when such a system is "set in stone", either in the form of ROM or Micro-code. Changes are much more difficult to implement in such a system than their RAM counterparts. Even the UNIX system, with it's "recompile kernal to add driver" archetecture come very close to "set in stone" implementation. In addition, how many systems make "root" or "bin" the sole means of adding a tool to the bin directories or to the libraries. User contributed tools are less than trivial to get adopted, yet they are often so useful, that people's paths will often contain several ~user/bin componants, or links. If the design cycle were a matter of days, and the design/implement/document cycle is communicated on a weekly or even daily basis, the number of duplicate "get record member" primitives could be reduced significantly. The old "60/1/39" (60% design, 1% coding, 39% debug/document) formula is still valid. The main difference is that the team might spend the entire morning "designing", the majority of the of the afternoon coding/debugging the "known levels" of the design, and come back to indentify needed or invented primitives. These primitives can be incorporated into the remaining design, and even "tuned" in a "universal" manner. How many times have you seen "bcopy(3)" functionality coded in-line? How many "convert binary byte to string" routines? How many "test member of structure" routines? How many times it the reason give as "speed", "efficiency", or "printf takes too much space"?. How many times is the critical factor something OTHER than the "sped up" routine. In one example, the code was so fast, it could execute in 4ms, but the comm time was over 200ms. An extra 2ms for mainainable code would not have hindered performance that significantly. In addition, the so-called "optimized" code, was, in many cases slower than a functionally identical primitive. Disclaimer: These observations come from a variety of sources, so don't consider them a reflection on my current employer.