By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,946 Members | 697 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,946 IT Pros & Developers. It's quick & easy.

Code style musing - eliminating double negatives.

P: n/a
I often come up with logic like this somewhere in a function:

....
If Not IsNull(<some expression>) Then
<default action>
Else
<alternative action>
End If
....

That If Not IsNull ... Else thing makes the code awkward to read, so my next
thought is to swap it around like this:

....
If IsNull(<some expression>) Then
<alternative action>
Else
<default action>
End If
....

Now, though, the alternative action is listed first, followed by the default
action which is also awkward to read. Next, I'm thinking I should write a
function with a positive name that evaluates Not IsNull(<Expression>), and I
still think that's a good idea, but what to call such a beast?

If I call it NotNull(), that doesn't help my double-negative legibility
situation much, it just turns a 2-word double-negative into a 1-word
double-negative. If I call it HasValue, the name is unclear because of all
the available kinds of Nothing? When reading the code, how do you know if
this is suppoed to mean Not Null, Not "", not Empty, not Missing, or some
hybrid of the above? To change that name to make it specific, I again seem to
be just replaying the double negative case, eg. HasNonNullValue, and the name
is getting longer as well.

I realize this seems like an awfully trivial topic for discussion, but it's
one of those little itches in the middle of my mind's back that I've been
having to live with for ages now.
Nov 12 '05 #1
Share this Question
Share on Google+
28 Replies


P: n/a
It just boils down to potatoes - potawtoes dosen't it?
You could probably find a way eliminate double-negatives, after spending an
inordinate amount of time and exponentially increasing your function names,
or you could just add a really clear comment next to it.

Mike Storr
www.veraccess.com

"Steve Jorgensen" <no****@nospam.nospam> wrote in message
news:km********************************@4ax.com...
I often come up with logic like this somewhere in a function:

...
If Not IsNull(<some expression>) Then
<default action>
Else
<alternative action>
End If
...

That If Not IsNull ... Else thing makes the code awkward to read, so my next thought is to swap it around like this:

...
If IsNull(<some expression>) Then
<alternative action>
Else
<default action>
End If
...

Now, though, the alternative action is listed first, followed by the default action which is also awkward to read. Next, I'm thinking I should write a
function with a positive name that evaluates Not IsNull(<Expression>), and I still think that's a good idea, but what to call such a beast?

If I call it NotNull(), that doesn't help my double-negative legibility
situation much, it just turns a 2-word double-negative into a 1-word
double-negative. If I call it HasValue, the name is unclear because of all the available kinds of Nothing? When reading the code, how do you know if
this is suppoed to mean Not Null, Not "", not Empty, not Missing, or some
hybrid of the above? To change that name to make it specific, I again seem to be just replaying the double negative case, eg. HasNonNullValue, and the name is getting longer as well.

I realize this seems like an awfully trivial topic for discussion, but it's one of those little itches in the middle of my mind's back that I've been
having to live with for ages now.

Nov 12 '05 #2

P: n/a
Sure, but the point is that I hit this problem hundreds of times in a typical
mid-sized app, and I do many of those per year. That's a lot of itching that
could be relieved if I could come up with a general answer.

Also, I feel good comments are essential much of the time, but comments are
what you write when you couldn't think of a way to make the code
self-explanatory. I always try first to make the code as self-explanatory as
possible, then add what remaining comments are still required.

On Tue, 20 Jan 2004 22:37:19 -0500, "Mike Storr" <st******@sympatico.ca>
wrote:
It just boils down to potatoes - potawtoes dosen't it?
You could probably find a way eliminate double-negatives, after spending an
inordinate amount of time and exponentially increasing your function names,
or you could just add a really clear comment next to it.

Mike Storr
www.veraccess.com

"Steve Jorgensen" <no****@nospam.nospam> wrote in message
news:km********************************@4ax.com.. .
I often come up with logic like this somewhere in a function:

...
If Not IsNull(<some expression>) Then
<default action>
Else
<alternative action>
End If
...

That If Not IsNull ... Else thing makes the code awkward to read, so my

next
thought is to swap it around like this:

...
If IsNull(<some expression>) Then
<alternative action>
Else
<default action>
End If
...

Now, though, the alternative action is listed first, followed by the

default
action which is also awkward to read. Next, I'm thinking I should write a
function with a positive name that evaluates Not IsNull(<Expression>), and

I
still think that's a good idea, but what to call such a beast?

If I call it NotNull(), that doesn't help my double-negative legibility
situation much, it just turns a 2-word double-negative into a 1-word
double-negative. If I call it HasValue, the name is unclear because of

all
the available kinds of Nothing? When reading the code, how do you know if
this is suppoed to mean Not Null, Not "", not Empty, not Missing, or some
hybrid of the above? To change that name to make it specific, I again

seem to
be just replaying the double negative case, eg. HasNonNullValue, and the

name
is getting longer as well.

I realize this seems like an awfully trivial topic for discussion, but

it's
one of those little itches in the middle of my mind's back that I've been
having to live with for ages now.


Nov 12 '05 #3

P: n/a
On Wed, 21 Jan 2004 02:13:06 GMT, Steve Jorgensen
<no****@nospam.nospam> wrote:

Personally I'm not too concerned with which action comes first.
For example I'll happily write:
if rs.recordcount=0 then
' do this
else
'do that
end if

