tags:

views:

1136

answers:

15

Ever since I first wrote

if ($a = 5) {
   #  do something with $a, e.g.
   print "$a";
}

and went through the normal puzzling session of

  • why is the result always true
  • why is $a always 5

until I realized, I'd assigned 5 to $a, instead of performing a comparison.

So I decided to write that kind of condition above as

 if (5 == $a)

in other words:

always place the constant value to the left side of the comparison operator, resulting in a compilation error, should you forget to add the second "=" sign.

I tend to call this defensive coding and tend to believe it's a cousin to defensive-programming, not on the algorithmic scale, but keyword by keyword.

What defensive coding practices have you developed?


One Week Later:

A big "thank you" to all who answered or might add another answer in the future.

Unfortunately (or rather fortunately!) there is no single correct answer. For that my question was to broad, asking more for opinions or learnings of experience, rather than facts.

+10  A: 

This is a simple and obvious one, but I NEVER EVER NEVER repeat the same string constant twice in my code, cause I KNOW that if I do I will be spelling one of them wrong :) Use constants, people!

Torbjørn
+4  A: 

I stopped using languages where you can do

if a = 5: print a

This has saved me tons of headaches =).

On a more serious note... I now always write the curly braces right after I write my ifs and for loops, and then fill them in afterwards. This makes sure my brackets are always aligned.

Claudiu
I agree ... but in this not so perfect world, the choice of programming language is not mine...
lexu
+7  A: 

Always put curly braces after an if/for/while ... even if there's only one single statement after. BTW D. Crockford thinks it's better too: Required blocks

PW
Perl has mandated curly braces after if (and elsif) and else for aeons.
Jonathan Leffler
Yeah, but Perl also has a unary _ operator, doesn't it? Don't try and convince me that Perl is a shining beacon of readability :-)
endian
I just posted a reply on another question pointing out that the "to brace or not to brace" issue is closely related to proper indenting practices.
staticsan
Searching Perl's perlop page (http://perldoc.perl.org/perlop.html) yields no mention of a unary _ operator. Care to elaborate on your unfounded claims?
Chris Lutz
+3  A: 

Returning a copy of a mutable object, i.e. a copy of an array, not the mutable object itself.

dhiller
I'd agree, in worlds where speed and memory are not issues.
Bill James
... and this is hardly a defensive *coding* practice...
Rich
Did you guys ever run into problems with a leaking reference?
dhiller
+1: An improvement, return an immutable copy whenever possible. Both are defensive practices - they help prevent defects (ie, stupid programmer tricks ;-))
Ken Gentle
strager
+14  A: 

Always use braces:

if(boolean)
    oneliner();
nextLineOfCode();

is not the same as:

if(boolean)
{
    oneliner();
}
nextLineOfCode();

If oneliner() is a #defined function, and it isn't defined then your next line of code suddenly becomes subject to the if(). Same thing applies to for loops etc. With braces then the next piece of code never unintentionally becomes conditional on the if/for etc.

Wairapeti
If oneliner() is supposed to be #defined but isn't, then you have a call to an undeclared function (an error in C++, allowed in C). If oneliner() is #defined with an empty body, then you have a semi-colon giving an empty statement after the if. In both cases, the constructs are the same.
Jonathan Leffler
Oh God, YES! Always use braces!
endian
+10  A: 

The top 3 defensive coding practices I employ are

  1. unit testing
  2. unit testing
  3. unit testing

There is no better defense for the quality of your code than a good unit test to back you up.

