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: duncan@yc.estec.esa.nlx Subject: Re: Software landmines (loops) Date: 1998/09/09 Message-ID: #1/1 X-Deja-AN: 389325020 Sender: duncan@yc.estec.esa.nlx References: <904556531.66622 <6t4dmi$rhp@flatland.dimensional.com> Organization: ESA/ESTEC/YC, Noordwijk, The Netherlands Newsgroups: comp.lang.eiffel,comp.object,comp.software-eng,comp.lang.ada Date: 1998-09-09T00:00:00+00:00 List-Id: In article <6t4dmi$rhp@flatland.dimensional.com>, Jim Cochrane wrote: >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. The first 'Commandments' for coding were: 1. Thou shalt use single entry/single exit routines. 2. Thou shalt guarantee all pointers before dereferencing. As mentioned before, the system was made up of 7 sub-systems, all running as separate processes, and communicating via shared memory. Hence there was a lot of 'redundant' checking. Yes, you could use 'assert' but seeing as the error checking had to go into the production code anyway, there was little point. Yes, the pre-conditions could have been checked before the routine was actually called, but now you have moved knowledge of where in the tree data structure the relevant information lives into the caller. When you consider that some of the paths through the tree involved following 6 or more pointers, that's a lot of encapsulation and data hiding that has been lost. All of the code for determining which error has occurred has also been moved from the routine to the caller... These are all tradeoffs that need to be made. I believe that there are various 'good practices' which should be included in an ideal world, but until I find employment in the ideal world, it's going to be a case of making these tradeoffs, and some of the 'good practices' may not be applied in all cases. Of course it helps if you are aware of the 'good practices' in the first place so that you know what you are missing. Cheers Duncan This is my article, not my employer's, with my opinions and my disclaimer! -- Duncan Gibson, ESTEC/YCV, Postbus 299, 2200AG Noordwijk, The Netherlands Tel: +31 71 5654013 Fax: +31 71 5656142 Email: duncan@yc.estec.esa.nlx To avoid junk email my quoted address is incorrect. Use nl instead of nlx.