rmartin@clear.com (Bob Martin) (11/11/90)
In article <14369@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes: > >Often, because it was written by amateurs, or at any rate hackers who >have not learned the magnitude of the maintenance problem for >production software. The lack of standard coding practice IS a big problem for software maintenance. At Clear we have instituded a style standard which all our engineers follow. This standard specifies how indenting should be done, how variables, functions and types should be named. I specifies that functions should have single entrance and single exit points, and that functions should not be much longer then one page. It specifies a documentation style and demands that comments always be placed on closing braces. etc. etc. One might think that engineers would resist this kind of "infringement on their creativity" But in fact we have found that most engineers want to have standards like this since they can then read each others code easily and channel their creativity towards the problem instead of towards the style. -- +-Robert C. Martin-----+---------------------------------------------+ | rmartin@clear.com | My opinions are mine. They aren't anybody | | uunet!clrcom!rmartin | elses. And thats the way I want to keep it.| +----------------------+---------------------------------------------+
imp@marvin.Solbourne.COM (Warner Losh) (11/17/90)
In article <1990Nov10.191840.21113@clear.com> rmartin@clear.com (Bob Martin) writes: : The lack of standard coding practice IS a big problem for software : maintenance. Agreed. However, a bad coding standard can make life miserable for everybody. : It specifies that functions should have single entrance and single : exit points This is a bogus restriction, at least in terms of a single exit point. When you have small functions, the return statement can be used to give meaningful flow control to the functions w/o the need for a "goto". I have found that when I adhere to this rule, I either get code that looks like: if (allocate-memory) { do some stuff if (get-more-memory) { do more stuff if (open-file) { do even more stuff if (alloc more memory) { ... status = OK; } else status = NO_MEM } else status = NO_FILE } else status = NO_MEM } else status = NO_MEM return status; Or I get code that looks like: if (!allocate-memory) { status = NO_MEM; goto done; } do some stuff if (!get-more-memory) { status = NO_MEM; goto done; } do more stuff if (!openfile) { status = NO_FILE; goto done; } do even more stuff if (!alloc memory) { status = NO_MEM; goto done; } last stuff status = OK; done: return status; When what I really want is: if (!allocate-memory) return NO_MEM do some stuff if (!get-more-memory) return NO_MEM do more stuff if (!openfile) return NO_FILE do even more stuff if (!alloc memory) return NO_MEM last stuff return OK; A quick check reveals that the above code segments are all the same. However, I may have missed something. The final one is the clearest one, IHO, of them all. Comments.... -- Warner Losh imp@Solbourne.COM How does someone declare moral bankruptcy?
6600dt@ucsbuxa.ucsb.edu (David Goggin) (11/17/90)
In article <1990Nov10.191840.21113@clear.com> rmartin@clear.com (Bob Martin) writes: >At Clear we have instituded a style standard which >all our engineers follow. This standard specifies how indenting >should be done, how variables, functions and types should be named. >I specifies that functions should have single entrance and single >exit points, and that functions should not be much longer then >one page. It specifies a documentation style and demands that >comments always be placed on closing braces. etc. etc. I don't think I'd like to have a format forced on me like that. I think, however, I _well-designed_ standard does go a long way in clearing up the problem. I would reccommend a standard that is thought out carefully in advance, to be most logical in showing the structure of code, as well as aestheticaly pleasing (a big factor for me.) *dt* 6600dt@ucsbuxa.bitnet
stanley@phoenix.com (John Stanley) (11/17/90)
imp@marvin.Solbourne.COM (Warner Losh) writes: >This is a bogus restriction, at least in terms of a single exit point. >When you have small functions, the return statement can be used to >give meaningful flow control to the functions w/o the need for a >"goto". >>lots of code deleted<< >A quick check reveals that the above code segments are all the same. >However, I may have missed something. The final one is the clearest >one, IHO, of them all. Comments.... Ooh, an invitation for comments! The main advantage to having one exit point is that it is easier to be sure any necessary cleanup is performed prior to exit. It can be quite messy when cleanup code is distributed in multiple copies throughout the file. The example that I deleted involved opening files, then doing something, then exiting if that something caused an error. This type of situation makes it very easy to forget to close that file. If you call this function many times, and have many errors, you will eventually run out of files. It was just this bug I found in some production code, a year after it was released. I put the software into a neverending demo loop during a trade show and noticed that it started complaining about "no more units" after 20 minutes or so. The code was bullet proof enough that it didn't crash, just could no longer access any data. If the code had had but one exit from that routine, it would probably have never had that bug get by. <> "Aneth! That's a charming place!" "You've been to Aneth?" <> "Yes, but not yet." -- The Doctor and Seth, "The Horns of Nimon". >< <> "Sanity check!" "Sorry, we can't accept it, it's from out of state." - me
c164-bd@falstaff.uucp (John D. Mitchell) (11/17/90)
>In article <1990Nov10.191840.21113@clear.com> rmartin@clear.com (Bob Martin) writes: > >At Clear we have instituted a style standard which >all our engineers follow. This standard specifies how indenting >should be done, how variables, functions and types should be named. >I specifies that functions should have single entrance and single >exit points, and that functions should not be much longer then >one page. It specifies a documentation style and demands that >comments always be placed on closing braces. etc. etc. > I hate to jump into the middle of a religious war :-) but... from working as a consultant/contractor, school (as a student), and school (as a reader) I have found that it's not so much someone's code formatting that makes such a big difference in ease of comprehension but their design. I have seen many bizarre (to me :-)) coding formats but as long as it was halfway rational (read I could figure it out :-)) and most of all CONSISTENT I could quickly adapt and understand the meaning. Sure there are cases where the code is all nice and tidy but makes no sense, but each time it's the ambiguity of the design of the [module|function|whatever] that's to blame (which of course was the coder/designer's fault). So make my life easier by being consistent. As far as single entry/exit points go, I side with those who say "It depends." Again I stress the need for a clean design. Sometimes (ok so I'm moody! :-)) it works out nice for multiple return calls and other times it doesn't. I've been led to believe that we're all supposed to be grown-ups and can make those kinds of decisions. The trick for me is: which way is the least complicated. Naming. What a mess. You get everything from the minimalists (i, i2, tmp, etc.) to those foreigners (:-)) at M#$@*soft with their 'Hungarian' notation. Once again (boy I sure am repetitive!), it depends. My style is still evolving. I use my own (I think more consistent and orthogonal) version of 'Hungarian' notation. Hey, it works for me and the way the rest of the name is (long and descriptive :-)) if you don't understand the prefix you can just ignore it. ----- John D. Mitchell johnm@cory.Berkeley.EDU
dmocsny@minerva.che.uc.edu (Daniel Mocsny) (11/17/90)
In article <7267@hub.ucsb.edu> 6600dt@ucsbuxa.ucsb.edu (David Goggin) writes: >In article <1990Nov10.191840.21113@clear.com> rmartin@clear.com (Bob Martin) writes: >>At Clear we have instituded a style standard which >>all our engineers follow. > >I don't think I'd >like to have a format forced on me like that. But by deviating from the standard, you are forcing additional noise and complexity on everyone who needs to read your code. Even a fairly poor standard will beat no standards almost every time, provided that the poor standard begins with a large-enough share of the user base. The standard then becomes the language that enables the users to share ideas with each other. Like any communications system, the overall value of the system is in direct proportion to the number of subscribers. For example, consider the english language (and associated dialects, such as all the USA varieties). What a mess---hundreds of irregular verbs, a hopelessly irrational non-phonemic alphabet, an enormous number of grammatical and pronunciation rules which it violates constantly, etc. Any person with a shred of logic would understandably hate to have such a standard imposed on them. The logical person would chuck this bloated, inconsistent monstrosity and start over with something simple and elegant, such as esperanto or loglan. Yet english, with all its obvious warts and shortcomings, is quite simply THE most valuable language to speak. This does not follow from any inherent advantage of the language. Rather, it follows from who happens to be speaking the language. And humans, being such marvelously adaptive creatures, are quite capable of tolerating the flaws of english and using it to advantage in spite of them. If everybody who didn't like the details of the language decided to change them as they saw fit, what would happen to the language? It would become worthless. Fragmentation doesn't always kill computer languages, of course, because the computer can be made to "understand" any dialect. But fragmentation does reduce the value of a computer language as a means for communication between programmers. As long as we insist on creating code of potential value to more than one person, this will be an important consideration. > I >think, however, I _well-designed_ standard does go a >long way in clearing up the problem. I would >reccommend a standard that is thought out carefully >in advance, to be most logical in showing the >structure of code, as well as aestheticaly pleasing >(a big factor for me.) The situation for programmers is better than for natural-language speakers, because automated formatting tools can allow individual programmers some latitude for expression, while still retaining compatibility with the standard. For example, the details of indenting belong in a pretty-printing program (or language-sensitive editor, for that matter). I can think of no reason to impose any particular indenting style on a programmer, because a quick run through a standardizing beautifier will repair any idiosyncrasy. -- Dan Mocsny Snail: Internet: dmocsny@minerva.che.uc.edu Dept. of Chemical Engng. M.L. 171 dmocsny@uceng.uc.edu University of Cincinnati 513/751-6824 (home) 513/556-2007 (lab) Cincinnati, Ohio 45221-0171
gwyn@smoke.brl.mil (Doug Gwyn) (11/17/90)
In article <i7NRs3w163w@phoenix.com> stanley@phoenix.com (John Stanley) writes: > The main advantage to having one exit point is that it is easier to be >sure any necessary cleanup is performed prior to exit. A lot of the code in BRL's MUVES project has functions implemented more or less along the following lines: bool function( ... ) { ... if ( problem ) { ErSet( CODE_0 ); goto err_0; } ... if ( problem ) { ErSet( CODE_N ); goto err_n; } ... return true; /* success */ /* error handling consolidated here: */ err_n: fclose( fp ); /* for example */ ... err_0: FreeList( tp ); /* for example */ ... return false; } The idea is to make sure the sequential actions are unwound in reverse order when an error occurs. While there are numerous other methods, this one has worked rather well in practice. It is also a good example of structured use of "goto".
henry@zoo.toronto.edu (Henry Spencer) (11/18/90)
In article <6733@uceng.UC.EDU> dmocsny@minerva.che.uc.edu (Daniel Mocsny) writes: >...I can think of no reason to impose any >particular indenting style on a programmer, because a quick run through >a standardizing beautifier will repair any idiosyncrasy. Nonsense. There are several reasons for not relying on beautifiers, summed up well by the words written over a decade ago in the Indian Hill style guide (with my footnote): ---------- This committee recommends that programmers not rely on automatic beautifiers for the following reasons. First, the main person who benefits from good program style is the programmer himself. This is especially true in the early design of handwritten algorithms or pseudo-code. Automatic beautifiers can only be applied to complete, syntactically correct programs and hence are not available when the need for attention to white space and indentation is greatest. It is also felt that programmers can do a better job of making clear the complete visual layout of a function or file, with the normal attention to detail of a careful programmer\*f. .FS .IP \*F In other words, some of the visual layout is dictated by intent rather than syntax. Beautifiers cannot read minds. .FE Sloppy programmers should learn to be careful programmers instead of relying on a beautifier to make their code readable. Finally, it is felt that since beautifiers are non-trivial programs that must parse the source, the burden of maintaining them in the face of the continuing evolution of C is not worth the benefits gained by such a program. ---------- -- "I don't *want* to be normal!" | Henry Spencer at U of Toronto Zoology "Not to worry." | henry@zoo.toronto.edu utzoo!henry
dbc@bushido.uucp (Dave Caswell) (11/18/90)
.At Clear we have instituded a style standard which .all our engineers follow. This standard specifies how indenting .should be done, how variables, functions and types should be named. .I specifies that functions should have single entrance and single .exit points, and that functions should not be much longer then .one page. It specifies a documentation style and demands that .comments always be placed on closing braces. etc. etc. In my opinion anyone who wants to standardize simple formatting considerations had better write a program to translate arbitrary code into that standard. On the other hand rules like having a single entrance and exit point are good ones. They should be written down and strictly enforced. -- David Caswell dbc%bushido.uucp@umich.edu
amodeo@dataco.UUCP (Roy Amodeo) (11/18/90)
In article <IMP.90Nov16123956@marvin.Solbourne.COM> you write: >In article <1990Nov10.191840.21113@clear.com> rmartin@clear.com (Bob Martin) writes: >: It specifies that functions should have single entrance and single >: exit points > >This is a bogus restriction, at least in terms of a single exit point. It does solve some problems. The code fragments you've posted are a pretty good illustration of why such standards exist. May I please "correct" them? >When you have small functions, the return statement can be used to >give meaningful flow control to the functions w/o the need for a >"goto". I have found that when I adhere to this rule, I either get >code that looks like: > > if (allocate-memory) { > do some stuff > if (get-more-memory) { > do more stuff > if (open-file) { > do even more stuff > if (alloc more memory) { > ... > status = OK; > } > else > status = NO_MEM > } > else > status = NO_FILE > } > else > status = NO_MEM > } > else > status = NO_MEM /*-- Don't forget to free memory and close files on failure! --*/ if ( status != OK ) { if ( file-is-opened ) close-file; if ( more-memory-was-got ) free-more-memory; if ( memory-allocated ) free-memory; } > > return status; > >Or I get code that looks like: > > if (!allocate-memory) { > status = NO_MEM; > goto done; > } > ... > > last stuff > > status = OK; >done: /*-- Insert same code fragment from above here --*/ > return status; > >When what I really want is: (with cleanup code added) > > if (!allocate-memory) > return NO_MEM > > do some stuff > > if ( !get-more-memory) { free-memory-allocated-above > return NO_MEM } > > do more stuff > > if (!openfile) { free-memory-allocated-above free-memory-allocated-first-time > return NO_FILE } > > do even more stuff > > if (!alloc memory) { close-files ... > return NO_MEM } > > last stuff > > return OK; > >A quick check reveals that the above code segments are all the same. I hope I've preserved that. >However, I may have missed something. The final one is the clearest >one, IHO, of them all. Comments.... But as you can see, it's also the most painful to modify to clean up after itself. When there is no cleanup to be done, I agree that the last example is clearest. However, if you introduce an operation near the beginning that does have to be cleaned up when you fail then you are setting yourself up for some pain. That said, I think the first method is a pain, because of the indentation required. The second one uses goto's which I still do not like (although this is the only use of goto's that I consider justifiable (especially if the programmers use a standard naming convention for the label at the end of the routine. )) A method we have been using on a very large project that retains readability in exchange for making cleanup code a bit more awkward is the following: ( adapted to the conventions above ) In a project-wide include file we have #define FAILIF( cond, reason ) { if (cond) { FAIL_ACTION; return reason; } } #define FAIL_ACTION /*-- default is do nothing --*/ The code we would write for your example would be: #undef FAIL_ACTION #define FAIL_ACTION \ if ( file-is-opened ) \ close-file; \ if ( more-memory-was-got ) \ free-more-memory; \ if ( memory-allocated ) \ free-memory; \ FAILIF( !allocate-memory, NO_MEM ); do some stuff FAILIF( !get-more-memory, NO_MEM ); do more stuff FAILIF( !open-file, NO_FILE ); do even more stuff FAILIF( !alloc more memory, NO_MEM ); return OK; The eye is forcibly directed to the abnormal termination conditions, whereas embedded returns are a little harder to see. If one is concerned about the amount of code generated, you could always do this: #undef FAIL #define FAIL(cond,reason) { if (cond) { status = reason; goto failed; } } FAILIF( !allocate-memory, NO_MEM ); ... return OK; failed: if ( file-is-opened ) close-file; ... return status; Actually I really prefer the second form. The code produced is a little tighter and it puts the cleanup code in a better place: near the normal return statement. Apologies for being longwinded, and I hope I didn't come off sounding too arrogant. I'll second Warner's request for comments. >Warner Losh imp@Solbourne.COM rba iv (a signature file would be an admission of existence) nrcaer!dataco!amodeo
jdarcy@encore.com (Jeff d'Arcy) (11/19/90)
dbc@bushido.uucp (Dave Caswell) writes: >rules like having a single entrance and exit point are good >ones. They should be written down and strictly enforced. Blech! Consider the following example: int fubar (x, y, z) int x, y, z; { if (abnormal_condition_1) return(foo); if (abnormal_condition_2) return(bar); for (blah; blah; blah) { do_some_stuff(); if (screwed_up) return(foobar); do_other_stuff(); } return(blech); } If you enforce a single-exit-point rule the code will be obfuscated to a pretty high degree. For starters you'd have to declare a dummy return variable to hold values for the abnormal_condition cases, just so you can use it at your single exit point. Then you'd have the entire for loop encased in an unnecessary extra if statement, contributing to "indentation creep", that nasty syndrome where the real work in a routine is indented halfway across the page. To get rid of the return statement in the for loop you'd either have to use a break (another no-no) or add a new status variable, making the loop condition more complex and indenting the bottom part of the for loop still further. In short, the handstands you'd have to do to enforce a single-exit-point rule make the code *less* readable and often less efficient as well even in simple cases such as this. I'm rabidly opposed to unconstrained goto statements, but return, break and continue are controlled enough to be worthwhile. -- Jeff d'Arcy, Generic Software Engineer - jdarcy@encore.com Ask me if I care. . .maybe I do
browns@iccgcc.decnet.ab.com (Stan Brown) (11/19/90)
In article <1990Nov10.191840.21113@clear.com>, rmartin@clear.com (Bob Martin) writes: > > The lack of standard coding practice IS a big problem for software > maintenance. At Clear we have instituted a style standard which > [...] demands that comments always be placed on closing braces. Am I the only one who thinks this extremely silly? int io_fatal_error_count = 0; void io_error(int code) { char *errmsg; errmsg = io_stget(code); if (errmsg == NULL) { ++io_fatal_error_count; printf("Error code %d: full explanation not available\n"); } /* end if errmsg is NULL */ else printf("Error %d: %s\n", code, errmsg); } /* end of function prterr */ Given _any_ rule in a coding standard, it's possible to come up with an example where applying the rule is inappropriate. But the rule cited above is the other way round: following it is more likely to hurt than help. Following it blindly will certainly hurt. Just to hammer homee the point: My problem is chiefly with the "always" part of the cited rule. Please do not attribute these remarks to any other person or company. email: browns@iccgcc.decnet.ab.com Stan Brown, Oak Road Systems, Cleveland, Ohio, USA +1 216 371 0043
ghoti+@andrew.cmu.edu (Adam Stoller) (11/19/90)
Excerpts from netnews.comp.lang.c: 16-Nov-90 Re: Coding Standards. was:.. Warner Losh@marvin.Solbo (1834) > When what I really want is: > if (!allocate-memory) > return NO_MEM > do some stuff > if (!get-more-memory) > return NO_MEM > do more stuff > if (!openfile) > return NO_FILE > do even more stuff > if (!alloc memory) > return NO_MEM > last stuff > > return OK; The final one is the clearest one, IHO, of them all. Comments. Well, if you're looking for a highly maintainable coding standard - you would be better off keeping the braces for each if/else/for/while/(etc) loops (not to mention the semicolons after the return statements;-) - i.e.: { if (!allocate-memory){ return (NO_MEM); } /* do some stuff */ if (!get-more-memory){ return (NO_MEM); } /* do more stuff */ if (!openfile){ return (NO_FILE); } /* do even more stuff */ if (!alloc memory){ return (NO_MEM); } /* last stuff */ return (OK); } Whether or not to put parens around the argument to return is, of course, another tidbit of religious wardom, I prefer to do it, a lot of other people prefer not to - whatever you do, you should try to be consistant. As for the braces - the reason for them is that it helps to avoid nasty situations when the next person maintaining the code has to add one more thing before the return statement - and doesn't realize that there wasn't a set of braces around it to begin with. By always putting the braces there, you waste a fairly insignificant amount of space, do nothing if not improve readabiltiy, and increase the maintainability (by others) quite a bit -- by not leaving the door open for those simple to make (and often hard to find) bugs. Other than that, I agree with you in that I find your third example (with above modification) much clearer to work with than the [in]finite nesting, or goto style. --fish
dmocsny@minerva.che.uc.edu (Daniel Mocsny) (11/20/90)
In article <1990Nov18.005030.28841@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes: >In article <6733@uceng.UC.EDU> dmocsny@minerva.che.uc.edu (Daniel Mocsny) writes: >>...I can think of no reason to impose any >>particular indenting style on a programmer, because a quick run through >>a standardizing beautifier will repair any idiosyncrasy. > >Nonsense. There are several reasons for not relying on beautifiers, >summed up well by the words written over a decade ago in the Indian Hill >style guide (with my footnote): >---------- >This committee recommends that programmers not rely on automatic >beautifiers for the following reasons. >First, the main person who benefits from good program style is the >programmer himself. I apologize for being unduly vague with "programmer". I should have said "competent programmer". I assumed a programmer who already believes (s)he has a "good" programming style, and is able to write code that (s)he can read. I didn't mean someone who loses the ball after writing 50 lines of spaghetti. Such a programmer definitely should not rely on a beautifier (if the beautified output is too different from the original, it won't assist the programmer's thinking). So the "any idiosyncrasies" I had in mind would probably be rather slight. However, in the rest of this article, I will try to show that if beautifiers are deficient, then our definition of "good program style" must be similarly deficient. >Automatic beautifiers can only be applied to complete, syntactically >correct programs and hence are not available when the need for >attention to white space and indentation is greatest. This was written 10 years ago. That sounds like a long time in the world of computers. It especially sounds like a long time in the C language market, which is quite dynamic and competitive now. Has no progress transpired in the meantime, or are we talking about an inherent limitation of beautifiers? (Remember, in my original comment, I assumed a programmer who does not need help from a beautifier to read her/his own code, and I was speaking of a beautifier as a tool to assist programmers in the job of reading other programmer's code.) >It is also felt that programmers can do a better job of making clear >the complete visual layout of a function or file, with the normal >attention to detail of a careful programmer\*f. This is the crux of the original notion in this thread. The question was whether a standardized coding style was a good idea. I said I favored standards over chaos, in general. Saying the programmer can do a better job at source formatting is equivalent to saying that we cannot rigorously define a standardized coding style. A rigorously defined style would be suitable for implementing in a beautifier and compliance-checking program. If this is not possible, then what we call "good program style" must necessarily remain somewhat vague. A vague standard leaves many details to the discretion of the programmer. While this probably reduces the value of the standard, insofar as minimizing the barriers to inter-programmer communication, it also reduces the potential for disagreements on style. >In other words, some of the visual layout is dictated by intent >rather than syntax. The standard must not interefere, then, with the details of layout that depend on programmer intent. However, that still leaves some question about how syntax shall dictate those portions it dictates. What will happen when two programmers disagree on the best way to lay out those portions of their code which are amenable to syntax- dictated layout? Since these two programmers disagree about a detail which is easy to embed in a beautifier program, since it depends only on syntax, then a beautifier program should be able to mediate the style disagreement, and allow each programmer to view the other's code consistently with personal preference. I now modify my original garbled claim to the previous sentence. >Beautifiers cannot read minds. Then this must also be true of the definition of "good program style". Everything we can unambiguously state about "good program style" must be able to live in a beautifier. If we can't write good beautifiers, then we also can't say exactly what we mean by "good program style", other than we know it when we see it. :-) >Finally, it is felt that since beautifiers are non-trivial programs >that must parse the source, >the burden of maintaining them in the face of the continuing evolution >of C is not worth the benefits gained by such a program. This is almost certainly true if the programming team must maintain its own tools. However, in 10 years the market for C language tools has grown substantially. The market today can provide the economy of scale needed to turn the "burdens" of 10 years ago into profitable opportunities. I suspect that 10 years ago, the burden of maintaining full-screen symbolic debuggers was also not worth the benefits gained by such a program. Today, of course, we regard an environment lacking such to be rather deficient. -- Dan Mocsny Snail: Internet: dmocsny@minerva.che.uc.edu Dept. of Chemical Engng. M.L. 171 dmocsny@uceng.uc.edu University of Cincinnati 513/751-6824 (home) 513/556-2007 (lab) Cincinnati, Ohio 45221-0171
dbc@bushido.uucp (Dave Caswell) (11/20/90)
I said >>rules like having a single entrance and exit point are good >>ones. They should be written down and strictly enforced. . .Blech! Consider the following example: . >int fubar (x, y, z) >int x, y, z; >{ > if (abnormal_condition_1) > return(foo); > if (abnormal_condition_2) > return(bar); > for (blah; blah; blah) { > do_some_stuff(); > if (screwed_up) > return(foobar); > do_other_stuff(); > } > return(blech); Try modifying this to pass in the error value, or how about if clean-up code has to be written. They're plenty of reasons to think that a goto to ERROR_EXIT: (or whatever), is better than having more than one return statement. -- David Caswell dbc%bushido.uucp@umich.edu
peter@ficc.ferranti.com (Peter da Silva) (11/20/90)
(crossposted to comp.lang.misc... this is a general coding problem and not C-specific) My objection to beautifiers is what they do to stuff like this: ARGDESC Args[] = { 'T', ARGOPT, argChar, __ &TabChar, "Tab", 'a', ARGOPT, argBool, __ &AllFlag, "All", '1', ARGOPT, argBool, __ &OneFlag, "First", ' ', ARGREQ, argStr, __ &Format, "Format", ' ', ARGREQ|ARGLIST, listStr, __ &CmdNames, "Command", 'f', ARGOPT|ARGLIST, listStr, __ &Files, "File", ENDOFARGS }; The only real solution to this is to include formatter commands in comments or something of that nature, so the code ends up as: ARGDESC Args[] = { /*.TS L L L L L */ 'T', ARGOPT, argChar, __ &TabChar, "Tab", ... 'f', ARGOPT|ARGLIST, listStr, __ &Files, "File", /*.TE */ ENDOFARGS }; Which is probably a good idea, especially if you make the format command syntax loose enough: /*.TS option flags function variable keyword */ But I don't know any fprmatter that supports this... -- Peter da Silva. `-_-' +1 713 274 5180. 'U` peter@ferranti.com
salomon@ccu.umanitoba.ca (Dan Salomon) (11/21/90)
In article <6741@uceng.UC.EDU> dmocsny@minerva.che.uc.edu (Daniel Mocsny) writes: >In article <1990Nov18.005030.28841@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes: > > It is also felt that programmers can do a better job of making clear > > the complete visual layout of a function or file, with the normal > > attention to detail of a careful programmer\*f. > > ... Saying the programmer > can do a better job at source formatting is equivalent to saying that > we cannot rigorously define a standardized coding style. A rigorously > defined style would be suitable for implementing in a beautifier > and compliance-checking program. If this is not possible, then what > we call "good program style" must necessarily remain somewhat vague. > The real problem is that to prepare the ideal layout for a program the beautifier would have to: (1) Read and understand the comments. This is especially true if the comments label the rows and columns of a table of data or expressions. (2) Understand the problem being solved, and the method being used. Blank lines in code segments can help delineate the steps in a computation, and spaces can be used to group related parts of an expression. (3) Know enough psychology to predict the human response to a layout. Layout choices made by a standard can be optimal in the general case but suboptimal in specific cases. All of these factors influence a complete program layout. It is still much easier for a programmer to do it while coding than for someone else to write a beautifier that can do it after the fact for any program at all. -- Dan Salomon -- salomon@ccu.UManitoba.CA Dept. of Computer Science / University of Manitoba Winnipeg, Manitoba, Canada R3T 2N2 / (204) 275-6682
rmartin@clear.com (Bob Martin) (11/22/90)
In article <291@dcsun21.dataco.UUCP> amodeo@dataco.UUCP (Roy Amodeo) writes: >In article <IMP.90Nov16123956@marvin.Solbourne.COM> you write: >>In article <1990Nov10.191840.21113@clear.com> rmartin@clear.com (Bob Martin) writes: >>: It specifies that functions should have single entrance and single >>: exit points >> >>This is a bogus restriction, at least in terms of a single exit point. > >It does solve some problems. The code fragments you've posted are >a pretty good illustration of why such standards exist. May I please >"correct" them? > >A method we have been using on a very large project that retains readability >in exchange for making cleanup code a bit more awkward is the following: >( adapted to the conventions above ) > >In a project-wide include file we have > >#define FAILIF( cond, reason ) { if (cond) { FAIL_ACTION; return reason; } } >#define FAIL_ACTION /*-- default is do nothing --*/ > >The code we would write for your example would be: > >#undef FAIL_ACTION >#define FAIL_ACTION \ > if ( file-is-opened ) \ > close-file; \ > if ( more-memory-was-got ) \ > free-more-memory; \ > if ( memory-allocated ) \ > free-memory; \ > > FAILIF( !allocate-memory, NO_MEM ); > do some stuff > > FAILIF( !get-more-memory, NO_MEM ); > do more stuff > > FAILIF( !open-file, NO_FILE ); > do even more stuff > > FAILIF( !alloc more memory, NO_MEM ); > return OK; > The thing that I don't like about this is that the "cleanup" code is relatively hidden, and thus it is easier for a noviciate to make modifications which are not "cleaned up". I understand the desire to hide the cleanup details since they detract from the 'intent' of the function. It is easier to determine "what" a program is doing if the cleanup details are hidden. But it is harder to determine if the "what" is being done correctly. IMHO if a function is going to be understood, then the details are just as important as the "what", and deserve as prominent a place in the code. If this makes the function a bit harder to understand, then I say that the extra effort is justified since otherwise the function would not "really" be understood. When you hide cleanup details, you are sending a message to future readers of your code: "Don't worry about this guys, I've already taken care of it." This is _never_ the message you want to send. Instead you want to say: "This is what I did to do the job, and this is what I did to clean up after." -- +-Robert C. Martin-----+:RRR:::CCC:M:::::M:| Nobody is responsible for | | rmartin@clear.com |:R::R:C::::M:M:M:M:| my words but me. I want | | uunet!clrcom!rmartin |:RRR::C::::M::M::M:| all the credit, and all | +----------------------+:R::R::CCC:M:::::M:| the blame. So there. |
rmartin@clear.com (Bob Martin) (11/22/90)
In article <2055.27469abd@iccgcc.decnet.ab.com> browns@iccgcc.decnet.ab.com (Stan Brown) writes: >In article <1990Nov10.191840.21113@clear.com>, rmartin@clear.com (Bob Martin) writes: >> >> The lack of standard coding practice IS a big problem for software >> maintenance. At Clear we have instituted a style standard which >> [...] demands that comments always be placed on closing braces. > >Given _any_ rule in a coding standard, it's possible to come up with an >example where applying the rule is inappropriate. But the rule cited >above is the other way round: following it is more likely to hurt than >help. Following it blindly will certainly hurt. > >Just to hammer homee the point: My problem is chiefly with the "always" >part of the cited rule. The "ALWAYS" is present because it is the safest course. Programmers are not always very good at predicting what changes will be made to their code in the future. If he makes decides that comments on his closing braces are not important because his conditionals are trivial, then he is ignoring the possibility that two years from now some other engineer my add many lines of code to his conditionals, making the comment on the closing brace useful. The convention is "demanded" because it is cheap, easy, has very few down-sides, and the _possibility_ of significant up-sides. -- +-Robert C. Martin-----+:RRR:::CCC:M:::::M:| Nobody is responsible for | | rmartin@clear.com |:R::R:C::::M:M:M:M:| my words but me. I want | | uunet!clrcom!rmartin |:RRR::C::::M::M::M:| all the credit, and all | +----------------------+:R::R::CCC:M:::::M:| the blame. So there. |
peter@ficc.ferranti.com (Peter da Silva) (11/29/90)
In article <6733@uceng.UC.EDU> dmocsny@minerva.che.uc.edu (Daniel Mocsny) writes: > Even a fairly poor standard will beat no standards almost every time, > provided that the poor standard begins with a large-enough share of > the user base. [uses English language as an example] Ah, but consider what it would be like to have to express oneself: 1) In bureaucratese which a) is the sort of standard that standards committees generate i) with the best of intentions ii) despite their own best efforts b) is capable of driving people i) insane A) clinically B) metaphorically ii) to desparate acts c) nobody wants to read, whether i) they want to ii) they have to A) as a job requirement B) simply to get along I) with friends II) with family III) with the government ... etc... -- Peter da Silva. `-_-' +1 713 274 5180. 'U` peter@ferranti.com
rsalz@bbn.com (Rich Salz) (12/06/90)
In <L237B.5@xds13.ferranti.com> peter@ficc.ferranti.com (Peter da Silva) writes: >My objection to beautifiers is what they do to stuff like this: ARGDESC Args[] = { 'T', ARGOPT, argChar, __ &TabChar, "Tab", 'a', ARGOPT, argBool, __ &AllFlag, "All", '1', ARGOPT, argBool, __ &OneFlag, "First", ' ', ARGREQ, argStr, __ &Format, "Format", ' ', ARGREQ|ARGLIST, listStr, __ &CmdNames, "Command", 'f', ARGOPT|ARGLIST, listStr, __ &Files, "File", ENDOFARGS }; If you put the curly braces in then there would be no problem: { 'T', ARGOPT, argChar, __ &TabChar, "Tab", } Anyone who maintains the code after you will thank you for it. The other problem is to not use the C pre-processor to change the syntax of the language, as __ and ENDOFARGS apparently do. /r$ -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net. Use a domain-based address or give alternate paths, or you may lose out.
peter@ficc.ferranti.com (Peter da Silva) (12/07/90)
In article <3072@litchi.bbn.com> rsalz@bbn.com (Rich Salz) writes: > In <L237B.5@xds13.ferranti.com> peter@ficc.ferranti.com (Peter da Silva) writes: > >My objection to beautifiers is what they do to stuff like this: > 'T', ARGOPT, argChar, __ &TabChar, "Tab", > If you put the curly braces in then there would be no problem: > { 'T', ARGOPT, argChar, __ &TabChar, "Tab", } Really? I run this code through Indent and I get: { 'T', ARGOPT, argChar, __ & TabChar, "Tab", } > Anyone who maintains the code after you will thank you for it. Good point. I normally do, but in this case I was cribbing from the parseargs sample code. > The other problem is to not use the C pre-processor to change the syntax of > the language, as __ and ENDOFARGS apparently do. Complain to Eric Allman. I don't see this as such a heinious sin, myself, if it significantly improves readability (as it does in this case). -- Peter da Silva. `-_-' +1 713 274 5180. 'U` peter@ferranti.com