JaredPar
But a unit test is something that happens after coding, not during coding. It's a good thing to do, but not a coding practice.
Treb
In my opinion unit testing is a defensive programming practice (an importent one, don't go without!), but not a defensive coding example ... a "opps-ative" coding error in your test is not caught ... depends on the (mine really) definitions of "coding" and "programing"
lexu
in many cases a unit test is written before the implementation.Yes, it is a coding practice.
Tom Barta
It is written before coding (if you do TDD) and applied after coding. Not during coding.
Treb
Whether unit tests are written before or after the actual code is written it has nothing to do with defensive coding/programming but rather ensuring the code produces the correct/expected result given a known set of inputs. They won't help you prevent common coding mistakes as you write the code.
Scott Dorman
+1  A: 

Avoid unnecessary test. Example

  1. if(bool == true)
  2. Pointer checks if(pointer)

EDIT: if(pointer) is not readable so nowadays I prefer if(NULL != pointer)

yesraaj
I agree wholeheartedly with point 1, but for point 2, I prefer if (pointer != NULL) because it makes the code easier to read.
RobH
I too agree!!
yesraaj
+2  A: 

Couple things:

  • Yes, the 1-line blocks. Use the braces... heck, most good IDE's will make em for you.
  • Comment your code after you write it, or re-read your comments if you did it ahead of time. Make sure your code still does what the comments say.
  • Unit testing is a great fallback to re-reading your code.
  • Always log an exception... or, NEVER catch an exception without saying so, at least in debug.
Bill James
+5  A: 
  • always initialize variables
  • use const wherever I can (without using mutable)
  • avoid bare dynamic allocation of memor or other resources
  • always use curly braces
  • code use-cases and tests for any class before coding implementation
  • turn on as many useful warnings as I can (-Wall -Wextra -ansi -pedantic -Werror at a minimum)
  • use the simplest tool that solves the problem (in my current environment, that's bash -> grep -> awk -> python -> C++).
Tom Barta
+1 for always initialize variables and curly braces.
Scott Dorman
+3  A: 

Personally, I dislike this defensive style, it makes the code hard ro read.

VC compiler warning level 4 will spot this (possible) error.
"warning C4706: assignment within conditional expression"

You can enable just this specific compiler warning, at any level:

#pragma warning(3,4706)
Tal
GCC will warn you by default when you do this; it advises you to put an assignment inside nested parens to make your intention clear.
Rich
The C# compiler will also complain about this: Cannot implicitly convert type 'xyz' to 'bool'.
Scott Dorman
+7  A: 

When comparing a string with a constant, write

if ("blah".equals(value)){}

instead of

if (value.equals("blah")){}

to prevent a NullPointerException. But this is the only time I use the suggested coding-style (cause "if (a = 1)..." is not possible in Java).

Tobias Schulte
Mmm, nice, I like it.
endian
Just be careful if your programming language does **case sensitivie** string comparisons using the equality operators (or equals method).
Scott Dorman
+5  A: 

One of the things I always try to remember when I am in the Javascript world is to always start the return value of a function on the same line as the return key word.

function one(){
    return {
        result:"result"
    };
}

function two(){
    return 
    {
        result:"result"
    };
}

These 2 functions will not return the same value. The first function will return an Object with a property results set to "result". The second function will return undefined. It's a really simple mistake and it happens becaus eof Javascript's over-zealous Semi-Colon Insertion strategy. Semi-colons are semi-optional in Javascript and becasue of this the Javscript engine will add semi-coons where it thinks it's should be. Because return is actaully a valid statement a semi-colon will be inserted after the return statement and the rest of the function will essentially be ignored.

kouPhax
One more reason why Javascript is Evil.
endian
I very much disagree. I think it was rushed to the market and didn't have time in a lab for refinement. The it's populatiry exploded which meant it couldn't be fixed without breaking things. Used correctly it's a brilliantly adaptive and powerful language. Rant Over.
kouPhax
Wow - I never knew that! Thanks for the info. That rates a question/Answer all by itself.
Preet Sangha
+4  A: 

From my blog:

  1. Think positive and return early plus avoid deep nesting. Instead of

    if (value != null) { ... do something with value ... } return

    write

    if (value == null) { return } ... do something with value ...

  2. Avoid "string constants" (i.e. the same text in quotes in more than one place). Always define a real constant (with a name and an optional comment what it means) and use that.

Aaron Digulla
+1  A: 

Installed Resharper ;) Then I don't need to write "5 == a" to get warned if I did something wrong :)

badbadboy
Does that work with perl / python / bash ... self discipline does .. and yes, that's a lame argument in a way .-(
lexu
@lexu: no, but it is a subjective question, and I do not use perl, python or bash :)
badbadboy
+1  A: 

Several suggestions for embedded C programming in the article Rules for Defensive C Programming from embedded.com.

dwj