or

if rs.eof then
' do this
else
'do that
end if

or

if isnull(myfunction()) then
' do this
else
'do that
end if
I don't know who came up with the idea that the "common" action has to
occur first, and the exception after that. I'm not bothered by the
reverse, but like you I *am* bothered by double negatives.

-Tom.
I often come up with logic like this somewhere in a function:

...
If Not IsNull(<some expression>) Then
<default action>
Else
<alternative action>
End If
...

That If Not IsNull ... Else thing makes the code awkward to read, so my next
thought is to swap it around like this:

...
If IsNull(<some expression>) Then
<alternative action>
Else
<default action>
End If
...

Now, though, the alternative action is listed first, followed by the default
action which is also awkward to read. Next, I'm thinking I should write a
function with a positive name that evaluates Not IsNull(<Expression>), and I
still think that's a good idea, but what to call such a beast?

If I call it NotNull(), that doesn't help my double-negative legibility
situation much, it just turns a 2-word double-negative into a 1-word
double-negative. If I call it HasValue, the name is unclear because of all
the available kinds of Nothing? When reading the code, how do you know if
this is suppoed to mean Not Null, Not "", not Empty, not Missing, or some
hybrid of the above? To change that name to make it specific, I again seem to
be just replaying the double negative case, eg. HasNonNullValue, and the name
is getting longer as well.

I realize this seems like an awfully trivial topic for discussion, but it's
one of those little itches in the middle of my mind's back that I've been
having to live with for ages now.


Nov 12 '05 #4

P: n/a
On Tue, 20 Jan 2004 22:11:01 -0700, Tom van Stiphout <to*****@no.spam.cox.net>
wrote:
....
I don't know who came up with the idea that the "common" action has to
occur first, and the exception after that. I'm not bothered by the
reverse, but like you I *am* bothered by double negatives.

-Tom.


Well, it's nothing anyone told me. It just seems like an obvious thing to me
that the default action should come first.

When reading the code, you want to see what the code is normally supposed to
do, not the exceptional case. Reversing it just makes it harder to see at a
glance what the primary activity of the procedure is. You then have to find
the point in the middle of the code where the standard case starts.
Nov 12 '05 #5

P: n/a
I don't want to not disagree, but triple negatives are worse!
--
Danny J. Lesandrini
Nov 12 '05 #6

P: n/a
"Steve Jorgensen" wrote
I realize this seems like an awfully trivial topic for discussion, but it's
one of those little itches in the middle of my mind's back that I've been
having to live with for ages now.


Also consider those if statements where the condition can
evaluate to Null. If it does, the else-part will be executed.
This may add to the confusion - some discipline is needed
It's my habit to boldly eliminate double negatives unless
Null-handling prevents it - even if Null cannot occur in that
particular statement.
Nov 12 '05 #7

P: n/a
On Tue, 20 Jan 2004 22:28:31 -0700, "Danny J. Lesandrini"
<dl*********@hotmail.com> wrote:
I don't want to not disagree, but triple negatives are worse!


Probably so.
Nov 12 '05 #8

P: n/a
On Wed, 21 Jan 2004 02:13:06 GMT in comp.databases.ms-access, Steve
Jorgensen <no****@nospam.nospam> wrote:
I often come up with logic like this somewhere in a function:

...
If Not IsNull(<some expression>) Then
<default action>
Else
<alternative action>
End If
...

That If Not IsNull ... Else thing makes the code awkward to read, so my next
thought is to swap it around like this:

...
If IsNull(<some expression>) Then
<alternative action>
Else
<default action>
End If
...

Now, though, the alternative action is listed first, followed by the default
action which is also awkward to read. Next, I'm thinking I should write a
function with a positive name that evaluates Not IsNull(<Expression>), and I
still think that's a good idea, but what to call such a beast?

If I call it NotNull(), that doesn't help my double-negative legibility
situation much, it just turns a 2-word double-negative into a 1-word
double-negative. If I call it HasValue, the name is unclear because of all
the available kinds of Nothing? When reading the code, how do you know if
this is suppoed to mean Not Null, Not "", not Empty, not Missing, or some
hybrid of the above? To change that name to make it specific, I again seem to
be just replaying the double negative case, eg. HasNonNullValue, and the name
is getting longer as well.

I realize this seems like an awfully trivial topic for discussion, but it's
one of those little itches in the middle of my mind's back that I've been
having to live with for ages now.


One of the most annying things some of my collegues do is not use the
NOT keyword and code thus:

if <condidtion> then
else
.. do something
end if

it could be re-written as:

if not <condition> then
.. do something
end if

Then of course someone comes along later and thinks of doing something
for the true condition.

As for NotNull(), an antonym for null is "Valid" but IsValid() would
be a bit ambiguous I think as an antonym for Valid is Invalid, which
would mean there is data there but is wrong rather than having nothing
there. Perhaps:

If Something() but then that could be confused with being not Nothing
and attributed to an object variable. Perhaps ContainsData()?
--
A)bort, R)etry, I)nfluence with large hammer.
Nov 12 '05 #9

