Path: utzoo!utgpu!news-server.csri.toronto.edu!rutgers!mcdchg!tellab5!balr!clrcom!rmartin From: rmartin@clear.com (Bob Martin) Newsgroups: comp.lang.c Subject: Re: Re: Coding Standards. was: a style question Message-ID: <1990Nov21.181610.23512@clear.com> Date: 21 Nov 90 18:16:10 GMT References: <14369@smoke.brl.mil> <1990Nov10.191840.21113@clear.com> <291@dcsun21.dataco.UUCP> Organization: Clear Communications, Inc. Lines: 72 In article <291@dcsun21.dataco.UUCP> amodeo@dataco.UUCP (Roy Amodeo) writes: >In article 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. |