Path: utzoo!attcan!uunet!husc6!mailrus!ames!amdahl!nsc!woolsey From: woolsey@nsc.nsc.com (Jeff Woolsey) Newsgroups: comp.software-eng Subject: Re: Paradigms for source control Message-ID: <5067@nsc.nsc.com> Date: 16 May 88 23:56:06 GMT References: <5291@cup.portal.com> <2846@mmintl.UUCP> Reply-To: woolsey@nsc.UUCP (Jeff Woolsey) Organization: National Semiconductor, Sunnyvale Lines: 186 In article <2846@mmintl.UUCP> franka@mmintl.UUCP (Frank Adams) writes: >I have considerable familiarity with this latter class of code control (SCCS/RCS/PVCS et. al. (S/R/P hereinafter)) >systems (including having written one), but I have never before encountered >the former kind. (MODIFY/UPDATE/REVISE et. al. (M/U/R hereinafter)) >I am having some difficulty understanding just how it is supposed to work. >Everyone involved in the discussion apparently was quite familiar with them, >so the above is the best description of them supplied. It leaves quite a >bit unanswered. Let me provide a simple, yet complete run-down of the M/U/R model. The differences between the three are implementation issues, or small variances within the paradigm. There exists a Program Library (PL) consisting of source program modules (decks), include files (common decks), named changes (modsets), and a directory (for random access). The PL is a single file. Its appeal is its integrity. Some effort is required to delete part of a PL. If you have the PL, you have the whole source. When you want to compile a program in a PL, you direct M/U/R to make a compile file. This file is fed to the assembler or compiler as is. Each line in it consists of the source line and a sequence number. The sequence number is the name of the deck or modset followed by the ordinal of that line within the deck or modset. Common decks are the same as source decks except that they have a bit set meaning that they can be included (at compile-file time) in another source deck. Their original purpose was to hold all the COMMON declarations in FORTRAN programs. You cannot generate a compile file from just a common deck. A modset consists of its name, the name of the deck to modify, and insertion or deletion directives each followed by abritrarily long sections of text. The text is inserted at the point the insertion or deletion directives refer to. The insertion points are desginated as modname.seqno or deckname.seqno, or just seqno if an original card in the deck is desired. Deletion points can specify a range of lines. The resemblance to drawers of punched card decks is the obvious ancestry. It's probably obsolete, although lines are still pretty pervasive as the unit of change in source control. Modset creation generally means that you take a nice assembly/compiler listing (made from the compile file with its sequence numbers) and go off into a corner and mark it all up. Then you figure out which lines are the insertion and deletion points, and type up your new text in between directives. Then you reenter the edit-compile-debug loop. Eventually the process was automated with tools analogous to diff -e. If a source deck contained enough modsets such that not more than some arbitrary number of lines were original code, it was said to need resequencing. This is a fairly major event in the life of a deck, and probably only happens twice. It destroys all the modset information while retaining the net changes. The OS vendor would resequence decks occasionally with new releases, and installation-specific modsets would have to be converted because the line numbers changed. Locally- developed programs could suffer resequencing, too. A set of miscellaneous tools rounded things out with the ability to extract everything back into source form and expunge modsets and other mundane operations. >It appears that the main editing done by programmers using such a system is >the creation of "modsets". These, in general, specify that certain lines >are to be inserted into a particular piece of source code. (I gather some >systems allow more than one piece of source (source file or "deck") to be >updated with the same modset. Maybe they all do?) For reference purposes, UPDATE/REVISE treat decks and modsets as the same thing, whereas MODIFY distingushes them. This just dictates whether there are "DECK" directives in your modset, and what the modset sequence numbers are. However, this ability of one named change to alter several related source entities simultaneously and indivisibly is one of several features I miss from the M/R/U paradigm. Another feature is independent, non-monotonic changes, any particular collection of which may be selected to build a particular flavor of product. (analogous to #ifdef FEATURE ) The third is PL integrity (mentioned above). >In addition, a modset >may specify that certain lines of code be deleted (deactivated), or that >certain lines which were previously deleted be restored. Restoring deleted lines, though supported, was a no-no as far as OS support was concerned. A real good way to cause dependencies and other conflicts. You were to accomplish the same net effect by inserting new copies of the orignally-deleted lines. COMPARE (diff -e) would do it this way. Joe User, in complete control of his own PLs, however, is perfectly welcome to create conflicts and dependencies, as long as he can deal with the results. >I don't know how the lines to be inserted or deleted are identified. I >would guess that each line has a line number, and that new lines are >inserted so that their line numbers remain in order. By name.number . "number" is always sequential, and there are no fractions. Each change (modset) has a unique name (modname). The number of a line never changes, but it could be deactivated, and an identical line with a different modname and number could replace it. This is one reason why resequencing is so traumatic. >It appears that traditionally, programmers directly created modsets, and >that it is a relatively new and far from universal thing for them to edit >the entire source file, and create the modfile mechanically. "relatively" is relative here. This basically describes the state of affairs four years ago and more at a large university running mainframes. Eventually each programmer would discover that COMPARE could generate modsets. >It appears that the compilation step (in the development cycle) with such a >system is preceded by combining the programmer's modsets with the current >state of the code control system to produce the actual source to be compiled. Essentially correct. It is a special case. Even in the case of product installation, a compile file is built. The PL is really a list of lines, each of which contains a pointer to each modset that referenced it and how (active or not). When applying a modset, another set of these pointers is built, and making the compile file involves looking at the list of pointers to see the net effect. If the line is now active, it is copied to the compile file. >When a programmer is satisfied with his changes, he "signs in" his >modfile(s). There may(?) be a review by someone before this actually >becomes part of the standard. For the OS with local changes, yes. The system programmers "submit" their modsets to a coordinator, who then figured out which (if any) modsets conflicted or depended upon one another or the same thing. (This process was eventually automated.) The submittors were then asked to reconcile their modsets to resolve these problems. Then the whole mess was printed and circulated for code review. >-------- >It seems to me that the main problem with this kind of system is sorting out >simultaneous changes to the same piece of code. It seems to me that the >advocates of this approach have become so used to dealing with this, that >they simply accept it as part of the system. (In the comments I saw, there >were several suggestions for *mitigating* the problem, but no hint that it >was something one might want to *eliminate*. It is a key advantage of the >SCCS-style approach that it does avoid the problem.) So what does a programmer do while waiting for the code to be available? Go to the listings on the shelf and work out the changes based on that version. Then when the source is free, apply the changes. Surprise, reality has changed. But there are usually many ways to subvert the intentions of a source code control system. >I should note my own preference (not fully shared by my current co-workers). >I prefer an SCCS-style code control system, in conjuction with a convention >that there is only one entry point per file. If, as is good for other >reasons as well, the functions are all kept relatively small, then all the >source files are small. This means that two programmers trying to access >the same file at the same time are really trying to change the same code, >and one of them should wait for the other to finish. (The inability for two >people to modify the same module at the same time is the characteristic >problem of this style of code control system, as integrating simultaneous >changes is the characteristic problem of the other.) Usually the integration is painless, if the two programmers are doing different things and don't bump into each other. >One *must* support this with some kind of include file system, so that >declarations can be consistent across modules. The inclusion process need >not be regarded as the responsibility of the code control system, however. >(The include files themselves are source files to be maintained; but that is >another matter.) Indeed. It just so happend that M/U/R provided the include mechanism because the included portions are part of the program library. They could also be included from another such library, if needed (usually the case for the system common decks). -- Scrape 'em off, Jim! Jeff Woolsey National Semiconductor woolsey@nsc.NSC.COM -or- woolsey@umn-cs.cs.umn.EDU