P: n/a
On Wed, 21 Jan 2004 06:36:19 +0100 in comp.databases.ms-access, "Paul"
<ka*****@myprovider.nl.invalid> wrote:
"Steve Jorgensen" wrote
I realize this seems like an awfully trivial topic for discussion, but it's
one of those little itches in the middle of my mind's back that I've been
having to live with for ages now.


Also consider those if statements where the condition can
evaluate to Null. If it does, the else-part will be executed.
This may add to the confusion - some discipline is needed
It's my habit to boldly eliminate double negatives unless
Null-handling prevents it - even if Null cannot occur in that
particular statement.


Oh too true,

a = null
b = 1
if a <> b then
dothis
else
dothat
end if

In the above case, dothat will be executed and you wouldn't expect
dothat to be executed unless a=b, which it doesn't.

Funny I was thinking of Bool and his booleans, only two values but a
third will be returned from an expression, that being null. The funny
part was just now Chris Tarrant mentioned Jake the Peg on the radio
:-)

--
A)bort, R)etry, I)nfluence with large hammer.
Nov 12 '05 #10

P: n/a
"Trevor Best" wrote
Funny I was thinking of Bool and his booleans, only two values but a
third will be returned from an expression, that being null. The funny
part was just now Chris Tarrant mentioned Jake the Peg on the radio


Huh? Are those the colleagues you mentioned that, like me,
prefer to not use NOT?
Nov 12 '05 #11

P: n/a
I agree with Tom partially on this issue. In the case of a double negative,
I am not concerned with which action comes first. I believe placing the
nominal path for the code second to avoid the double negative logic. I only
believe this because double negatives are so difficult to read and I base
this observation on others reading my code when I used double negatives.
Admittedly, only two other programmers have ever had to read my code on a
regular basis so my sample is small. In general, the nominal path should
come first, once again because of readability.

This issue is a 'potato/potawtoes' issue as Mike Storr said earlier. For
example, Steve McConnell in "Code Complete" falls on both sides of the
issue. In chapter 14 section 1 on if statements he says, "Write the nominal
path through the code first; then write the exceptions." And then in
chapter 17 section 1 he says, "In if statements, convert negatives to
positives and flip flop the code in the if and else clauses." In a side
bar write next to that section he cross references chapter 14 he notes the
contradiction and says "decide which is better for your situation."

I don't quote him because I believe he is more authoritative than anyone of
us, I quote him only because his book makes so many thought provoking
suggestions about software construction. I believe if you went carefully
through his bibliography you could find a university study supporting both
points of view, since that was the purpose of his book, to inform us as
programmers about developments in academia that might improve our lot.

I always enjoy reading your posts on coding style and the follow ups.
Thanks, Steve.
--
Jeffrey R. Bailey
"Steve Jorgensen" <no****@nospam.nospam> wrote in message
news:dv********************************@4ax.com...
On Tue, 20 Jan 2004 22:11:01 -0700, Tom van Stiphout <to*****@no.spam.cox.net> wrote:
...
I don't know who came up with the idea that the "common" action has to
occur first, and the exception after that. I'm not bothered by the
reverse, but like you I *am* bothered by double negatives.

-Tom.
Well, it's nothing anyone told me. It just seems like an obvious thing to

me that the default action should come first.

When reading the code, you want to see what the code is normally supposed to do, not the exceptional case. Reversing it just makes it harder to see at a glance what the primary activity of the procedure is. You then have to find the point in the middle of the code where the standard case starts.

Nov 12 '05 #12

P: n/a
no****@nospam.nospam (Steve Jorgensen) wrote in
<km********************************@4ax.com>:
I realize this seems like an awfully trivial topic for discussion,
but it's one of those little itches in the middle of my mind's
back that I've been having to live with for ages now.


I don't worry about the default action coming second.

I always try to make the TRUE part be with the IF and the FALSE
part with the ELSE. I think that's more important than worrying
about the "default" action. Remember that in your example, the
default action is only the default statistically speaking because
of the context in which you run it. That is, in new records, it
wouldn't be the default for a field (which will be Null, unless the
field has a default value), but in existing records it's less
likely. So your idea of "default" is very context-based.

Why wouldn't a comment indicating the default value do the trick?

Of course, why worry about having the TRUE part first in the first
place? I worry about it because my eyes tend to cross when I have
to read double negatives in code (and Boolean operations of any
complexity almost always drive me to creating a truth table to
evaluate them!).

Adding another little bit:

I tend never to write this:

If Not IsNull(<some expression>) Then
[returns a TRUE value]
Else
[returns a FALSE value]
End If

Instead, I'd replace the entire IF/THEN/ELSE structure with a
single line:

[return Not IsNull([expression])]

Sometimes, though, this becomes cryptic enough that it's confusing,
especially when the expression is compound and not easily grasped,
or it's not easy to relate it to the context.

--
David W. Fenton http://www.bway.net/~dfenton
dfenton at bway dot net http://www.bway.net/~dfassoc
Nov 12 '05 #13

P: n/a
no****@nospam.nospam (Steve Jorgensen) wrote in
<sa********************************@4ax.com>:
Also, I feel good comments are essential much of the time, but
comments are what you write when you couldn't think of a way to
make the code self-explanatory. I always try first to make the
code as self-explanatory as possible, then add what remaining
comments are still required.


