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=-1.3 required=5.0 tests=BAYES_00,INVALID_MSGID autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: fac41,9a0ff0bffdf63657 X-Google-Attributes: gidfac41,public X-Google-Thread: f43e6,9a0ff0bffdf63657 X-Google-Attributes: gidf43e6,public X-Google-Thread: 103376,4b06f8f15f01a568 X-Google-Attributes: gid103376,public X-Google-Thread: 1108a1,9a0ff0bffdf63657 X-Google-Attributes: gid1108a1,public From: jtc@dimensional.com (Jim Cochrane) Subject: Re: Software landmines (loops) Date: 1998/09/08 Message-ID: <6t4dmi$rhp@flatland.dimensional.com>#1/1 X-Deja-AN: 389198927 References: <35f51e53.480 <904556531.66622 Organization: Dimensional Communications NNTP-Posting-Date: Tue, 08 Sep 1998 17:13:41 MDT Newsgroups: comp.lang.eiffel,comp.object,comp.software-eng,comp.lang.ada Date: 1998-09-08T00:00:00+00:00 List-Id: Of course, if the conditions being checked in the code below are really pre-conditions - that is, it can be considered a coding error that the function is called with one of these conditions true, then it would be better coded as: void Worker::do_something (Tree *top) { assert (top != NULL && top->child != NULL && ...); _error_code = really_do_something(top->child...->child); if (_error_code != 0) // or whatever value means non-error { _error_occurred = true; } else { _error_occurred = false; } } Where the assertion would be documented as a pre-condition of the function specification. Then a client would do: // ensure the pre-condition for root worker.do_something (root); if (worker.error_occurred()) { //report/handle the error with worker.error_code() ... } [Changed to an OO style, since the discussion is occurring on OO newsgroups.] The difference, of course, is that the checking for null pointers becomes part of the function specification rather than being explicitely coded (the assertion will probably be turned of in the production release). This is the difference between design by contract and defensive coding. In article , wrote: > > >This is a response to several articles in different subthreads, so >you might not have seen some of the quoted articles on your way here... > > ... >Although many people may have been taught about Structured Programming, >and the importance of single entry and single exit points for program >proving and testing, there are often times when other factors - shall I >say "political" rather than technical - come into play. > >For example, I once worked on a C project where se/se was the be-all >and end-all of the technical factors, with the testing for errors at >every point coming in a close second. As the system consisted of 7 >sub-systems all communicating via shared memory there was the risk >that although the logic in one system would preclude future errors, >this couldn't be guaranteed in general. The data was organised in >huge tree structures, all linked by pointers. Therefore, each routine >always did "redundant" testing: > >int doSomething(Tree *pTop) >{ > int errorCode; > > if (pTop != NULL) > { > if (pTop->pChild != NULL) > { > if (pTop->pChild->pChild != NULL) > { > /* lots of nesting omitted */ > > if (pTop->pChild...->pChild != NULL) > { > errorCode = reallyDoSomething(pTop->pChild...->pChild); > } else > { > errorCode = ERRORX; > } else > { > errorCode = ERROR3; > } > } else > { > errorCode = ERROR2; > } > } else > { > errorCode = ERROR1; > } > return(errorCode); >} > -- Jim Cochrane jtc@dimensional.com