From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=0.7 required=5.0 tests=BAYES_00,INVALID_DATE, MSGID_SHORT,REPLYTO_WITHOUT_TO_CC autolearn=no autolearn_force=no version=3.4.4 Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!cs.utexas.edu!tut.cis.ohio-state.edu!att!cbnewsl!arny From: arny@cbnewsl.ATT.COM (arny.b.engelson) Newsgroups: comp.lang.ada Subject: Re: Use of "is separate" and compilatio Message-ID: <3076@cbnewsl.ATT.COM> Date: 29 Nov 89 20:16:27 GMT References: <20600021@inmet> Reply-To: arny@cbnewsl.ATT.COM (arny.b.engelson,wh,) Organization: AT&T Bell Laboratories List-Id: In article <20600021@inmet> stt@inmet.inmet.com writes: >We have built a number of very large Ada systems at Intermetrics, >and our customers have built some even bigger ones. >As a result of this we have built up a very strong >prejudice *against* the use of subunits (aka "is separates"). >Instead, we try to structure our system as a series >of medium size packages (about 500-2500 lines each), >using either a functional or object-oriented structuring. > >Ideally, each of these packages represents a well-defined, >relatively self-contained component of the system. >When making a change or trying to understand a particular >feature of the system, it is generally only necessary to >look at the single medium-size package which implements it. >Furthermore, most of the candidates for low-level, small-chunk-of-code >reuse, are within a single package. My personal experience has been working mostly on somewhat smaller efforts (single person, 20000 - 30000 lines of code programs), and I don't agree with this philosophy for those types of programs. Generally, I have several "medium" size packages, but with most of these having a few small (about 50-200 lines) subunits. Each subunit implements a single requirement (for lack of a better term). Usually, when a change is required, it is to a single subunit (not always, but usually). I believe this is due to a combination of the nature of the application and a good design/program structure on my part. Occasionally it is necessary to restructure the parent package, but not often. >Subunits foul up this structure in a number of ways: >First and foremost, a single subunit is in no way "self-contained." >It has unlimited visibility into its parent unit, representing >a very "broad" interface (the worst kind). The visibility of the subunit doesn't change by integrating it into the parent. If proper scoping of declarations is done (i.e. only what really should be visible is visible), I don't see the problem. >Secondly, when editing a subunit, other related code is >not immediately available, so we have found that programmers >working on a heavily "subunited" program tend to reinvent the >wheel repeatedly, rather than noticing a similar sequence >of code in another subprogram of the same package, and >separating off that logic as a local shared subprogram >of the package. Isn't this a problem of the programmers not having enough knowledge of the program, rather than a problem of the program structure itself? If the programmer really knows the existing code, s/he will know enough not to reinvent the wheel. In my case, since I developed the entire program, I know when I can reuse an existing piece of code. Maybe your anti-subunits stance should be limited to very large systems with many programmers working on it. >Thirdly, subunits cause havoc with sophisticated optimizers, >especially subunits within subprograms. When calling a separately-compiled >subunit the compiler must assume the worst: that the subunit >accesses and/or updates all objects it can see, meaning that >all local variables visible to the subunit must be stored back >into memory from registers before the call, and reloaded afterward. Again, if proper scope is maintained for variables, there should be very few that to which this would apply. >Finally, they tend to allow single library units to grow >without bound. Often when a subsystem grows too big, it >is wise to split it up into a number of packages, each with >a narrower purpose. When using subunits, the tendency >is to instead just keep adding more and more functionality >into a single package. This is a very real risk, but is again a fault of the programmer. A good programmer should recognize that a subsystem needs to be split regardless of whether there are subunits; a less qualified programmer will let a single package grow to several thousand lines, containing many unrelated subprograms, regardless of whether or not subunits are employed. >As far as recompilation, subunits are also bad news, since >almost all compilers will recompile *all* subunits when >any change is made to the enclosing parent unit, including One of my goals in using subunits is to reduce the scope of changes. Fewer changes should involve the parent. >just the addition of another subunit. Of course, the total >amount of code is no greater than if the package had not >been "subunited" (presuming you resisted the growth-without-bound In other words (my words), the amount of code recompiled is the same, and there is no real difference. >phenomenon), but most compilers will compile a single 2500-line >package much faster than 50 50-line subunits. So what? I don't think this amount of reduced compilation time is a strong argument for changing your program structure. But, if the change is only to one subunit, compilation time can be reduced substantially. This has actually saved me a very substantial amount of time when adding a new feature as a subunit. I can repeatedly recompile and debug this very quickly. >Of course you win when the only change to be made was in a single >subunit, but in our experience, that incentive causes many >of the problems with subunits -- the avoidance of restructuring >of the package. Many bugs can best be fixed by modest >restructuring of the implementation of a package. Maybe and maybe not -- it depends on the bug. As far as avoiding the restructuring of a package because of subunits, I think this is again a fault of the programmer. I restructure when necessary, what's the big deal? Changing the documentation may be a different story, but that depends on your documentation, and how it is maintained. >Any attempt at restructuring in the presence of subunits >causes them all to be recompiled again. Even if they weren't subunits they would be getting recompiled anyway. It's easier to see what areas are untouched by a change when the code is in different files. >I should mention that reasonable people differ >on this whole "subunit" issue, and there are >selected places where a subunit can be extremely useful, >to, for instance, isolate a very small bit of host-dependent >code. However, on balance, I would regard them almost >as bad as a goto -- to be used only when all other >avenues have been exhausted. I think this view is a bit extreme, and its validity varies with each type of application and with the size of the application. Besides the arguments I presented above, as a result of my work environment I have saved a lot of time by using subunits. I have saved time on recompilation (on my sometimes overloaded system), on disk space (which we are always running out of), on printouts (they are smaller), and on debugging time (in many cases). Your mileage may (rather, will) vary. >As Lori Clarke, et al, said in their classic critique of >Ada subunits long ago, "nesting in Ada is for the birds." Tweet, tweet. :-) >S. Tucker Taft >Intermetrics, Inc. >Cambridge, MA 02138 Arny Engelson AT&T Bell Laboratories Whippany, NJ 07981 att!wayback!arny