Hmm. That's not my philosophy of when to include comments. All code
is self-explanatory at some level. I include comments for dumb
programmers who may someday look at my code in the future. Six
months from now, in most cases, I'll be one of those dumb
programmers, and I'm writing those comments not to explain what's
difficult to understand, but to make sure that I don't have to
re-think what is currently bloody obvious to me. My theory is that
the time it takes to type the comment is vastly smaller than the
time it will take me to re-think the logic 6 months from now.

--
David W. Fenton http://www.bway.net/~dfenton
dfenton at bway dot net http://www.bway.net/~dfassoc
Nov 12 '05 #14

P: n/a
bouncer@localhost (Trevor Best) wrote in
<cp********************************@4ax.com>:
One of the most annying things some of my collegues do is not use
the NOT keyword and code thus:

if <condidtion> then
else
.. do something
end if

it could be re-written as:

if not <condition> then
.. do something
end if

Then of course someone comes along later and thinks of doing
something for the true condition.
I always use the IF TRUE ELSE [FALSE] rule, but if there is no
action for the TRUE, I will code only the FALSE case (your
re-written version). I never write empty blocks in control
structures, because that seems to me to be more confusing than
violating the IF TRUE rule.
As for NotNull(), an antonym for null is "Valid" but IsValid()
would be a bit ambiguous I think as an antonym for Valid is
Invalid, which would mean there is data there but is wrong rather
than having nothing there. Perhaps:

If Something() but then that could be confused with being not
Nothing and attributed to an object variable. Perhaps
ContainsData()?


Being an old Paradox hand, I like Is functions, and IsNotNull would
put it close to IsNull in Intellisense. The idea of naming it
IsntNull amuses me, but I'd probably not do it. :)

--
David W. Fenton http://www.bway.net/~dfenton
dfenton at bway dot net http://www.bway.net/~dfassoc
Nov 12 '05 #15

P: n/a
On Wed, 21 Jan 2004 17:25:09 GMT, dX********@bway.net.invalid (David W.
Fenton) wrote:
no****@nospam.nospam (Steve Jorgensen) wrote in
<sa********************************@4ax.com>:
Also, I feel good comments are essential much of the time, but
comments are what you write when you couldn't think of a way to
make the code self-explanatory. I always try first to make the
code as self-explanatory as possible, then add what remaining
comments are still required.


Hmm. That's not my philosophy of when to include comments. All code
is self-explanatory at some level. I include comments for dumb
programmers who may someday look at my code in the future. Six
months from now, in most cases, I'll be one of those dumb
programmers, and I'm writing those comments not to explain what's
difficult to understand, but to make sure that I don't have to
re-think what is currently bloody obvious to me. My theory is that
the time it takes to type the comment is vastly smaller than the
time it will take me to re-think the logic 6 months from now.


I don't disagree with what you're saying, I just think that the most
maintainable code is the code that's the most clear before comments are added.
If there's something that is repeatedly making my code less clear than it
could be, I want to try to fix that, not use comments as a band aid. Pretty
much all code will still need comments, but that'll one less thing that has to
go -in- the comments.
Nov 12 '05 #16

P: n/a
On Wed, 21 Jan 2004 16:53:29 GMT, "Jeffrey R. Bailey"
<Mr******************@yahoo.com> wrote:
I agree with Tom partially on this issue. In the case of a double negative,
I am not concerned with which action comes first. I believe placing the
nominal path for the code second to avoid the double negative logic. I only
believe this because double negatives are so difficult to read and I base
this observation on others reading my code when I used double negatives.
Admittedly, only two other programmers have ever had to read my code on a
regular basis so my sample is small. In general, the nominal path should
come first, once again because of readability.

This issue is a 'potato/potawtoes' issue as Mike Storr said earlier. For
example, Steve McConnell in "Code Complete" falls on both sides of the
issue. In chapter 14 section 1 on if statements he says, "Write the nominal
path through the code first; then write the exceptions." And then in
chapter 17 section 1 he says, "In if statements, convert negatives to
positives and flip flop the code in the if and else clauses." In a side
bar write next to that section he cross references chapter 14 he notes the
contradiction and says "decide which is better for your situation."

I don't quote him because I believe he is more authoritative than anyone of
us, I quote him only because his book makes so many thought provoking
suggestions about software construction. I believe if you went carefully
through his bibliography you could find a university study supporting both
points of view, since that was the purpose of his book, to inform us as
programmers about developments in academia that might improve our lot.
You know, I've never read Code Complete, and I've heard so many good things
about it (2 in the last 2 days). I'll have to get around to that one.
I always enjoy reading your posts on coding style and the follow ups.
Thanks, Steve.


Thanks for the compliment.

Of course, everyone is welcome at this party. If you're interested in style
issues, post your own questions as well.
Nov 12 '05 #17

P: n/a
On Wed, 21 Jan 2004 17:22:52 GMT, dX********@bway.net.invalid (David W.
Fenton) wrote:
no****@nospam.nospam (Steve Jorgensen) wrote in
<km********************************@4ax.com>:
I realize this seems like an awfully trivial topic for discussion,
but it's one of those little itches in the middle of my mind's
back that I've been having to live with for ages now.
I don't worry about the default action coming second.

I always try to make the TRUE part be with the IF and the FALSE
part with the ELSE. I think that's more important than worrying
about the "default" action. Remember that in your example, the


