473,805 Members | 2,074 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

if clause

Hello,

i have a question about "design" issues in C.

In ACMqueue of february
(article here:
http://www.acmqueue.org/modules.php?...owpage&pid=364
), KV says:
A dangerous if clause is one in which the code you want to protect
with the if isn't really protected. Consider the following pseudocode:

0: if (out < 0)
1: return (fileError)
2:
3: if (permission < operator)
4: return (permissionErro r)
5:
6: if (data.len() <= 0)
7: return (dataError)
8:
9: write(out, data, data.len)

(...)
The reason that all the if statements were added was to protect
the program from calling the write() function when there was
a problem, so the code should be structured in just that way:

0: if ((out >= 0) && (permission >= operator) && (data.len() 0))
1: write(out, data, data.len)
2: // Put all the error condition returns here.
In my mind, man can argue with the latter code, man has to copy the error
checks
and have twice the same code. What do you thinks about this code snippet?
Thanks for your replies,

rogz
Oct 30 '06
27 5388
Ancient_Hacker wrote:
rogz wrote:
>>0: if (out < 0)
1: return (fileError)
2:
3: if (permission < operator)
4: return (permissionErro r)
5:
6: if (data.len() <= 0)
7: return (dataError)
8:
9: write(out, data, data.len)


There are several disparate issues with this code and the original
writer wasnt very good at pointing them out. Here's my view:

(1) Some people think a function should have just ONE clear exit
point, at the bottom. I realize that can get a bit long-winded, but it
can make the code MUCH CLEARER, much easier to set breakpoits, much
easier to add code you're SURE will get run every time. Multiple entry
points went out with FORTRAN II, why do we still have multiple exit
points in this 21sh century?
This is certainly a common opinion, but the code I maintain embraced the
other approach: if you have special cases while setting up the main meat
of the function that suggest that continuing makes no sense, then bail
out early.

We have a whole runtime-enabled logger system so, as long as you log the
entry and exit, debugging is easy and the code is easy to read.

Once we get into the main logic for the function we usually have the
usual assortment of breaks to ensure that there is only one more exit
point to be had.

The other approach I've seen is to have all the special cases handled by
a number of "goto early" or "goto error", where the return is normalized
and control short-circuited to the exit point.

All of these approaches make sense under the right circumstances, but
this maintenance drone prefers code that can be easily read,
top-to-bottom, to figure out what it is *supposed* to do so the bugs are
easier to find.

Freeing up my cognitive energy by being able to discard early control
paths as I go really helps me solve some obscure problems. It also
allows one to say with accuracy that some variable or parameter is in
some known range (e.g., some value is or is not null, or some parameter
cannot possibly be 0, &etc.) after some specific point.

I'm speaking as someone who might not be able to run a debugger on live
code (I maintain chunks that are compiled with older compilers that have
crufty debuggers that don't run on later releases of Windows, for example).
Oct 30 '06 #11
On 30 Oct 2006 06:17:28 -0800, "Ancient_Hacker " <gr**@comcast.n et>
wrote:
>(1) Some people think a function should have just ONE clear exit
point, at the bottom. I realize that can get a bit long-winded, but it
can make the code MUCH CLEARER, much easier to set breakpoits, much
easier to add code you're SURE will get run every time. Multiple entry
points went out with FORTRAN II, why do we still have multiple exit
points in this 21sh century?
Because in some circumstances, it makes the code much clearer, much
easier to set breakpoints, and much easier to add code to individual
tests.

IOW, "some people" are not always right. In the example given, I would
prefer the form presented as a bad example :-)

BTW, what do multiple entry points have to do with multiple exit
points?

