- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
There's so much about this code style that annoys me. The condition could be rewritten to
... != ... || != ...
, which is so much easier to read.StringUtils.equals
is either equivalent toObjects.equals
(i.e. just a null-safe equality check), in which case it's redundant, or it's not, in which case it's confusingly named.getParameter
feels vague and cryptic, but it might be meaningful in context. And then there's the emptyelse
block, of course.Admin
I once found this paradigm throughout a Fortran app I was maintaining:
Admin
IIRC it inspired a song which went (to the tune of Lili Marlene:
"Else Continue Endif, that's the code to use
Else Continue Endif, be sure it won't confuse"
and I misremember the rest.
Admin
Was it intentional on your part that the entire code snippet could be replaced with
(note, I'm assuming Fortran booleans don't have
.FILE_NOT_FOUND.
)Admin
Good old FORTRAN IV with IF but o ELSE. Had to simulate with GOTO's These where the days ...
Admin
That was acceptable in FORTRAN IV 1957. Not so much in Sinclair and C64 BASICs in the early 1980s...
Admin
In COBOL a common rule was only test for positive conditions.
IF MONTANA CONTINUE ELSE PERFORM 8010-RETURN END-IF
Admin
Does anyone else here ever leave the "if" part blank and only use the else when the negation is too darn hard to read? I have done it a couple of times in my career and it feels dirty.
Admin
Yes, that is indeed where we are going with this.
I believe the thinking was that by testing whether the field was false or not first, you would then save wasting vital clock cycles on performing an unnecessary boolean assignment, and ... oh, wait ...
Admin
Usually I try DeMorgan's rule first. In this case:
And if I don't need short-circuit evaluation, use temporary variables.
Admin
If code is good then great, else goto DAILYWTF.
Admin
I have been tempted to do that a few times, but it feels dirty indeed. Usually it is an indication that one should rewrite the condition in such a way that it is both readable and positive (as in handled by the IF part). And it that fails, write the condition as you would, and put a NOT in front of it.
Admin
Long ago -- regrettably, not in a galaxy far away, but right here in this one -- there was a lightweight-database-oriented programming-for-nonprogrammers thingy called FilePro (or, on a different platform, for trademark reasons, ProFile). Every statement was an if/else. If you didn't need the else, you left it empty; if you didn't need the if -- that is, if your statement was unconditional -- you put it in the else.
Admin
Ever heard of MISRA C ? It's a C programming standard, very common in at least the automotive industry, that essentially requires this! (I believe the rationale is "I have considered the other case", but people I've spoken to are vocal that it's not useful most of the time.)
Admin
Sometimes I'll flip a condition around to put the shorter exceptional case that ends with a return or break into the 'if' part, to get it out of the way first.
Admin
How about FORTRAN II, when you didn't have a logical IF at all. Only the arithmetic IF.
Admin
I think MS left out the ELSE in Commodore BASIC to make it fit in the 8 kB available. Otherwise there is no excuse.
Did Apple, Atari, Tandy, Sinclair, Coleco, TI, etc. have ELSE at the same time? Which of those were also MS BASICs?
Admin
How about FORTRAN 0, where you had to physically solder transistors in NAND patterns.
Admin
It is usually because it is implementing a requirement verbatim. The people writing requirements aren't always the most tech-savvy and if it makes the casual source-code reader compare it to a requirement, it stays as is.
Dear lord, don't get me started on the number of requirements that says if x < y do (foo) else if x > y do (bar) else if x=y do (foobar) where x and y are floating point numbers based on physical attributes (think level of gallons in a 10k gallon tank or flowrate through a pipe).
Took months of letters going back and forth arguing why they'll never get a meaningful exact comparison (not just floating point epsilon but sensor accuracy) and why it provides no increase in value to break out the exact equality (except $$$ value of the contract since it overcomplicates the test plan.)
Admin
This is a good practice - it tells the reader that even though this language is not Rust and therefore there are lots of ways you can unintentionally leave a variable null or not handle an error or what-have-you, you have in fact thought through what the impact of the
if
condition not being true is and <insert impact>, which here is 'no impact'. Very important when you have nested if statements, and certain corporations have it as one of their required style guidelines that every if must have an else and empty elses must be commented.Admin
I actually have worked in places where this was mandatory as part of the style guide. Similarly, I think some compilers will warn you by default if you don't include a default case in a switch statement. This is also mandatory in Haskell, but that's a very different language in a very different paradigm.
I think I can see the logic, in a sort of perverse way, even if I don't like it. In Haskell this is done because every statement always has to evaluate to something, and adding some kind of "default" value just doesn't work with the way the language is designed. In this case, and the "default switch" case, the intent is to be explicit about covering every single case, and being explicit that you don't want to do anything.
I actually hate that condition way more...
Admin
I actually worked on a big java 6 project migrated from another language (automagically then "fixed" manually). We started to add
else
everywhere because we could not figure out whether theelse
was missing or if it was effectively not necessary. There were lots of other issues (like some files of 20k+ lines, methods of hundreds of lines of code, no tests…) so this thing actually simplify understanding in this context.Admin
Only when followed by a series of else-if, e.g. (hope I get the formatting right):
Inverting the frist condition (as I normally would) would require an extra level of indentation for the rest, so in this case, it looks nicer to me this way.
Admin
I once knew someone who wrote EVERY if statement with a negation, no matter how simple, as an empty if branch with an else branch. He said it made more sense to him.
Admin
I absolutely hate the 'one return per function'. It's a complete misapplication of a rule that was designed to discourage you from using the ability in fortran to specify multiple points for a function to return to in the call to the function. Seriously, you'd end up with absolutely no idea where the code might be going.
There are situations in languages more modern than fortran 2 where it might make your code clearer to have only exit point, but there are situations where it most definitely doesn't.
It's basically a Cargo cult rule now
Addendum 2022-03-28 15:54: It's part of the 'single entry, single exit' rule for writing maintainable fortran. Not only did fortran allow return to multiple places, it allowed routines to have multiple entry points. The single entry part of the rule has died because you can't do that any more.
Admin
re: "it allowed routines to have multiple entry points" An old-school definition of an object (as in OOP) is that they are "modules with multiple entry points and persistent state," so that capability still exists, albeit well hidden behind methods and properties now.
Admin
Ha, another example where someone read Clean Code but didn't understand a thing.
First, the else statement is basically covered by the rule of not having fall-throughs ever. A good example is the switch statement, but it can also expanded to the else statement. I don't actually remember the reasoning behind it, it never made really sense to me, but eh.
Second, not using != as an operator again is about the rule of not using negative conditional statements, because they are harder to understand. Personally I also never had any troubles with those as long is it doesn't go crazy with nested double negatives or worse.
So yeah, this looks to me like code from a complete rookie developer strictly going by textbook with the brain turned off.
Admin
reminds me of a VERY old story where someone insisted on doing "if (do NOTHING) else (do something important) EVERY time he used "if"!
Admin
"Only one return from a function" originally and most importantly meant that a (machine code or assembly language) function should only return to where it came from.
In assembly or machine code, it's really easy to make each exit point from a function go to a different place. It's not obvious in stack-oriented languages, and not obvious when you are using a processor specifically designed for a stack-oriented language, but when your "language" is a macro assembler (like FORTRAN ZERO), and other early environments, why would you want to waste cycles by always exiting with the same exit code to the same entry point?
The restriction was adopted by early 'structured' languages, where 'structures' like loops and function calls were provided by the compiler: a structure is provided for function calls, but the structure has only one exit point: you always go through the epilogue and back to the call point, (or back to the call point and through the epilogue).
Admin
Isn't "single point of exit" also about error and resource handling in languages without exception handling?
From my understanding, in C it even constitutes a valid use of
goto
: "If the function returned an error code, jump to the cleanup section of the function."As for the original example of the article: I have come to hate
if
statements. When you seeif CONDITION
, you have to guess if there will be anelse
. I may at some points have done something likethough I'm pretty sure it added some year in purgatory.
My personal preference would be for all languages to:
else
on anif
when
andunless
to communicate conditional execution without anelse
.Admin
A slightly more reasonable reason for "always have an else": dangling elses. This is a syntactic ambiguity: in
if(a) if(b) c(); else d();
it's not clear to which if the else belongs (the grammar may specify, but it's still very hard to read).Most programmers adopt the more sensible style rule of "always put braces around the body of an if" (or use a language where they're mandatory), but this is the sort of stupid rule that someone will inevitably use instead.
Admin
Always tradeoff's -- how would you set a breakpoint in the code when the condition is not true without the else???? [and yes, sometimes you want to break if the condition is not met]
Admin
Sinclair Spectrum and earlier, no. Not MS. Sinclair Superbasic for the QL, yes. But that was (and had the space to be) a much better language. Also not MS. BBC, yes; also not MS. The rest, I have no idea, except that Apple Basic was MS, but I never used it or any of the others.
Admin
Just simulate it by using computed GOTOs. Assuming you have the usual conventions for 0 and 1 for truth values, it's not too difficult to write a computed GOTO that doesn't drive you completely mad. Really really ugly though, and we try to avoid that sort of thing now precisely because it is really awful.
OK, merely thinking of computed GOTO is strongly towards madness.
Admin
"OK, merely thinking of computed GOTO is strongly towards madness."
Let's not even mention assigned GOTOs, which seem to have been designed solely for the purpose of making code completely unmaintainable.