I agree. Of course, I'd rather have my cake and eat it too.
default action is only the default statistically speaking because
of the context in which you run it. That is, in new records, it
wouldn't be the default for a field (which will be Null, unless the
field has a default value), but in existing records it's less
likely. So your idea of "default" is very context-based.
Well, it's more based on what the procedure name implies should be the main
thing going on. It may be that, statistically, in the run-time context, the
alternative is actually far more likely than the default, but I'm not so
concerned with that.
Why wouldn't a comment indicating the default value do the trick?
We'll keep that in the other sub-thread.
Of course, why worry about having the TRUE part first in the first
place? I worry about it because my eyes tend to cross when I have
to read double negatives in code (and Boolean operations of any
complexity almost always drive me to creating a truth table to
evaluate them!).

Adding another little bit:

I tend never to write this:

If Not IsNull(<some expression>) Then
[returns a TRUE value]
Else
[returns a FALSE value]
End If

Instead, I'd replace the entire IF/THEN/ELSE structure with a
single line:

[return Not IsNull([expression])]

Sometimes, though, this becomes cryptic enough that it's confusing,
especially when the expression is compound and not easily grasped,
or it's not easy to relate it to the context.


I'm not sure what you're saying here exactly. I only see how this helps if
what you want to return is just the truth or falseness of the boolean
expression.

That does remind me of one things I have done about the issue in some cases,
though. Even though it adds 2 lines of code, I'll sometimes dimension a
boolean for the result of the expression, then use that in the If statement.
Nov 12 '05 #18

P: n/a
On Wed, 21 Jan 2004 17:30:25 GMT, dX********@bway.net.invalid (David W.
Fenton) wrote:
bouncer@localhost (Trevor Best) wrote in
<cp********************************@4ax.com>:
One of the most annying things some of my collegues do is not use
the NOT keyword and code thus:

if <condidtion> then
else
.. do something
end if

it could be re-written as:

if not <condition> then
.. do something
end if

Then of course someone comes along later and thinks of doing
something for the true condition.


I always use the IF TRUE ELSE [FALSE] rule, but if there is no
action for the TRUE, I will code only the FALSE case (your
re-written version). I never write empty blocks in control
structures, because that seems to me to be more confusing than
violating the IF TRUE rule.


In the cases where the If block encompasses all or most of an entire procedure
body (but only then) you can use a guard clause for these cases.

If (exceptional case expression) Then Exit Sub

or

If (exceptional case expression) Then Go To Clean_Up_And_Exit

Nov 12 '05 #19

P: n/a
no****@nospam.nospam (Steve Jorgensen) wrote in
<pv********************************@4ax.com>:
On Wed, 21 Jan 2004 17:25:09 GMT, dX********@bway.net.invalid
(David W. Fenton) wrote:
no****@nospam.nospam (Steve Jorgensen) wrote in
<sa********************************@4ax.com>:
Also, I feel good comments are essential much of the time, but
comments are what you write when you couldn't think of a way to
make the code self-explanatory. I always try first to make the
code as self-explanatory as possible, then add what remaining
comments are still required.


Hmm. That's not my philosophy of when to include comments. All
code is self-explanatory at some level. I include comments for
dumb programmers who may someday look at my code in the future.
Six months from now, in most cases, I'll be one of those dumb
programmers, and I'm writing those comments not to explain what's
difficult to understand, but to make sure that I don't have to
re-think what is currently bloody obvious to me. My theory is
that the time it takes to type the comment is vastly smaller than
the time it will take me to re-think the logic 6 months from now.


I don't disagree with what you're saying, I just think that the
most maintainable code is the code that's the most clear before
comments are added. If there's something that is repeatedly making
my code less clear than it could be, I want to try to fix that,
not use comments as a band aid. Pretty much all code will still
need comments, but that'll one less thing that has to go -in- the
comments.


I think your rules are, therefore, in conflict with each other when
the TRUE case is not the default. You have to discard one of them,
in that case.

I don't see any issue with that, myself, certainly not enough to
write a set of functions to allow me to avoid having to have a
double negative as the TRUE case.

--
David W. Fenton http://www.bway.net/~dfenton
dfenton at bway dot net http://www.bway.net/~dfassoc
Nov 12 '05 #20

P: n/a
no****@nospam.nospam (Steve Jorgensen) wrote in
<e5********************************@4ax.com>:
On Wed, 21 Jan 2004 17:22:52 GMT, dX********@bway.net.invalid
(David W. Fenton) wrote:
I tend never to write this:

If Not IsNull(<some expression>) Then
[returns a TRUE value]
Else
[returns a FALSE value]
End If

Instead, I'd replace the entire IF/THEN/ELSE structure with a
single line:

[return Not IsNull([expression])]

Sometimes, though, this becomes cryptic enough that it's
confusing, especially when the expression is compound and not
easily grasped, or it's not easy to relate it to the context.


I'm not sure what you're saying here exactly. I only see how this
helps if what you want to return is just the truth or falseness of
the boolean expression.


That's what I said, didn't I? If your IF/THEN/ELSE structure is
only determining whether to return TRUE or FALSE, I simply
eliminate the structure and do it directly.
That does remind me of one things I have done about the issue in
some cases, though. Even though it adds 2 lines of code, I'll
sometimes dimension a boolean for the result of the expression,
then use that in the If statement.