--
Al Balmer
Sun City, AZ
Oct 30 '06 #12
Michal Nazarewicz wrote:
>>>0: if (out < 0)
1: return (fileError)
2:
3: if (permission < operator)
4: return (permissionErro r)
5:
6: if (data.len() <= 0)
7: return (dataError)
8:
9: write(out, data, data.len)
Makes me feel uncomfortable
>
"Ancient_Hacker " <gr**@comcast.n etwrites:
>(1) Some people think a function should have just ONE clear exit
point, at the bottom. I realize that can get a bit long-winded, but it
can make the code MUCH CLEARER,
I agree totally, especially when maintaining code that has grown to a
hundred lines per function.
>
Or much less clear when it comes into nesting ifs which, IMO, is less
readable then returning when error condition occurs.
which is why I prefer "exceptions first with else if" or goto error exit
>
>much easier to set breakpoits, much
easier to add code you're SURE will get run every time. Multiple entry
points went out with FORTRAN II, why do we still have multiple exit
points in this 21sh century?

I believe, I've heard about some research showing that programmers
tend to make less errors when they are allowed to use 'break' - maybe
the same goes to multiple exit points.
>Now to get just one exit point TAKES A LITTLE MORE WORK and a little
more nesting or use of "break".

Isn't "break" really cheating? Like in:

#v+
answer;
do {
some stuff;
if (error 1) {
answer = error1;
break;
}
some stuff();
if (error 2) {
answer = error2;
break;
}
some stuff;
if (error 1) {
answer = error2;
break;
}
some stuff;
answer = success;
} while (0);
return answer;
#v-
I would say yes, since it can easily be handled with a reasonable amount of
indenting (and if it can't then it's time to consider two smaller
functions)
>
It looks just like the same function with many exit points but
uglier.

Just showing my point of view though.

>Personally I'm a nervous nelly and won't use "break" (see ATT $400
million looss due to the vagaries of "break"). So I end up with
code like the stuff below. Your opinion may vary. :

ErrorType Answer;
if( out >= 0 ) {
if( permission >= operator ) {
if( data.len 0 ) {
Answer = write( ....) 0;
} else Answer = BADLEN;
}
else Answer = BADPERMS;
} else Answer = BADOUT

return Answer;
For that depth that would satisfy me
>
Why not:

