Deutsch   English   Français   Italiano  
<vgnfnd$3nmui$1@dont-email.me>

View for Bookmarking (what is this?)
Look up another Usenet article

Path: ...!weretis.net!feeder9.news.weretis.net!news.quux.org!eternal-september.org!feeder2.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: David Brown <david.brown@hesbynett.no>
Newsgroups: comp.lang.c
Subject: Re: else ladders practice
Date: Sat, 9 Nov 2024 12:06:21 +0100
Organization: A noiseless patient Spider
Lines: 91
Message-ID: <vgnfnd$3nmui$1@dont-email.me>
References: <3deb64c5b0ee344acd9fbaea1002baf7302c1e8f@i2pn2.org>
 <vg0t3j$2ruor$1@dont-email.me>
 <78eabb4054783e30968ae5ffafd6b4ff2e5a5f17@i2pn2.org>
 <vg2g37$37mh3$1@dont-email.me> <6724CFD2.4030607@grunge.pl>
 <vg2llt$38ons$1@dont-email.me>
 <2491a699388b5891a49ef960e1ad8bb689fdc2ed@i2pn2.org>
 <b681ee05856e165c26a5c29bf42a8d9d53843d6d@i2pn2.org>
 <vg2ttn$3a4lk$1@dont-email.me> <vg33gs$3b8n5$1@dont-email.me>
 <vg358c$3bk7t$1@dont-email.me> <vg37nr$3bo0c$1@dont-email.me>
 <vg3b98$3cc8q$1@dont-email.me> <vg5351$3pada$1@dont-email.me>
 <vg62vg$3uv02$1@dont-email.me> <vg8a84$euka$1@dont-email.me>
 <vg8koq$gpsg$1@dont-email.me> <vgat50$112jp$1@dont-email.me>
 <vgb8if$13ioj$1@dont-email.me> <vgbhkt$155v2$1@dont-email.me>
 <vgn0vl$3kr82$1@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Sat, 09 Nov 2024 12:06:22 +0100 (CET)
Injection-Info: dont-email.me; posting-host="459e4b97cad4e99e231618c7734617ff";
	logging-data="3922898"; mail-complaints-to="abuse@eternal-september.org";	posting-account="U2FsdGVkX1+BtUO4xsUE27HPMkj9RxnVU1mXOE6CvrI="
User-Agent: Mozilla Thunderbird
Cancel-Lock: sha1:M8XzdcBGQMILJqp3/Y+LLMnuTt4=
In-Reply-To: <vgn0vl$3kr82$1@dont-email.me>
Content-Language: en-GB
Bytes: 6144

On 09/11/2024 07:54, Janis Papanagnou wrote:
> On 04.11.2024 23:25, David Brown wrote:
>>
>> If you have a function (or construct) that returns a correct value for
>> inputs 1, 2 and 3, and you never pass it the value 4 (or anything else),
>> then there is no undefined behaviour no matter what the code looks like
>> for values other than 1, 2 and 3.  If someone calls that function with
>> input 4, then /their/ code has the error - not the code that doesn't
>> handle an input 4.
> 
> Well, it's a software system design decision whether you want to
> make the caller test the preconditions for every function call,
> or let the callee take care of unexpected input, or both.
> 

Well, I suppose it is their decision - they can do the right thing, or 
the wrong thing, or both.

I believe I explained in previous posts why it is the /caller's/ 
responsibility to ensure pre-conditions are fulfilled, and why anything 
else is simply guaranteeing extra overheads while giving you less 
information for checking code correctness.  But I realise that could 
have been lost in the mass of posts, so I can go through it again if you 
want.


(On security boundaries, system call interfaces, etc., where the caller 
could be malicious or incompetent in a way that damages something other 
than their own program, you have to treat all inputs as dangerous and 
sanitize them, just like data from external sources.  That's a different 
matter, and not the real focus here.)



> We had always followed the convention to avoid all undefined
> situations and always define every 'else' case by some sensible
> behavior, at least writing a notice into a log-file, but also
> to "fix" the runtime situation to be able to continue operating.
> (Note, I was mainly writing server-side software where this was
> especially important.)

You can't "fix" bugs in the caller code by writing to a log file. 
Sometimes you can limit the damage, however.

If you can't trust the people writing the calling code, then that should 
be the focus of your development process - find a way to be sure that 
the caller code is right.  That's where you want your conventions, or to 
focus code reviews, training, automatic test systems - whatever is 
appropriate for your team and project.  Make sure callers pass correct 
data to the function, and the function can do its job properly.

Sometimes it makes sense to specify functions differently, and accept a 
wider input.  Maybe instead of saying "this function will return the 
integer square root of numbers between 0 and 10", you say "this function 
will return the integer square root if given a number between 0 and 10, 
and will log a message and return -1 for other int values".  Fair enough 
- now you've got a new function where it is very easy for the caller to 
ensure the preconditions are satisfied.  But be very aware of the costs 
- you have now destroyed the "purity" of the function, and lost the key 
mathematical relation between the input and output.  (You have also made 
everything much less efficient.)

In terms of development practices, for large code bases you should 
divide things up into modules with clear boundaries.  And then you might 
say that the teams working on other modules that call yours are muppets 
that can't read a function specification and can't get their code right. 
  So these boundary functions have to accept as wide a range of inputs 
as possible, and check them as well as possible.  But you only do that 
for these externally accessible interfaces, not your internal code.

> 
> That's one reason why (as elsethread mentioned) I dislike 'else'
> to handle a defined value; I prefer an explicit 'if' and use the
> else for reporting unexpected situations (that practically never
> appear, or, with the diagnostics QA-evaluated, asymptotically
> disappearing).
> 
> (For pure binary predicates there's no errors branch, of course.)
> 
> Janis
> 
> PS: One of my favorite IT-gotchas is the plane crash where the
> code specified landing procedure functions for height < 50.0 ft
> and for height > 50.0 ft conditions, which mostly worked since
> the height got polled only every couple seconds, and the case
> height = 50.0 ft happened only very rarely due to the typical
> descent characteristics during landing.
>