I only use a variable when the test value is needed in more than
one line of code.

--
David W. Fenton http://www.bway.net/~dfenton
dfenton at bway dot net http://www.bway.net/~dfassoc
Nov 12 '05 #21

P: n/a
On Wed, 21 Jan 2004 21:13:46 GMT, dX********@bway.net.invalid (David W.
Fenton) wrote:
no****@nospam.nospam (Steve Jorgensen) wrote in
<pv********************************@4ax.com>:
On Wed, 21 Jan 2004 17:25:09 GMT, dX********@bway.net.invalid
(David W. Fenton) wrote:
no****@nospam.nospam (Steve Jorgensen) wrote in
<sa********************************@4ax.com>:

Also, I feel good comments are essential much of the time, but
comments are what you write when you couldn't think of a way to
make the code self-explanatory. I always try first to make the
code as self-explanatory as possible, then add what remaining
comments are still required.

Hmm. That's not my philosophy of when to include comments. All
code is self-explanatory at some level. I include comments for
dumb programmers who may someday look at my code in the future.
Six months from now, in most cases, I'll be one of those dumb
programmers, and I'm writing those comments not to explain what's
difficult to understand, but to make sure that I don't have to
re-think what is currently bloody obvious to me. My theory is
that the time it takes to type the comment is vastly smaller than
the time it will take me to re-think the logic 6 months from now.


I don't disagree with what you're saying, I just think that the
most maintainable code is the code that's the most clear before
comments are added. If there's something that is repeatedly making
my code less clear than it could be, I want to try to fix that,
not use comments as a band aid. Pretty much all code will still
need comments, but that'll one less thing that has to go -in- the
comments.


I think your rules are, therefore, in conflict with each other when
the TRUE case is not the default. You have to discard one of them,
in that case.

I don't see any issue with that, myself, certainly not enough to
write a set of functions to allow me to avoid having to have a
double negative as the TRUE case.


Well, no one else here seems to have an issue with the order of the default
case either, so perhaps I -am- making a mountain (well, a foothill) out of a
molehill. I also, perhaps, made my original statement of the problem too
narrow since there are other cases besides IsNull where the problem arises.
For instance, the infamous...

Dim rst As DAO.Recordset
....
rst.FindFirst strExpression
If Not rst.Nomatch then
<action if found>
End If
Fortunately, about 1/3 of these cases I see should be turned into guard
clauses anyway...
Dim rst As DAO.Recordset
....
rst.FindFirst strExpression
If rst.Nomatch then Go To Clean_Up_And_Exit
<action if found>
And a good general solution with some side benefits...
Public Function DAOFindInRecordset( _
rst As DAO.Recordset, _
strFindExpr As String _
) As Boolean
If rst.RecordCount=0 Then Exit Function
rst.MoveFirst
rst.FindFirst strFindExpr
DAOFindInRecordset = Not rst.NoMatch
End Function

then

Dim rst As DAO.Recordset
....
if DAOFindInRecordset(rst, strExpression) Then
<action if found>
End If

Nov 12 '05 #22

P: n/a
On Wed, 21 Jan 2004 21:15:55 GMT, dX********@bway.net.invalid (David W.
Fenton) wrote:
no****@nospam.nospam (Steve Jorgensen) wrote in
<e5********************************@4ax.com>:
On Wed, 21 Jan 2004 17:22:52 GMT, dX********@bway.net.invalid
(David W. Fenton) wrote:

I tend never to write this:

If Not IsNull(<some expression>) Then
[returns a TRUE value]
Else
[returns a FALSE value]
End If

Instead, I'd replace the entire IF/THEN/ELSE structure with a
single line:

[return Not IsNull([expression])]

Sometimes, though, this becomes cryptic enough that it's
confusing, especially when the expression is compound and not
easily grasped, or it's not easy to relate it to the context.


I'm not sure what you're saying here exactly. I only see how this
helps if what you want to return is just the truth or falseness of
the boolean expression.


That's what I said, didn't I? If your IF/THEN/ELSE structure is
only determining whether to return TRUE or FALSE, I simply
eliminate the structure and do it directly.


Uh - er - yes. Sorry.

Nov 12 '05 #23

P: n/a
no****@nospam.nospam (Steve Jorgensen) wrote in
<44********************************@4ax.com>:
On Wed, 21 Jan 2004 21:13:46 GMT, dX********@bway.net.invalid
(David W. Fenton) wrote:
no****@nospam.nospam (Steve Jorgensen) wrote in
<pv********************************@4ax.com>:
On Wed, 21 Jan 2004 17:25:09 GMT, dX********@bway.net.invalid
(David W. Fenton) wrote:

no****@nospam.nospam (Steve Jorgensen) wrote in
<sa********************************@4ax.com> :

>Also, I feel good comments are essential much of the time, but
>comments are what you write when you couldn't think of a way
>to make the code self-explanatory. I always try first to make
>the code as self-explanatory as possible, then add what
>remaining comments are still required.

Hmm. That's not my philosophy of when to include comments. All
code is self-explanatory at some level. I include comments for
dumb programmers who may someday look at my code in the future.
Six months from now, in most cases, I'll be one of those dumb
programmers, and I'm writing those comments not to explain
what's difficult to understand, but to make sure that I don't
have to re-think what is currently bloody obvious to me. My
theory is that the time it takes to type the comment is vastly
smaller than the time it will take me to re-think the logic 6
months from now.