#v+
ErrorType Answer;
if (out<0) {
Answer = BADOUT
} else if (permission<ope rator) {
Answer = BADPERMS;
} else if (data.len<=0) {
Answer = BADLEN;
} else {
Answer = write(...) 0;
}
return Answer;
#v-
although I prefer that
>
And then, of course, since I prefer data-oriented to process-oriented, there
is
Answer = out < 0 ? BADOUT :
permission < operator ? BADPERMS :
data.len() <= 0 ? BADLEN :
write(...) <= 0 ? BADWRITE :
SUCCESS;
--
Bill Medland
Oct 30 '06 #13
Ancient_Hacker wrote:
>
(1) Some people think a function should have just ONE clear exit
point, at the bottom. I realize that can get a bit long-winded, but it
can make the code MUCH CLEARER, much easier to set breakpoits, much
easier to add code you're SURE will get run every time. Multiple entry
points went out with FORTRAN II, why do we still have multiple exit
points in this 21sh century?
Because there's one reason to enter a function ("Do this
specified thing") but many reasons the function might not be
able to do its job ("Logarithm of negative number" or "File
not found" or "Inauspicio us lunar phase").

Even the "not do its job" part is suspect: Some functions
can succeed in multiple different ways. "Item was present in
hash table" or "Item was not present but was inserted" or
"New file opened for output" or "Old file erased and truncated
to zero length, now ready for output."

Insisting that all modes of failure and all modes of success
must somehow filter down to one great holy return statement is
not good practice, but monotheism run rampant. "Thou shalt have
no RETURN before Me" -- pfui!

--
Eric Sosman
es*****@acm-dot-org.invalid
Oct 31 '06 #14
Eric Sosman said:

<snip>
>
Insisting that all modes of failure and all modes of success
must somehow filter down to one great holy return statement is
not good practice, but monotheism run rampant. "Thou shalt have
no RETURN before Me" -- pfui!
Pfui schmui. This isn't about religion, but about clarity. If we can write
the code in a way that a maintenance droid will be able to understand
easily in five years' time, then that's a Good Thing. Personally, I find
code easier to understand if it doesn't arbitrarily leap off a cliff under
certain conditions, at apparently random intervals.

The thing that put me off multiple returns was not success/failure -
bail-out code is easy to understand, and the only caveat is "was it a clean
failure?" (e.g. let's remember to clean up memory, close any files that
shouldn't be open if the operation failed, etc etc). Rather, it was when I
was having to modify long-winded financial calculations that had return
statements sprinkled liberally through the (oversized) function.
Unravelling the "let's squeeze the last nanosecond out of this mainframe"
code so that I could do the mod properly was an exercise in torture. And
one of the worst culprits was this "oh, look, we're in six levels of loop,
this seems a suitably arbitrary place, so let's return the value of this
badly named variable. Or perhaps we should wait until we get to the next
loop, where we can return the value of an *even more* badly named
variable!"

I wouldn't want to put anyone through that. So I don't.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Oct 31 '06 #15
Richard Heathfield wrote:
Eric Sosman said:

<snip>
>>
Insisting that all modes of failure and all modes of success
must somehow filter down to one great holy return statement is
not good practice, but monotheism run rampant. "Thou shalt have
no RETURN before Me" -- pfui!

Pfui schmui. This isn't about religion, but about clarity. If we can write
the code in a way that a maintenance droid will be able to understand
easily in five years' time, then that's a Good Thing. Personally, I find
code easier to understand if it doesn't arbitrarily leap off a cliff under
certain conditions, at apparently random intervals.

The thing that put me off multiple returns was not success/failure -
bail-out code is easy to understand, and the only caveat is "was it a clean
failure?" (e.g. let's remember to clean up memory, close any files that
shouldn't be open if the operation failed, etc etc). Rather, it was when I
was having to modify long-winded financial calculations that had return
statements sprinkled liberally through the (oversized) function.
Unravelling the "let's squeeze the last nanosecond out of this mainframe"
code so that I could do the mod properly was an exercise in torture. And
one of the worst culprits was this "oh, look, we're in six levels of loop,
this seems a suitably arbitrary place, so let's return the value of this
badly named variable. Or perhaps we should wait until we get to the next
loop, where we can return the value of an *even more* badly named
variable!"

I wouldn't want to put anyone through that. So I don't.
Arguing that X is bad because you've seen bad examples of X isn't
very convincing, unless you can show that there are no /good/
examples of X.

The code you describe apparently fails the clarity test in at least
two other ways. (fx:assert) Code that /didn't/ fail those clarity
tests and used multiple returns can still be clear.

--
Chris "hashed up hashing" Dollin
"Who are you? What do you want?" /Babylon 5/

Oct 31 '06 #16
Chris Dollin said:
Richard Heathfield wrote:
<snip>
>>
The thing that put me off multiple returns was [...]

I wouldn't want to put anyone through that. So I don't.

Arguing that X is bad because you've seen bad examples of X isn't
very convincing, unless you can show that there are no /good/
examples of X.
I'm not trying to argue that X is bad. I'm just pointing out that in *my*
experience I find X hard to maintain in general terms, and consequently I
don't like to inflict X on other people (including myself). Clarity takes
precedence over religion.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Oct 31 '06 #17
Richard Heathfield wrote:
Chris Dollin said:
>Richard Heathfield wrote:
<snip>
>>>
The thing that put me off multiple returns was [...]

I wouldn't want to put anyone through that. So I don't.

Arguing that X is bad because you've seen bad examples of X isn't
very convincing, unless you can show that there are no /good/
examples of X.

I'm not trying to argue that X is bad. I'm just pointing out that in *my*
experience I find X hard to maintain in general terms, and consequently I
don't like to inflict X on other people (including myself). Clarity takes
precedence over religion.
I think we agree on that last sentence. And, in practice, I suspect
our code might be more alike than disputes like this might suggest.

Is "Clarity takes precedence over religion." a religion?

--
Chris "(fx:quack) diagonal" Dollin
"We did not have time to find out everything we wanted to know."
- James Blish, /A Clash of Cymbals/

Oct 31 '06 #18
Chris Dollin said:
Richard Heathfield wrote:
<snip>
>Clarity takes precedence over religion.

I think we agree on that last sentence. And, in practice, I suspect
our code might be more alike than disputes like this might suggest.
I suspect you're right. All well-maintained roads lead to clarity.
Is "Clarity takes precedence over religion." a religion?
It's not clear.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Oct 31 '06 #19
Ancient_Hacker wrote:
Multiple entry points went out with FORTRAN II, why do we still have
multiple exit points in this 21sh century?
One can use setjmp() and longjmp() to create multiple entry points.

Or is that different?
Oct 31 '06 #20

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
11511
by: malcolm | last post by:
Example, suppose you have these 2 tables (NOTE: My example is totally different, but I'm simply trying to setup the a simpler version, so excuse the bad design; not the point here) CarsSold { CarsSoldID int (primary key) MonthID int DealershipID int NumberCarsSold int
2
2364
by: aj70000 | last post by:
This is my query select ano,max(date),a_subject from MY_TAB where table_name='xyz' and ano=877 group by a_subject,ano order by a_subject ANO max(Date) A_Subject 877 2005-01-20 00:00:00.000 Subject_1 877 1900-01-01 00:00:00.000 Subject_2 877 2004-12-20 00:00:00.000 Subject_3
7
2755
by: JJ_377 | last post by:
Can someone tell me why SQL seems to ignore my order by clause? I tried to run through the debugger, but the debugger stops at the select statement line and then returns the result set; so, I have no idea how it is evaluating the order by clause. THANK YOU! CREATE proc sprAllBooks @SortAscend varchar(4), @SortColumn varchar(10)
27
4721
by: Chris, Master of All Things Insignificant | last post by:
I have come to greatly respect both Herfried & Cor's reponses and since the two conflicted, I wanted to get some clarification. My orginal post: Herfried, maybe your example here can get you to answer a question I've wondered about for a while. With Me.Label1 .Text = ... .Refresh()
3
1870
by: Sean Shanny | last post by:
To all, We are running postgresql 7.4.1 on an G5 with dual procs, OSX 10.3.3 server, 8GB mem, attached to a fully configured 3.5TB XRaid box via fibre channel. I think we have run into this issue before but I thought the code was fixed. :-( I have the following SQL:
26
17216
by: GreatAlterEgo | last post by:
Hi, This is my query which is embedded in a COBOL program. EXEC SQL SELECT DATE, AGE, DURATION, AMT INTO :LDATE, :L.AGE, :L.DURATION, :L.AMT FROM TAB1 WHERE CODE = :KEY.CODE AND SET = :KEY.SET AND DATE <= :KEY.DATE
25
1879
by: metaperl.etc | last post by:
A very old thread: http://groups.google.com/group/comp.lang.python/browse_frm/thread/2c5022e2b7f05525/1542d2041257c47e?lnk=gst&q=for+else&rnum=9#1542d2041257c47e discusses the optional "else:" clause of the for statement. I'm wondering if anyone has ever found a practical use for the else branch?
2
10760
by: Jim.Mueksch | last post by:
I am having a problem with using calculated values in a WHERE clause. My query is below. DB2 gives me this error message: Error: SQL0206N "APPRAISAL_LESS_PRICE" is not valid in the context where it is used. SQLSTATE=42703 SELECT DISTINCT S3.OPR_APPLICATION_NR, S3.APPLICATION_ID, S3.APPRAISAL_TYPE_CD, S3.Appraisal_Used_Amount, S3.RPT_LEVEL2_NR,
5
2666
by: pwiegers | last post by:
Hi, I'm trying to use the result of a conditional statement in a where clause, but i'm getting 1)nowhere 2) desperate :-) The query is simple: -------- SELECT idUser, (@ageraw:=YEAR(CURRENT_DATE()) - YEAR(dateofbirth) -
6
3110
by: jackal_on_work | last post by:
Hi Faculties, I have two queries which give me the same output. -- Query 1 SELECT prod.name, cat.name FROM products prod INNER JOIN categories cat ON prod.category_id = cat.id WHERE cat.id = 1;
0
9596
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10613
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9186
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7649
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5544
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5678
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4327
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3846
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
3008
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.