I don't disagree with what you're saying, I just think that the
most maintainable code is the code that's the most clear before
comments are added. If there's something that is repeatedly
making my code less clear than it could be, I want to try to fix
that, not use comments as a band aid. Pretty much all code will
still need comments, but that'll one less thing that has to go
-in- the comments.


I think your rules are, therefore, in conflict with each other
when the TRUE case is not the default. You have to discard one of
them, in that case.

I don't see any issue with that, myself, certainly not enough to
write a set of functions to allow me to avoid having to have a
double negative as the TRUE case.


Well, no one else here seems to have an issue with the order of
the default case either, so perhaps I -am- making a mountain
(well, a foothill) out of a molehill. I also, perhaps, made my
original statement of the problem too narrow since there are other
cases besides IsNull where the problem arises. For instance, the
infamous...

Dim rst As DAO.Recordset
...
rst.FindFirst strExpression
If Not rst.Nomatch then
<action if found>
End If
Fortunately, about 1/3 of these cases I see should be turned into
guard clauses anyway...
Dim rst As DAO.Recordset
...
rst.FindFirst strExpression
If rst.Nomatch then Go To Clean_Up_And_Exit
<action if found>
And a good general solution with some side benefits...
Public Function DAOFindInRecordset( _
rst As DAO.Recordset, _
strFindExpr As String _
) As Boolean
If rst.RecordCount=0 Then Exit Function
rst.MoveFirst
rst.FindFirst strFindExpr
DAOFindInRecordset = Not rst.NoMatch
End Function

then

Dim rst As DAO.Recordset
...
if DAOFindInRecordset(rst, strExpression) Then
<action if found>
End If


Well, to me, you've gone from the frying pan into the fire. I'm
definitely opposed to unnecessary use of GoTos, and Exit
Function/Sub and Go To Clean_Up_And_Exit are all things that I just
would never do, especially if they are arrived at in an
IF/THEN/ELSE structure.

--
David W. Fenton http://www.bway.net/~dfenton
dfenton at bway dot net http://www.bway.net/~dfassoc
Nov 12 '05 #24

P: n/a
Steve Jorgensen <no****@nospam.nospam> wrote in
news:km********************************@4ax.com:
I often come up with logic like this somewhere in a function:

...
If Not IsNull(<some expression>) Then
<default action>
Else
<alternative action>
End If
...

That If Not IsNull ... Else thing makes the code awkward to
read, so my next thought is to swap it around like this:

...
If IsNull(<some expression>) Then
<alternative action>
Else
<default action>
End If
...

Now, though, the alternative action is listed first, followed
by the default action which is also awkward to read.
I usually put my default action last, I try to see the flow as
follows:

If IsNull(<some expression>) Then
<exception action>
Else
<default action>
End If

bacause it's easily expandable to:

If IsNull(<some expression>) Then
<exception action>
ElseIf <some expression> = somevalue then
<exception_2 action>
Else
<default action>
End If

Or collaqpsible to

If IsNull(<some expression>) Then
<exception correction action >
End If
I realize this seems like an awfully trivial topic for
discussion, but it's one of those little itches in the middle
of my mind's back that I've been having to live with for ages
now.


An extension to this issue is the question of when to move inline
actions to a sub procedure for clarity, not for reuse of code.

Do you base it on # of lines, and how many or other criteria?

Bob Q.
Nov 12 '05 #25

P: n/a
On Thu, 22 Jan 2004 00:35:17 GMT, dX********@bway.net.invalid (David W.
Fenton) wrote:
no****@nospam.nospam (Steve Jorgensen) wrote in
<44********************************@4ax.com>:

....

Well, no one else here seems to have an issue with the order of
the default case either, so perhaps I -am- making a mountain
(well, a foothill) out of a molehill. I also, perhaps, made my
original statement of the problem too narrow since there are other
cases besides IsNull where the problem arises. For instance, the
infamous...

Dim rst As DAO.Recordset
...
rst.FindFirst strExpression
If Not rst.Nomatch then
<action if found>
End If
Fortunately, about 1/3 of these cases I see should be turned into
guard clauses anyway...
Dim rst As DAO.Recordset
...
rst.FindFirst strExpression
If rst.Nomatch then Go To Clean_Up_And_Exit
<action if found>
And a good general solution with some side benefits...
Public Function DAOFindInRecordset( _
rst As DAO.Recordset, _
strFindExpr As String _
) As Boolean
If rst.RecordCount=0 Then Exit Function
rst.MoveFirst
rst.FindFirst strFindExpr
DAOFindInRecordset = Not rst.NoMatch
End Function

then

Dim rst As DAO.Recordset
...
if DAOFindInRecordset(rst, strExpression) Then
<action if found>
End If


Well, to me, you've gone from the frying pan into the fire. I'm
definitely opposed to unnecessary use of GoTos, and Exit
Function/Sub and Go To Clean_Up_And_Exit are all things that I just
would never do, especially if they are arrived at in an
IF/THEN/ELSE structure.


Well, me and an awfull lot of other smart people writing programming books
today have reched the conclusion that guard clauses are a good thing - sort of
a topic du jour. Basically, its're saying that a particular condition is
simply not applicable to the main body of the procedure. In this case, why
should the entire main body of the procedure need to be indendet within an If
block. It's the primary function of the procedure, not some ancillary by
product.

In the case above, the primary activity of the function is to search for an
expression match in a recordset, but this is not applicable and there can be
no amtch when the RecordCount is zero, so abort. If we're logically talking
about an abot, the rest of the procedure should not have to suffer the
indignity of being nested in an If. The advantage for this logic becomes more
obvious when there are a bunch of about conditions (usually negatives) to be
checked first that can't go in the same If statement (and if I have one, a
second will usually come up shortly).

The nested if way...

Public Sub MySub()

If not <abort condition 1> Then
If not <abort condition 2> Then
If not <abort condition 3> Then
<15 lines of main body all indented 16 spaces>
End If
End If
End If

Exit Sub

The "guard clause" way...

Public Sub MySub()

If <abort condition 1> Then Exit Sub
If <abort condition 2> Then Exit Sub
If <abort condition 3> Then Exit Sub

<15 lines of main body>

Exit Sub

I'd rather read the guard clause code.

Of course, since this is Access, sometimes clean-up is required (sort of Like
a Finally clause in Java), so I use a Go To Clean_Up_And_Exit. That's not as
clean as I like, but it makes the main body easier enough to read that I go
ahead and use it anyway. An exit point with clean-up code is not too
eggregeous a use of Go To.

Now, I only use guard clauses when I'm checking for what are essentially n/a
conditions skipping the majority of the code in a procedure, and sometimes, I
have to revert to If/Then/Else when specific abort conditions turn out to need
special handling, but I stick to the guard clause as long and as much as I can
make it make sense.
Nov 12 '05 #26

P: n/a
On Thu, 22 Jan 2004 01:08:38 GMT, Bob Quintal <bq******@generation.net> wrote:
Steve Jorgensen <no****@nospam.nospam> wrote in
news:km********************************@4ax.com : ....An extension to this issue is the question of when to move inline
actions to a sub procedure for clarity, not for reuse of code.

Do you base it on # of lines, and how many or other criteria?

Bob Q.


Well, I'm afraid you've started me on another epic. I'd also like to see what
other folks have to say on this subject. Besides just splitting out
subfunctions, it's good to also think when code would become simpler using a
class module, but that would make this even more of an epic, and everyone's
heard too much of me lately already, so...

Off the top of my head, I seem to use the following criteria for splitting out
subfunctions:

1. Number of Lines.
2. Number of variables.
3. Logical function.
4. Complex, nested logic.
5. Duplicated code in different logical branches.
6. Large-ish loops.
7. Set-up/Teardown cases.

Numbers 2 and 3 tend to go together whether that's obvious at first or not.

If I have a function beyond about 25 lines in the main body, I usually try to
break it up. Sometimes, I'm not successful at finding a good way, or I have
to take another look later to see how, but usually, there's a clear way to do
it.

Now, if I have a function longer than say, 10 lines where one chunk of the
function contains all the statements that need some subset of the function's
variables, then I can rip that code and those variables into another function.
Usually, the result is more clear, and I find I've also accidentally
identified a logical sub-function that should have been split out per #3
anyway. Likely, that function will also evolve into something that will be
reused elsewhere, so breaking it out early can benefit other code, not just
the code in the function at hand.

Regarding number 6, a loop can often be seen, metaphorically as a set
operation, so it reads more clearly if it's represented by just a call in the
main function. This also keeps the loop iterator variable and any aggregate
or forward tracking variables off by themselves. Besides clarity, this also
makes it easier to see that these variables are being initialized before each
loop, and aren't reused between loops without reinitialization - it helps
engineer out bugs.

Regarding number 7, if I have a subset of things that have to be set up and
torn down properly, I like to have this in a separate function. Often,
clean-up can be handled by simply letting the sub-function's variables go out
of scope, though you have to watch/force the order of tear-down sometimes
(particularly DAO objects!). Doing this split actually hepls ensure the order
of tear-down too, though, because the sub-function's teardown always happens
before returning to the main function for its teardown (eg. the main function
handles the Database, and the subfunction handles the Recordset).

Nov 12 '05 #27

P: n/a
starwars <no****@tatooine.homelinux.net> wrote:
Comments: This message did not originate from the Sender address above.
It was remailed automatically by anonymizing remailer software.


Please ignore the above posting.

Tony
--
Tony Toews, Microsoft Access MVP
Please respond only in the newsgroups so that others can
read the entire thread of messages.
Microsoft Access Links, Hints, Tips & Accounting Systems at
http://www.granite.ab.ca/accsmstr.htm
Nov 12 '05 #28

P: n/a
starwars <no****@tatooine.homelinux.net> wrote:
Comments: This message did not originate from the Sender address above.
It was remailed automatically by anonymizing remailer software.


Please ignore the above posting.

Tony
--
Tony Toews, Microsoft Access MVP
Please respond only in the newsgroups so that others can
read the entire thread of messages.
Microsoft Access Links, Hints, Tips & Accounting Systems at
http://www.granite.ab.ca/accsmstr.htm
Nov 12 '05 #29

This discussion thread is closed

Replies have been disabled for this discussion.