148

If you had to choose your Favorite (clever) techniques for defensive coding, what would they be? Although my current languages are Java and Objective-C (with a background in C++), feel free to answer in any language. Emphasis here would be on clever defensive techniques other than those that 70%+ of us here already know about. So now it is time to dig deep into your bag of tricks.

In other words try to think of other than this uninteresting example:

  • if(5 == x) instead of if(x == 5): to avoid unintended assignment

Here are some examples of some intriguing best defensive programming practices (language-specific examples are in Java):

- Lock down your variables until you know that you need to change them

That is, you can declare all variables final until you know that you will need to change it, at which point you can remove the final. One commonly unknown fact is that this is also valid for method params:

public void foo(final int arg) { /* Stuff Here */ }

- When something bad happens, leave a trail of evidence behind

There are a number of things you can do when you have an exception: obviously logging it and performing some cleanup would be a few. But you can also leave a trail of evidence (e.g. setting variables to sentinel values like "UNABLE TO LOAD FILE" or 99999 would be useful in the debugger, in case you happen to blow past an exception catch-block).

- When it comes to consistency: the devil is in the details

Be as consistent with the other libraries that you are using. For example, in Java, if you are creating a method that extracts a range of values make the lower bound inclusive and the upper bound exclusive. This will make it consistent with methods like String.substring(start, end) which operates in the same way. You'll find all of these type of methods in the Sun JDK to behave this way as it makes various operations including iteration of elements consistent with arrays, where the indices are from Zero (inclusive) to the length of the array (exclusive).

So what are some favorite defensive practices of yours?

Update: If you haven't already, feel free to chime in. I am giving a chance for more responses to come in before I choose the official answer.

Ryan Delucchi
  • 7,718
  • 13
  • 48
  • 60
  • I'd like to represent the ignorant 30% of us here that may not know the *simple* techniques. Anybody have a link to the "obvious" techniques everyone should know as a foundation? – elliot42 Jan 29 '09 at 09:18
  • Related: http://stackoverflow.com/questions/163026/what-is-your-least-favorite-syntax-gotcha/163035 – Bill the Lizard Jan 29 '09 at 12:53
  • Why would you choose an official answer? That just sounds wholly unclever. – bzlm Jan 30 '09 at 12:15
  • Well, when it comes to programming, even cleverness should take a back seat in honor of "the rule of least astonishment". For me to break with the Stack Overflow spirit of marking the best answer would violate Stack Overflow protocol (hence breaking said rule). Aside from that: I like closure :-) – Ryan Delucchi Jan 30 '09 at 23:19

67 Answers67

103

In c++, I once liked redefining new so that it provided some extra memory to catch fence-post errors.

Currently, I prefer avoiding defensive programming in favor of Test Driven Development. If you catch errors quickly and externally, you don't need to muddy-up your code with defensive maneuvers, your code is DRY-er and you wind-up with fewer errors that you have to defend against.

As WikiKnowledge Wrote:

Avoid Defensive Programming, Fail Fast Instead.

By defensive programming I mean the habit of writing code that attempts to compensate for some failure in the data, of writing code that assumes that callers might provide data that doesn't conform to the contract between caller and subroutine and that the subroutine must somehow cope with it.

Joe Soul-bringer
  • 3,294
  • 5
  • 31
  • 37
  • 1
    That's an interesting stance; a young one too. It's generally accepted that you should attempt to recover whenever there is hope to, and only fail as a last resort. Fail fast in debug mode (ASSERT) but recover where possible in production or you are just going to crash lots with user input. – Adam Hawes Jan 29 '09 at 05:19
  • 8
    Defensive programming is attempting to deal with illegal conditions introduced by other parts of a program. Handling improper user input is completely different thing. – Joe Soul-bringer Jan 29 '09 at 06:25
  • I would +5 this answer if I could! ;-) – MiniQuark Jan 29 '09 at 07:09
  • I recall someone creating a C++ preprocessor to do things like replace outofmemory errors with overwrites of existing memory, using modulo when using array indices to avoid overflow, etc. Detecting failure quickly is good, but continuing to run, even in broken state, is sometimes necessary. – Brian Jan 29 '09 at 14:47
  • 5
    Errr... note that this definition of defensive programming isn't even close to the definition implicitly used in the question. – Sol Jan 29 '09 at 14:54
  • 15
    Never avoid Defensive Programming. The thing is not "compensating" for failures in the data but protecting yourself from malicious data designed to make your code do things it isn't supposed to do. See Buffer Overflow, SQL Injection. Nothing fails faster than a web page under XSS but it ain't pretty – Jorge Córdoba Jan 29 '09 at 17:45
  • 6
    I would argue that "fail fast" procedures are a form of defensive programming. – Ryan Delucchi Jan 29 '09 at 19:41
  • 1
    I would disagree @Ryan. Failing is not defensive; it's erroneous. Detect errors early, recover fast. Fail only the situation is so dire you can't possibly recover. – Adam Hawes Jan 29 '09 at 21:57
  • 2
    I have a more broad definition of "defensive programming" (much like: http://en.wikipedia.org/wiki/Defensive_programming). The whole point of writing "fail-fast" functions is to *defend* functions that depend on them against execution when some set of objects are in an erroneous state. – Ryan Delucchi Jan 29 '09 at 23:23
  • You should only fail fast on server side. Otherwise, you risk ruining data and doing inappropriate things. That's why Win32 SEH sucks. – mannicken Jan 30 '09 at 08:28
  • I agree with Sol here; this question is (at least partially) about *static compile-time defense*, not *run-time defense*. – reuben Jan 30 '09 at 09:18
  • I'm not in *complete* agreement with a number of assumptions made by this response. But as an advocate of TDD and fail-fast behavior (which I will continue to declare as "defensive programming" strategies), I am selecting this one as the official answer. – Ryan Delucchi Jan 30 '09 at 23:22
  • 6
    @ryan is exactly right, fail fast is a good defensive concept. If the state you are in is not possible, don't try to keep limping along, FAIL FAST AND LOUD! Extra important if you are meta-data driven. Defensive programming isn't just checking your parameters... – Bill K Mar 10 '09 at 21:46
75

SQL

When I have to delete data, I write

select *    
--delete    
From mytable    
Where ...

When I run it, I will know if I forgot or botched the where clause. I have a safety. If everything is fine, I highlight everything after the '--' comment tokens, and run it.

Edit: if I'm deleting a lot of data, I will use count(*) instead of just *

John MacIntyre
  • 12,910
  • 13
  • 67
  • 106
48

Allocate a reasonable chunk of memory when the application starts - I think Steve McConnell referred to this as a memory parachute in Code Complete.

This can be used in case something serious goes wrong and you are required to terminate.

Allocating this memory up-front provides you with a safety-net, as you can free it up and then use the available memory to do the following:

  • Save all the persistent data
  • Close all the appropriate files
  • Write error messages to a log file
  • Present a meaningful error to the user
LeopardSkinPillBoxHat
  • 28,915
  • 15
  • 75
  • 111
42

In every switch statement that doesn't have a default case, I add a case that aborts the program with an error message.

#define INVALID_SWITCH_VALUE 0

switch (x) {
case 1:
  // ...
  break;
case 2:
  // ...
  break;
case 3:
  // ...
  break;
default:
  assert(INVALID_SWITCH_VALUE);
}
Brad Gilbert
  • 33,846
  • 11
  • 78
  • 129
Diomidis Spinellis
  • 18,734
  • 5
  • 61
  • 83
  • 2
    Or a throw in a modern fangled language. – Tom Hawtin - tackline Feb 25 '09 at 14:00
  • 2
    Assert has the advantage that its effects can be globally disabled at compile-time. Yet, in some situations throw can be more appropriate, if your language supports it. – Diomidis Spinellis Feb 26 '09 at 05:54
  • 2
    Assert has another advantage that makes it useful for production code: When something goes wrong, it tells you exactly what failed and what line of the program the error came from. A bug report like that is wonderful! – Mason Wheeler Jun 18 '10 at 16:54
  • 2
    @Diomidis: Another angle is: Assert has the **disadvantage** that its effects can be globally disabled at compile-time. – Disillusioned Apr 22 '11 at 19:40
  • @Mason: Yes, exceptionally useful - provided you can easily tie application version to correct source file version. – Disillusioned Apr 22 '11 at 19:41
  • @Craig: Of course you can. You *do* have source control, don't you? – Mason Wheeler Apr 22 '11 at 20:18
  • @Mason: Of course _I_ do. :D But I can't speak for all readers of your excellent advice. ;) Nor whether they're using source control _effectively_ through a well defined build and distribution process. – Disillusioned Apr 22 '11 at 20:55
  • 1
    throw is indeed better. And then you make sure that your test coverage is adequate. – Dominic Cronin May 29 '12 at 12:52
41

When you're handling the various states of an enum (C#):

enum AccountType
{
    Savings,
    Checking,
    MoneyMarket
}

Then, inside some routine...

switch (accountType)
{
    case AccountType.Checking:
        // do something

    case AccountType.Savings:
        // do something else

    case AccountType.MoneyMarket:
        // do some other thing

    default:
-->     Debug.Fail("Invalid account type.");
}

At some point I'll add another account type to this enum. And when I do, I'll forget to fix this switch statement. So the Debug.Fail crashes horribly (in Debug mode) to draw my attention to this fact. When I add the case AccountType.MyNewAccountType:, the horrible crash stops...until I add yet another account type and forget to update the cases here.

(Yes, polymorphism is probably better here, but this is just an example off the top of my head.)

Brad Gilbert
  • 33,846
  • 11
  • 78
  • 129
Ryan Lundy
  • 204,559
  • 37
  • 180
  • 211
  • 4
    Most compilers are smart enough to issue a warning if you don't handle some enums in a case block. But setting the default to fail is still good form - an enum is just a number and if you get memory corruption you can have an invalid value appear. – Adam Hawes Jan 29 '09 at 05:15
  • in c, i used to add an invalidAccountType at the end. this is useful sometimes. – Ray Tayek Jan 29 '09 at 06:33
  • 1
    @Adam -- compilers will issue a warning if you recompile *everything*. If you add new classes and only partially recompile, you may not notice something like the above, and the default case will save you. It won't just silently fail. – Eddie Jan 29 '09 at 06:51
  • Your code will crash !! you forgot break – Nicolas Dorier Jan 29 '09 at 11:53
  • 4
    The break is implied in the comments, Slashene. :P – Ryan Lundy Jan 29 '09 at 13:28
  • 2
    After the debug should be a 'throw new NotSupportedException()' for production code. – user7116 Jan 29 '09 at 14:32
  • @NicolasDorier a friend of mine has found useful to write 'break' _before_ 'case'! Wonderful, but it works for Visual C++ - without any compiler warnings on level 4! – Brian Cannard Nov 27 '13 at 21:47
  • don't forget `break;` ;o) – Atmocreations Jul 30 '14 at 15:02
35

When printing out error messages with a string (particularly one which depends on user input), I always use single quotes ''. For example:

FILE *fp = fopen(filename, "r");
if(fp == NULL) {
    fprintf(stderr, "ERROR: Could not open file %s\n", filename);
    return false;
}

This lack of quotes around %s is really bad, because say filename is an empty string or just whitespace or something. The message printed out would of course be:

ERROR: Could not open file

So, always better to do:

fprintf(stderr, "ERROR: Could not open file '%s'\n", filename);

Then at least the user sees this:

ERROR: Could not open file ''

I find that this makes a huge difference in terms of the quality of the bug reports submitted by end users. If there is a funny-looking error message like this instead of something generic sounding, then they're much more likely to copy/paste it instead of just writing "it wouldn't open my files".

ekangas
  • 843
  • 1
  • 10
  • 17
Nik Reiman
  • 39,067
  • 29
  • 104
  • 160
28

SQL Safety

Before writing any SQL that will modify the data, I wrap the whole thing in a rolled back transaction:

BEGIN TRANSACTION
-- LOTS OF SCARY SQL HERE LIKE
-- DELETE FROM ORDER INNER JOIN SUBSCRIBER ON ORDER.SUBSCRIBER_ID = SUBSCRIBER.ID
ROLLBACK TRANSACTION

This prevents you from executing a bad delete/update permanently. And, you can execute the whole thing and verify reasonable record counts or add SELECT statements between your SQL and the ROLLBACK TRANSACTION to make sure everything looks right.

When you're completely sure it does what you expected, change the ROLLBACK to COMMIT and run for real.

Brad Gilbert
  • 33,846
  • 11
  • 78
  • 129
amsimmon
  • 116
  • 2
  • 5
25

For all languages:

Reduce the scope of variables to the least possible required. Eschew variables that are just provided to carry them into the next statement. Variables that don't exist are variables you don't need to understand, and you can't be held responsible for. Use Lambdas whenever possible for the same reason.

dkretz
  • 37,399
  • 13
  • 80
  • 138
  • 5
    What does exactly mean the eschew part? I sometimes do introduce variables that only live until the next line. They serve as a name for an expression, which makes the code more readable. – zoul Jan 29 '09 at 07:18
  • 4
    Yes I disagree too. With very complex expressions it's often a good idea to break them down into two or sometimes more shorter and simpler ones using temporary variables. It's less error prone in maintenance and the compiler will optimise out temps – Cruachan Jan 29 '09 at 10:05
  • 1
    I agree that there are exceptional cases where I declare variables for clarity (and sometimes to create a target for debugging). My experience is that the general practice is to err in the opposite direction. – dkretz Jan 29 '09 at 15:15
  • I agree with both viewpoints; though when I do break expressions into temporary variables I try to do so within a separate scope. Lambdas are great for this, as are helper methods. – Erik Forbes Jan 29 '09 at 23:18
19

When in doubt, bomb the application!

Check each and every parameter at the beginning of each and every method (whether explictly coding it yourself, or using contract-based programming does not matter here) and bomb with the correct exception and/or meaningful error message if any precondition to the code is not met.

We all know about these implicit preconditions when we write the code, but if they are not explicitly checked for, we are creating mazes for ourselves when something goes wrong later and stacks of dozens of method calls separate the occurance of the symptom and the actual location where a precondition is not met (=where the problem/bug actually is).

peSHIr
  • 6,279
  • 1
  • 34
  • 46
  • And of course: Use generic code (a small library, extension methods in C#, whatever) to make this easy. So you can write somethin glike `param.NotNull("param")` instead of `if ( param == null ) throw new ArgumentNullException("param");` – peSHIr Jan 30 '09 at 08:12
  • 2
    Or use contract-based programming, like Spec#! – bzlm Jan 30 '09 at 12:18
  • Depends what application it is. I hope the folks writing code for fly-by-wire aircraft and pacemakers don't think like peSHIr. – MarkJ Feb 03 '09 at 20:56
  • 6
    @MarkJ: You don't really get it, do you? If it bombs early (=during developent and testing) it should never bomb when it's in production. So I really hope they *do* program like this! – peSHIr Feb 05 '09 at 09:26
  • I must admit I don't like that very much, especially for private and protected methods. Reasons: a) you clutter the code with checks that do not at all resemble business requirements b) those checks are hard to test for non-public methods c) it's useless in many cases, e.g. since a null value will cause the method to fail anyway two lines later – Erich Kitzmueller Sep 30 '10 at 11:13
18

In Java, especially with collections, make use of the API, so if your method returns type List (for example), try the following:

public List<T> getList() {
    return Collections.unmodifiableList(list);
}

Don't allow anything to escape your class that you don't need to!

Brad Gilbert
  • 33,846
  • 11
  • 78
  • 129
David Grant
  • 13,929
  • 3
  • 57
  • 63
17

in Perl, everyone does

use warnings;

I like

use warnings FATAL => 'all';

This causes the code to die for any compiler/runtime warning. This is mostly useful in catching uninitialized strings.

use warnings FATAL => 'all';
...
my $string = getStringVal(); # something bad happens;  returns 'undef'
print $string . "\n";        # code dies here
Brad Gilbert
  • 33,846
  • 11
  • 78
  • 129
Eric Johnson
  • 17,502
  • 10
  • 52
  • 59
16

C#:

string myString = null;

if (myString.Equals("someValue")) // NullReferenceException...
{

}

if ("someValue".Equals(myString)) // Just false...
{

}
Brad Gilbert
  • 33,846
  • 11
  • 78
  • 129
Christian C. Salvadó
  • 807,428
  • 183
  • 922
  • 838
  • Same in Java, and probably most OO languages. – MiniQuark Jan 29 '09 at 07:05
  • This is nice in Objective-C, where it is possible to send messages to nil (“call methods of a null object”, with a certain license). Calling [nil isEqualToString:@"Moo"] returns false. – zoul Jan 29 '09 at 07:10
  • I disagree with the C# example. A nicer solution is to use "if (myString == "someValue")". Also no null reference exception, and certainly more readable. – Dan C. Jan 29 '09 at 09:10
  • But if you use == in C#, you can't use one of the overloads of Equals that lets you specify case-insensitivity. – Ryan Lundy Jan 29 '09 at 13:30
  • @Kyralessa - Thanks didn't know you could do that; saves me adding .ToLower() to both strings.. – Nick Jan 29 '09 at 14:45
  • @Kyralessa: agree, but only in those exceptional cases when you want the overload. Otherwise, using the == version is shorter and simpler. – Dan C. Jan 29 '09 at 15:46
  • 13
    this example is just allowing you to hide a potentially dangerous situation in your program. If you weren't expecting it to be null, you WANT it to throw an exception, and if you were expecting it to be null, you should handle it as such. This is a bad practice. – rmeador Jan 29 '09 at 16:16
  • 2
    In C#, I always just use string.Equals(,). It doesn't matter if either of them is null. – Darcy Casselman Jan 29 '09 at 17:19
  • Got to agree with rmeador on this one...in general, if I'm testing equality, I'm expecting two strings. If one is null (again, in most cases) something is drastically wrong, and I want to know about it. – Beska Jan 29 '09 at 19:22
  • @rmeador: handle how? if(myString == null) {do nothing} else {compare it etc...} it's stupid if having a null string (e.g. empty field on html form) is just a string that doesn't match some other string. Its bad only if it really shouldn't be null. – Slartibartfast Jan 30 '09 at 10:03
  • @Slartibartfast: An empty field on an html form _should_ return an empty string - not a null string. A non-existant field on the form could more appropriately return a null string if using something like `string GetField(string FieldName)`. – Disillusioned Apr 22 '11 at 23:35
15

In c# checking of string.IsNullOrEmpty before doing any operations on the string like length, indexOf, mid etc

public void SomeMethod(string myString)
{
   if(!string.IsNullOrEmpty(myString)) // same as myString != null && myString != string.Empty
   {                                   // Also implies that myString.Length == 0
     //Do something with string
   }
}

[Edit]
Now I can also do the following in .NET 4.0, that additionally checks if the value is just whitespace

string.IsNullOrWhiteSpace(myString)
Binoj Antony
  • 15,886
  • 25
  • 88
  • 96
  • 7
    That's not being defensive, it's ignoring the problem. Should be `if (!string.IsNullOrEmpty(myString)) throw new ArgumentException("", "myString"); /* do something with string */`. – enashnash Feb 09 '12 at 16:02
14

In Java and C#, give every thread a meaningful name. This includes thread pool threads. It makes stack dumps much more meaningful. It takes a little more effort to give a meaningful name to even thread pool threads, but if one thread pool has a problem in a long running application, I can cause a stack dump to occur (you do know about SendSignal.exe, right?), grab the logs, and without having to interrupt a running system I can tell which threads are ... whatever. Deadlocked, leaking, growing, whatever the problem is.

Erik van Brakel
  • 23,220
  • 2
  • 52
  • 66
Eddie
  • 53,828
  • 22
  • 125
  • 145
12

With VB.NET, have Option Explicit and Option Strict switched on by default for the whole of Visual Studio.

ChrisA
  • 4,163
  • 5
  • 28
  • 44
  • Although I'm working with older code, so I don't have option strict turned on (causes way too many compiler errors to fix), having both these options turned on can (and would have in my case) saved a lot of heart ache. – Kibbee Jan 29 '09 at 18:13
  • 1
    By the way, for anyone converting old code that didn't use Option Strict to use it, note that in the case of items that were autoconverted to String, they're not using ToString(); they're using a cast to string. In my early .NET days I'd change these to use ToString(), and it would break things, especially with enums. – Ryan Lundy Dec 04 '09 at 15:16
10

With Java, it can be handy to make use of the assert keyword, even if you run production code with assertions turned off:

private Object someHelperFunction(Object param)
{
    assert param != null : "Param must be set by the client";

    return blahBlah(param);
}

Even with assertions off, at least the code documents the fact that param is expected to be set somewhere. Note that this is a private helper function and not a member of a public API. This method can only be called by you, so it's OK to make certain assumptions on how it will be used. For public methods, it's probably better to throw a real exception for invalid input.

ekangas
  • 843
  • 1
  • 10
  • 17
Tim Frey
  • 9,901
  • 9
  • 44
  • 60
  • In .NET, Debug.Assert does the same thing. Whenever you have a place where you think "This reference can't be null here, right?", you can put a Debug.Assert there, so that if it *can* be null, you can either fix the bug or change your assumptions. – Ryan Lundy Jan 29 '09 at 04:54
  • 1
    +1, public methods should throw on contract failures, privates should assert – user7116 Jan 29 '09 at 14:33
10

C++

#define SAFE_DELETE(pPtr)   { delete pPtr; pPtr = NULL; }
#define SAFE_DELETE_ARRAY(pPtr) { delete [] pPtr; pPtr = NULL }

then replace all your 'delete pPtr' and 'delete [] pPtr' calls with SAFE_DELETE(pPtr) and SAFE_DELETE_ARRAY(pPtr)

Now by mistake if you use the pointer 'pPtr' after deleting it, you will get 'access violation' error. It is far easier to fix than random memory corruptions.

Svante
  • 50,694
  • 11
  • 78
  • 122
Nitin Bhide
  • 1,685
  • 14
  • 15
  • 1
    Better use a template. It's scoped and overloadable. –  Jan 29 '09 at 06:17
  • I was just about to say that. Use a template instead of a macro. That way if you ever need to step through the code, you can. – Steve Rowe Jan 29 '09 at 07:13
  • I learned which was easier to debug the hard way back in school. That's a mistake I haven't made since. :) – Greg D Jan 29 '09 at 14:33
  • This won't work too well if you got pPtr passed in as an argument - the caller won't be made aware of your assignment. – florin Jan 29 '09 at 22:31
  • 3
    Or use Smart Pointers... Or heck, avoid new/delete as much as you can anyway. – Arafangion Mar 10 '09 at 23:16
  • 1
    @Arafangion: just avoid `delete`. Using `new` is fine, as long as the new object gets owned by a smart pointer. – Alexandre C. Feb 23 '11 at 10:05
9

I didn't find the readonly keyword until I found ReSharper, but I now use it instinctively, especially for service classes.

readonly var prodSVC = new ProductService();
JMS
  • 2,183
  • 2
  • 15
  • 16
  • I use Java's equivalent 'final' keyword on all fields that I can. It really does save you from making bonehead moves like not setting a field/writing confusing switches that can set fields multiple times. I'm less likely to mark local varibles/parameters but I guess it couldn't hurt. – Tim Frey Jan 29 '09 at 04:16
  • C# doesn't allow you to mark local variables as readonly, so we don't even have the choice... – Restore the Data Dumps Jan 29 '09 at 04:55
  • I'm not sure what readonly here means, but Java's final is not enough for me. It just means that pointer to an object is unchanged, but there is no way to prevent change on the object itself. – Slartibartfast Jan 30 '09 at 10:11
  • In C# a readonly struct would prevent it from ever being changed. – Samuel Mar 11 '09 at 14:57
9

In Java, when something is happening and I don't know why, I will sometimes use Log4J like this:

if (some bad condition) {
    log.error("a bad thing happened", new Exception("Let's see how we got here"));
}

this way I get a stack trace showing me how I got into the unexpected situation, say a lock that never unlocked, something null that cannot be null, and so on. Obviously, if a real Exception is thrown, I don't need to do this. This is when I need to see what is happening in production code without actually disturbing anything else. I don't want to throw an Exception and I didn't catch one. I just want a stack trace logged with an appropriate message to flag me in to what is happening.

Eddie
  • 53,828
  • 22
  • 125
  • 145
  • Hmm, this is kinda neat but I am concerned it would cause some mixing of functional and error-handling code. While the try-catch mechanism can be on the clumsy side, it forces one to make exception reroute execution from one block (try) to another (catch), which is where all the error handling is – Ryan Delucchi Jan 29 '09 at 07:24
  • 1
    This isn't used for error handling, but for *diagnostics*, only. This allows you to see the path by which your code got into an unexpected situation without interrupting your code's flow. I use this when the method itself can handle the unexpected situation, but still it shouldn't happen. – Eddie Jan 29 '09 at 15:48
  • 2
    you can also use new Exception("message").printStackTrace(); No throwing or catching required, but you still get a nice stacktrace in the log. Obviously, this shouldn't be in production code, but it can be very useful for debugging. – Jorn Mar 10 '09 at 22:58
9

If you are using Visual C++, utilize the override keyword whenever you over-ride a base class's method. This way if anyone ever happens to change the base class signature, it will throw a compiler error rather than the wrong method being silently called. This would have saved me a few times if it had existed earlier.

Example:

class Foo
{
   virtual void DoSomething();
}

class Bar: public Foo
{
   void DoSomething() override { /* do something */ }
}
David
  • 13,360
  • 7
  • 66
  • 130
Steve Rowe
  • 19,411
  • 9
  • 51
  • 82
  • for Java, this is class Foo { void doSomething(){} } class Bar { @Override void doSomething(){} } Will give a warning if it's missing the annotation (so you can't silently override a method you didn't mean to) and when the annotation is there but it doesn't override anything. – Jorn Mar 10 '09 at 23:03
  • Nice... I didn't knew about this one... too bad it seems to be Microsoft specific... but some good #defines can help to make it portable – e.tadeu Feb 09 '10 at 18:20
8

I've learned in Java to almost never wait indefinitely for a lock to unlock, unless I truly expect that it may take an indefinitely long time. If realistically, the lock should unlock within seconds, then I'll wait only for a certain length of time. If the lock does not unlock, then I complain and dump stack to the logs, and depending on what is best for the stability of the system, either continue on as if the lock unlocked, or continue as if the lock never unlocked.

This has helped isolate a few race conditions and pseudo-deadlock conditions that were mysterious before I started doing this.

Eddie
  • 53,828
  • 22
  • 125
  • 145
  • 1
    waits with timeouts used like this are a sign of other, worse, problems. – dicroce Jan 29 '09 at 14:18
  • 2
    In a system that has to have high uptime, it's better to at least get diagnostic information out so you can find the problem. Sometimes you prefer to exit a thread or return a response to the caller when the system is in a known state, so you wait on a semaphore. But you don't want to hang forever – Eddie Jan 29 '09 at 16:01
8

C#

  • Verify non-null values for reference type parameters in public method.
  • I use sealed a lot for classes to avoid introducing dependencies where I didn't want them. Allowing inheritance should be done explicitly and not by accident.
Brian Rasmussen
  • 114,645
  • 34
  • 221
  • 317
8

When you issue an error message, at least attempt to provide the same information the program had when it made the decision to throw an error.

"Permission denied" tells you there was a permission problem, but you have no idea why or where the problem occurred. "Can't write transaction log /my/file: Read-only filesystem" at least lets you know the basis on which the decision was made, even if it's wrong - especially if it's wrong: wrong file name? opened wrong? other unexpected error? - and lets you know where you were when you had the problem.

Joe McMahon
  • 3,266
  • 21
  • 33
  • 1
    When writing the code for an error message, read the message and ask _what you would want to know next_, then add it. Repeat until unreasonable. For example: "Out of range." What is out of range? "Foo count out of range." What was the value? "Foo count (42) out of range." What's the range? "Foo count (42) out of range (549 to 666)." – HABO May 06 '17 at 21:22
7

In C#, use the as keyword to cast.

string a = (string)obj

will throw an exception if obj is not a string

string a = obj as string

will leave a as null if obj is not a string

You still need to take null into account, but that is typically more straight forward then looking for cast exceptions. Sometimes you want "cast or blow up" type behavior, in which case (string)obj syntax is preferred.

In my own code, I find I use the as syntax about 75% of the time, and (cast) syntax about 25%.

Matt Briggs
  • 41,224
  • 16
  • 95
  • 126
  • Correct, but now you have to check for null before using the reference. – Brian Rasmussen Jan 29 '09 at 06:29
  • 7
    Didn't get it. Seems a bad decision to me, to prefer the null. You will get problems *somewhere* during runtime with no hint to the original reason. – Kai Huppmann Jan 29 '09 at 07:27
  • Yes. This is only useful if you actually do want null when it's not the correct type. Useful in some cases: in Silverlight where control logic and design are often separated, the logic wants to use the control "Up" only if it is a button. If not, it is as if it did not exist (=null). – Sander Jan 29 '09 at 08:17
  • don't forget that a safe cast is slower as well. – Spence Jan 29 '09 at 09:34
  • +1 to kai1968. When I know it's supposed to be a string I use string a = (string)obj; if I expect it to be something else I'll use as and then check for null. This way it fails early if something unexpected happens. – Michał Piaskowski Jan 29 '09 at 13:34
  • @kai1968: You still have to take the null into account. But it is both easier and more common to check for null then to go looking for cast exceptions. I find I use "as" about 75% of the time, and (cast) about 25%. – Matt Briggs Jan 29 '09 at 14:04
  • "easier", who cares? The question is about clever defensive programming. – bzlm Jan 30 '09 at 12:17
  • 2
    This seems about as defensive as large ballroom windows in a fortress. But it's a lovely view! – Pontus Gagge Mar 11 '09 at 14:56
  • 1
    This reminds me of someone who didn't use exceptions because 'they broke programs'. If you want certain behavior when an object is not a class you expect, I think I would code this another way. `is/instanceof` spring to mind. – Kirschstein Apr 21 '09 at 16:51
  • Interesting. in Delphi **as** is the safe cast, and will except on invalid cast; that's the one I prefer. The unsafe cast `TSomeOtherObject(AnObject)`, I only use if there's no possibility of an invalid cast. – Disillusioned Apr 22 '11 at 19:54
6

Be prepared for any input, and any input you get that is unexpected, dump to logs. (Within reason. If you're reading passwords from the user, don't dump that to logs! And don't log thousands of these sorts of messages to logs per second. Reason about the content and likelihood and frequency before you log it.)

I'm not just talking about user input validation. For example, if you are reading HTTP requests that you expect to contain XML, be prepared for other data formats. I was surprised to see HTML responses where I expected only XML -- until I looked and saw that my request was going through a transparent proxy I was unaware of and that the customer claimed ignorance of -- and the proxy timed out trying to complete the request. Thus the proxy returned an HTML error page to my client, confusing the heck out of the client that expected only XML data.

Thus, even when you think you control both ends of the wire, you can get unexpected data formats without any villainy being involved. Be prepared, code defensively, and provide diagnostic output in the case of unexpected input.

Eddie
  • 53,828
  • 22
  • 125
  • 145
6

Java

The java api has no concept of immutable objects, which is bad! Final can help you in that case. Tag every class that is immutable with final and prepare the class accordingly.

Sometimes it is useful to use final on local variables to make sure they never change their value. I found this useful in ugly, but necessary loop constructs. Its just to easy to accidently reuse a variable even though it is mend to be a constant.

Use defense copying in your getters. Unless you return a primitive type or a immutable object make sure you copy the object to not violate encapsulation.

Never use clone, use a copy constructor.

Learn the contract between equals and hashCode. This is violated so often. The problem is it doesn't affect your code in 99% of the cases. People overwrite equals, but don't care about hashCode. There are instances in wich your code can break or behaves strange, e.g. use mutable objects as keys in a map.

raupach
  • 3,092
  • 22
  • 30
6

I try to use Design by Contract approach. It can be emulated run time by any language. Every language supports "assert", but it's easy and covenient to write a better implementation that let you manage the error in a more useful way.

In the Top 25 Most Dangerous Programming Errors the "Improper Input Validation" is the most dangerous mistake in the "Insecure Interaction Between Components" section.

Adding precondition asserts at the beginning of the methods is a good way to be sure that parameters are consistent. At the end of methods i write postconditions, that check that output is what's inteded to be.

In order to implement invariants, I write a method in any class that checks "class consistence", that should be called authomatically by precondition and postcondition macro.

I'm evaluating the Code Contract Library.

Zen
  • 917
  • 1
  • 7
  • 20
5

I forgot to write echo in PHP one too many times:

<td><?php $foo->bar->baz(); ?></td>
<!-- should have been -->
<td><?php echo $foo->bar->baz(); ?></td>

It would take me forever to try and figure out why ->baz() wasn't returning anything when in fact I just wasn't echoing it! :-S So I made an EchoMe class which could be wrapped around any value that should be echoed:

<?php
class EchoMe {
  private $str;
  private $printed = false;
  function __construct($value) {
    $this->str = strval($value);
  }
  function __toString() {
    $this->printed = true;
    return $this->str;
  }
  function __destruct() {
    if($this->printed !== true)
      throw new Exception("String '$this->str' was never printed");
  }
}

And then for the development environment, I used an EchoMe to wrap things which should be printed:

function baz() {
  $value = [...calculations...]
  if(DEBUG)
    return EchoMe($value);
  return $value;
}

Using that technique, the first example missing the echo would now throw an exception ...

too much php
  • 88,666
  • 34
  • 128
  • 138
4

C++

When I type new, I must immediately type delete. Especially for arrays.

C#

Check for null before accessing properties, especially when using the Mediator pattern. Objects get passed (and then should be cast using as, as has already been noted), and then check against null. Even if you think it will not be null, check anyway. I've been surprised.

mmr
  • 14,781
  • 29
  • 95
  • 145
  • I like your first point. I do similar things when, for example, writing a method that returns a collection of something. I create the collection on the first line, and immediately write the return statement. All that's left is filling in how the collection is populated. – Tim Frey Jan 29 '09 at 14:54
  • 5
    In C++, when you type new, you should immediately assign that pointer to an AutoPtr or reference-counted container. C++ has destructors and templates; use them wisely to handle the deletion automatically. – An̲̳̳drew Jan 31 '09 at 03:56
4

Use sentinel classes with certain interface based OOP patterns instead of null.

E.g. when using something like

public interface IFileReader {
  List<Record> Read(string file);
}

use a sentinel class like

public class NoReader : IFileReader {
  List<Record> Read(string file) {
    // Depending on your functional requirements in this case
    // you will use one or more of any of the following:
    // - log to your debug window, and/or
    // - throw meaningful exception, and/or
    return new List<Record>(); // - graceful fall back, and/or
    // - whatever makes sense to you here...
  }
}

and use it to initialize any IFileReader variable

IFileReader reader = new NoReader();

instead of just leaving them to null (either implicitly or explicitly)

IFileReader reader; /* or */
IFileReader reader = null;

to make sure you don't get unexpected null pointer exceptions.

Bonus: you don't really have to encase each and every IFileReader variable use with an if (var!=null) ... any more either because they won't be null.

peSHIr
  • 6,279
  • 1
  • 34
  • 46
  • If you want/need checking for null, you could always check for equality with the sentinel, or included a bool IsNull() in the interface that returns true in the sentinel and false from any concrete implementations. You can still always call methods on such variables without null checks then. – peSHIr Jan 29 '09 at 07:17
  • +1, This is a good one. I do it quite often in fact. – Ryan Delucchi Jan 29 '09 at 07:27
  • I found by my experience that this solution is wrong. If something goes wrong the application shoult fail hard so that the bug is impossible to be ignored ("Code complete"). This means NullPointer Exception in place of error and apropriate catch block at che user interfece level. – Łukasz Bownik Jan 29 '09 at 07:50
  • 1
    Whether or not to fail hard is very application dependent. Hard fails may make for simpler debugging, but if you can recover without data loss, your users might thank you for failing more softly. – Kim Reece Jan 29 '09 at 21:26
  • +1 - in many cases, you don't care whether the variable isn't set, but you want to do something if it is (consider iterating over zero-length arrays). It also makes you think about how to handle exceptional conditions, rather than simply letting the program bomb – kdgregory Jan 30 '09 at 00:54
  • 1
    @lbownik: See my other answer to this question! This is very specific for certain OOP situations. And you probably did see the "// - throw meaningful exception" in my above example as well? I'd rather have that than a generic null pointer exception any time... – peSHIr Jan 30 '09 at 08:15
  • @feonixrift: I agree this can also very application dependant. However, hard fails in individual methods should not mean hard fails that the user gets to see (see http://is.gd/hMAd and you do test you app before the user sees it in production, right?), just easier debugging traces. – peSHIr Jan 30 '09 at 08:53
4

Use a logging system that allows dynamic, run time log level adjustments. Often if you have to stop a program to enable logging, you'll lose whatever rare state the bug occurred in. You need to be able to turn on more logging information without stopping the process.

Also, 'strace -p [pid]' on linux will show you want system calls a process (or linux thread) is making. It may look strange at first, but once you get used to what system calls are generally made by what libc calls, you'll find this invaluable for in the field diagnosis.

dicroce
  • 45,396
  • 28
  • 101
  • 140
4

Always compile at the highest warning level, and treat warnings as errors (build breakers).

Even if the code is "right" fix the cause of the warning without disabling the warning if at all possible. For example, your C++ compiler might give you a warning for legal code like this:

while (ch = GetNextChar()) { ... }

It looks like you might have typed = instead of ==. Most compilers that offer this (useful) warning will shut up if you add an explicit check.

while ((ch = GetNextChar()) != 0) { ... }

Being slightly more explicit not only silences the warning but also helps the next programmer who has to understand the code.

If you MUST disable a warning, use a #pragma in the code, so you can (1) limit the span of code for which the warning is disabled and (2) use comments to explain why the warning must be disabled. Warnings disabled in command lines or makefiles are disasters waiting to happen.

Adrian McCarthy
  • 45,555
  • 16
  • 123
  • 175
3

when getting a table from a dataset

if(  ds != null &&
     ds.tables != null &&
     dt.tables.Count > 0 &&
     ds.tables[0] != null &&
     ds.tables[0].Rows > 0 )
{

    //use the row;
}
John Boker
  • 82,559
  • 17
  • 97
  • 130
3

For C++ : automatically detecting size of arrays

char* mystrings[] = { "abc", "xyz" , "pqr" }

typically then for is written like

for (int i=0; i< 3; i++)
{
    str= mystrings[i]
    // somecode
}

However, Later you may add new more strings to 'mystrings'. In that case, the for loop above may introduce subtle bugs in the code.

solution that i use is

int mystringsize = sizeof(mystrings)/sizeof(char*)
for (int i=0; i< mystringsize; i++)
{
    str= mystrings[i]
    // somecode
}

Now if you add more strings to 'mystrings' array, for loop will be automatically adjusted.

Nitin Bhide
  • 1,685
  • 14
  • 15
3

My C++ guidelines, but I don't consider this to be clever:

  • Always lint, heck, make it part of your makefile. Better yet, use coverity if possible.
  • Don't use C++ exceptions.
  • Don't put too much stuff on C++ constructor. Use init() method instead. The only ways to signal an error in constructor is exceptions, which is PITA.
  • Don't overload operator unless it's necessary.
  • If your constructor has one argument, always use explicit keyword.
  • Avoid global objects. Their execution order is not guaranteed.
  • Define copy constructor when your class allocates a memory. But if you don't expect the class to be copied, and you're too lazy to define one, guard it from being called.

class NonCopied {
private:
    NonCopied(const NonCopied&);
    NonCopied& operator=(const NonCopied&);
}
  • Stop using sprintf(), strcpy(), strcat(). Use their replacement instead, eg. snprintf, strncpy(), etc.
KOkon
  • 636
  • 1
  • 4
  • 13
  • Why do your constructors even need arguments, if their only role is to create an object to call `.init(arguments)` on ? It seems to me that with this coding style, you can alway accept the default constructor and never need one-arg ctors, let alone `explicit`. – MSalters Sep 30 '10 at 13:21
  • Don't use C++ exceptions?? – Mawg says reinstate Monica Jan 19 '18 at 11:19
3

Use a console, like in games;

Not completely "defensive" but I got this from seeing it in a lot games.

I like to have a full console for all my applications which allow me to:

  1. Define simple commands to be invoked from the console (like swiching to debug mode, setting some runtime variables, check internal configuration parameters and so on).
  2. Access a log everytime I want from the application while application is running.
  3. Save the log to a file if needed
  4. Log every unhandled exception to the console before raising it to the user (if appropiate). That way every exception is caught as some level. If you combine this cleverly with debug information or a map file you can get excelent results.

In C# if you mark the Console methods with the Conditional Attribute then they will be automatically stripped from the release version. In other languages the same can be achieved through preprocessor directives.

I've found it to be specially valuable during testing phase as it allows the developer to see what's happening and the tester to provide better feedback to the developer.

In addition:

  • Never catch an exception just for loggin.
  • Never catch general exceptions (exception E)
  • Never hide exceptions
  • Treat compiler warnings as if they were errors, only accept a warning with a very careful study.
  • Always check every input coming from outside the library.
  • Check the input coming from inside the library in "debug", don't check in release.
  • Never raise a generic exception. If an exception exists that describe the problem use it, if don't, create your own.
Jorge Córdoba
  • 51,063
  • 11
  • 80
  • 130
3

In C++ assert() is a very handy tool. I do not only provide it with the condition to evaluate but also with a message stating what's wrong:

assert( isConditionValid && "ABC might have failed because XYZ is wrong." );

When there is no actual variable to check or you find yourself in a situation that should never have occured ('default' handler of switch()) this works too:

assert( 0 && "Invalid parameter" );

It not only asserts in debug mode but also tells you what went wrong at the same time.

I got this from the "C++ Coding Standards" if I remember correctly.

vobject
  • 5,290
  • 3
  • 29
  • 21
3

In Python, if I stub out (or change a method) and then don't have time to test it that day, I cram in an "assert False" so that the code will crash if the method is run, creating embarrassing errors I'll notice the next day. An intentional syntax error can be helpful as well.

Example:

def somefunction(*args,**kwargs):
    ''' <description of function and args> '''
    # finish this in the morning
    assert False, "Gregg finish this up"
Gregg Lind
  • 20,690
  • 15
  • 67
  • 81
  • Similarly, .NET has `System.NotImplementedException`, and in Java you have Apache Commons providing a `NotImplementedException` type, which you can throw if you don't have the time to finish the method that day. I'm sure the same concept exists in other languages and frameworks as well. Of course, something like that should ideally never make it into centralized source control (though it could make it into something like your local git repository). – user Jun 08 '15 at 05:59
3

Remember that exceptions are a programmer's best friends - never eat them!

Vector
  • 10,879
  • 12
  • 61
  • 101
3
  • Tiny understandable classes. Many of them.
  • Tiny understandable Methods.
  • Immutable wherever possible.
  • Minimize scope--nothing public that can be package, nothing package that can be private.
  • never any excuse for a public mutable variable.

Also, when your classes are tiny and generally final, being defensive is really cheap--might as well throw it in regardless of if you believe in it or not. Test the values being passed to your constructors and (if you really MUST have them) setters.

Bill K
  • 62,186
  • 18
  • 105
  • 157
2

In Perl, die() when subroutines aren't passed enough parameters. This prevents you from getting failures that you have to trace back up 10 levels through the stack.

sub foo {
    my $param0 = shift or confess "param0 is a required param";
    my $param1 = shift or confess "param1 is a required param";
    my $param2 = shift or confess "param2 is a required param";
    ...
}
Eric Johnson
  • 17,502
  • 10
  • 52
  • 59
  • This is insanely verbose. Isn’t it better to rely on function prototypes, ie. declare foo($$$) and have perl check for you? This is not always possible, but when it is, it is a much better solution, IMHO. – zoul Jan 29 '09 at 07:05
  • Well, actually, prototypes cause more trouble than they're worth. If you need 4 parameters, why not check whether scalar @_ == 4? – Joe McMahon Jan 30 '09 at 23:16
  • What kind of problems do prototypes cause? – zoul Jan 31 '09 at 21:26
  • http://stackoverflow.com/questions/297034/why-are-perl-function-prototypes-bad – zoul Feb 15 '09 at 12:46
2

Design your logging strategy so that when an error occurs in production, the appropriate support person or developer is emailed automatically. This allows you to proactively find bugs, rather than waiting for users to complain.

Note that this should be done with some caution. One example I had was that a developer had written some logging code inside a loop. After a few months an error in the system triggered this code. Unfortunately the application sat in that loop, logging the same error over and over again. We arrived in the office that morning to be informed that our mail server had crashed after our logging framework sent 40,000 emails between the hours of 4am and 8am!

Richard Ev
  • 52,939
  • 59
  • 191
  • 278
davogones
  • 7,321
  • 31
  • 36
2

In C++

I spread out asserts all over my functions, especially at start and end of functions to catch any unexpected input/output. When I later add more functionality in a function the asserts will help me remember. It also helps other people to see the intention of the function and are only active in debug mode.

I avoid pointers as much as possible and instead use references, that way I don't need to put cluttering if (NULL!=p)-statements in my code.

I also use the word const as often as I can both in declarations and as function/method arguments.

I also avoid using PODs and instead use STL/Boost as much as possible to avoid mem leaks and other nasty things. However I do avoid using too much custom defined templates as I find them hard to debug, especially for others who didn't write the code.

Winter
  • 3,894
  • 7
  • 24
  • 56
AndersK
  • 35,813
  • 6
  • 60
  • 86
2

Back to those days where RAM was not free, most computers were very limited and "NOT ENOUGH MEMORY !" was a pretty common error message...

Well, most application were then able to crash with 'elegance' : users (almost) never lost their works.

(Almost, I said ! ^^).

How was it done ? Very simple : when you app starts, allocate a balloon of RAM (say, a whopping 20 KB!). Then, when a call to malloc() fails :

  1. Say kindly that there is "NOT ENOUGH MEMORY" (this message was mandatory).
  2. Add "And you better save all your work. Now!"
  3. Release the whopping 20 KB balloon of RAM.
  4. Resume.

Et voilà. Your app is crashing slowly at the user, most of the time, can save it's work.

Sylvain Rodrigue
  • 4,751
  • 5
  • 53
  • 67
2

Try not to build anything you design for a few weeks. Often other scenarios will come to you then before things get locked in.

Jas Panesar
  • 6,597
  • 3
  • 36
  • 47
2
  • Make your code as readable as possible, especially by using function and variable names that are as obvious as possible. If this means that some names are a bit on the long side, then so be it.

  • Use a static analyser as much as possible. You soon get into the habit of writing code that conforms to its rules.

  • During development, make it easy to turn on diagnostic output - but make it easy to turn them off for production.

Steve Melnikoff
  • 2,620
  • 1
  • 22
  • 24
2

Don't pass around naked collections, even generics. They cannot be protected and they cannot have logic attached to them.

A good parallel would be having a public variable instead of setter/getter. the setter/getter allows you to change your underlying implementation without effecting the outside world.

How do you change your data structure without effecting the outside world if you are passing around a collection? All the access for your collection is distributed throughout all your code!!

Instead, wrap it and give yourself a place to put a little business logic. You'll find some nice refactors once you've done so.

Often you'll find it makes sense to add some variables and maybe a second collection--then you'll realize this class has been missing all along!

Bill K
  • 62,186
  • 18
  • 105
  • 157
  • +10 if I could. Really often ran into this one. And one day you realize you need a `Map` instead of a `List` and you're all set with a wrapper class. – Atmocreations Jul 30 '14 at 15:12
2

When doing multi-threaded C/C++ programming, create a series of macros that assert your function is being called on the thread you think its being called on. Then use them liberally.

  • ASSERT_ON_UI_THREAD
  • ASSERT_ON_WORKER_THREAD
  • ASSERT_ON_THREADPOOL_THREAD
  • ASSERT_ON_DOWNLOAD_THREAD
  • etc.

Use GetCurrentThreadId() on Windows or pthread_self() on Posix when the thread is initialized, then store in globals. The asserts compare against the stored value.

Has saved me LOTS of painful debugging, especially when someone else refactors existing multi-threaded code.

i_am_jorf
  • 53,608
  • 15
  • 131
  • 222
1

So, who among us hasn't accidentally locked up Visual Studio for a while when writing a recursive method?

  int DoSomething(int value)  // stupid example for illustrative purposes
  {
      if (value < 0)
          return value;
      value++;  // oops
      return DoSomething(value);
  }

To avoid the annoyance of having to wait, and sometimes potentially having to kill off your IDE with task manager, include this in your recursive method while you're debugging it:

  int DoSomething(int value)
  {
>>    if (new StackTrace().FrameCount > 1000)  // some appropriately large number
>>        Debug.Fail("Stack overflow headed your way.");

      if (value < 0)
          // some buggy code that never fires
      return DoSomething(value);
  }

This may seem like it would be slow, but in practice checking the FrameCount is quite fast (less than a second on my PC). You can take this failsafe out (or maybe just comment it out, but leave it for later debugging) after you're sure the method is working properly.

Ryan Lundy
  • 204,559
  • 37
  • 180
  • 211
1

If (some really bad condition) Then
Throw New Exception("particular bad thing happened")
End If

Usually this takes the form

Public SUb New (key As Guid)
Dim oReturn As returnpacket = Services.TableBackedObjectServices.GetData(key)
If oReturn.ds.tables(0).Rows.Count = 0 then Throw New Exception("TableBackedObject loaded from key was not found in the database.")
End If

Since that particular constructor is only supposed to be called when loading a particular object after selecting it from the results of a search procedure, not finding it is either a bug or a race condition (which would mean another user deleted the object by key).

Joshua
  • 40,822
  • 8
  • 72
  • 132
  • 1
    Never, ever, ever, *ever* throw `Exception`. [Throw an exception type that actually *says something*.](http://programmers.stackexchange.com/a/128293/6384) Use details fields on the exception to provide additional relevant information about the error condition and application state. – user Jun 08 '15 at 06:07
  • 99% of exception handling is done wrong by all parties anyway. To fix this, JDBCException / SQLException must be broken up and all libraries implemented on top of them obsoleted. – Joshua Jun 08 '15 at 15:09
1

Some things I do in PHP (where mistakes are easy and often catastrophic):

  • Turn on all the syntax highlighting cues in Vim. There's a lot turned off by default (do :help php to see them). I'm thinking of adding a few error-highlighting things of my own...
  • Using a pre-commit hook in git to syntax-check (php -l) every changed file. It only prevents basic errors getting in, but it's better than nothing.
  • Writing wrappers around the database classes to make parameterised prepared statements brain-dead easy compared to typing out normal queries - $db->q1($sql, $param1, $param2) to fetch a single column of the first row, and so on.
  • Configuring it (via the Xdebug extension) to spit out gigantic HTML tables of debug info for even trivial warning messages, so it's impossible to ignore them. On the dev server, that is. On production they get silently logged instead.
  • Making things short, simple and obvious. I spend a lot of time just refactoring stuff for the sake of making smaller files.
  • Using the explicit control structure syntax to avoid having several "}"s in close proximity.
  • Proofreading code before it's checked in. I've got into a habit of maximising the window, then setting an absurdly large font size. If I can only make sense of it when I can see 132C x 50R on screen at once in a tiny font, it's too long to begin with.
1

In c# usage of TryParse instead of Parse for value types to avoid exceptions like FormatException, OverflowException etc, of course to avoid writing the try block for the same.

Bad code

string numberText = "123"; // or any other invalid value

public int GetNumber(string numberText)
  {
  try
  {
     int myInt = int.Parse(numberText);
     return myInt;
  }
  catch (FormatException)
  {
    //log the error if required
     return 0;
   }
  catch (OverflowException)
  {
     return 0;
  }
}

Good code (if you don't want to handle errors)

string numberText = "123"; // or any other invalid value
public int GetNumber(string numberText, int defaultReturnValue)
  {
    int myInt;
    return ( int.TryParse(numberText, out myInt) ) ?  myInt : defaultReturnValue;
}

You can do the same for almost all the value types e.g: Boolean.TryParse, Int16.TryParse, decimal.TryParse etc

Binoj Antony
  • 15,886
  • 25
  • 88
  • 96
  • This is dodgy if the calling routine may expect 0 or -1 or any arbitrary number you choose as "invalid" to be a valid possibility. Rather explicitly indicate the failure to convert the text to a number. It's hiding a possible error, and even worse - misinforming users of your method! – Disillusioned Apr 22 '11 at 20:05
  • Better yet, that's the whole point of `TryParse`... why write a method that wraps `TryParse` making `GetNumber("0")` and `GetNumer("dfgsdfg")` indistinguishable when you could just call `TryParse`? – Disillusioned Apr 23 '11 at 00:09
  • @Craig - updated ans to reflect your comments – Binoj Antony May 02 '11 at 07:04
1

In C#: Instead of this:

if( str==null )

Do this:

if( String.IsNullOrEmpty(str) )
dso
  • 9,463
  • 10
  • 53
  • 59
  • 1
    WARNING! Do this **if** and **only if** in the relevant piece of code `(str==null)` can be considered _exactly equivalent_ to `(str=='')`. Otherwise you're simply _hiding_ a problem which will bite you badly later. – Disillusioned Apr 23 '11 at 20:11
1

In C#, use 'using' to make sure object is disposed when it goes out of scope. i.e.

        using(IDataReader results = DbManager.ExecuteQuery(dbCommand, transaction))
        {
            while (results.Read())
            {
                //do something
            }
        }

Also, check for null values after casting

        MyObject obj = this.bindingSource.Current as MyObject;
        if (MyObject != null)
        {
           // do something
        }

Also, I use enums whenever possible to avoid hardcoding, typos and to provide easy renaming if required, i.e.

    private enum MyTableColumns
{ 
    UserID,
    UserName
}

private enum StoredProcedures
{
    usp_getMyUser,
    usp_doSomething
}

public static MyUser GetMyUser(int userID)
{
    List<SqlParameter> spParameters = new List<SqlParameter>();

    spParameters.Add(new SqlParameter(MyTableColumns.UserID.ToString(), userID));


    return MyDB.GetEntity(StoredProcedures.usp_getMyUser.ToString(), spParameters, CommandType.StoredProcedure);
}
Evgeny
  • 3,320
  • 7
  • 39
  • 50
1

Include high-level exception handling, as described in detail here

Top-level Exception Handling in Windows Forms Applications

My Program.cs would then look like this

    static class Program
    {
    [STAThread]
    static void Main()
    {
        Application.ThreadException += 
            new ThreadExceptionEventHandler(new ThreadExceptionHandler().ApplicationThreadException);

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new MainForm());
    }

    public class ThreadExceptionHandler
    {
        public void ApplicationThreadException(object sender, ThreadExceptionEventArgs e)
        {
            MessageBox.Show(e.Exception.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }
}
Evgeny
  • 3,320
  • 7
  • 39
  • 50
1

Don't use single-character variables for loop indexes. For example:

for (int ii = 0 ; ii < someValue ; ii++)
    // loop body

This is a simple habit, but it's very helpful if you have to use a standard text editor for find references to the loop variable. Of course, indexed loops typically shouldn't be so long that you need to search for the index references ...

kdgregory
  • 38,754
  • 10
  • 77
  • 102
  • Only useful in language that do not have more generic collection types and a for-each type operation on it. There, you hardly ever use loop index variables. – peSHIr Feb 02 '09 at 08:37
  • peSHIr: I wish that were true. I find I need indexes while iterating through Java lists a lot. (For example, when simultaneous iterating over two lists) – Jorn Mar 10 '09 at 23:14
  • 1
    Why would you ever have to use a standard text editor for editing code? – Jorn Mar 10 '09 at 23:15
1

C++:

Avoid raw pointers, always use the Boost smart pointer package (e.g., shared_ptr).

  • 1
    Of course `tr1::shared_ptr` for c++03 and `std::unique_ptr` and `std::shared_ptr` for c++11 are also good alternatives – Grizzly Aug 30 '12 at 22:43
1

Language agnostic: Do never rely on compilers, virtual machines, etc. regarding initialisation. Always initialise your variables explicitly to helpful values.

Assertions are your best friend, although unit testing could fit better in some cases.

C/C++: Use stack based objects whenever possible.

In conditionals, check explicitly for the value that you expect or don't expect. For example if you have a boolean variable called activated instead of writing if (activated) write if (true == activated). The reason is that activated might contain garbage good enough to make the conditional succeed.

sakisk
  • 1,807
  • 1
  • 24
  • 30
1

I do a lot of math in my work testing mixed signal semiconductors on Automatic Test Equipment from Teradyne (c, vba), Advantest(c++ .net), and the like.

Two defensive maneuvers I use are:

  • prevent division by zero, if (x!=0) { z=y/x; } else { /* give z a recognizable fake number, continue program */ }

  • don't pass zero or negative numbers to log calculations. This is common for calculations of gain, CMRR, and PSRR. if (x>0) { psrr = 20 * log (x); } else { psrr = -999 ; /*fake number */ }

Some may argue against using fake numbers, but these programs are used in very high volume semiconductor manufacturing. If an error happens while testing a bad part, it is better to continue testing and to keep the integrity of the data format. The fake numbers are easily separated as outliers during post-processing of test data.

-- mike

Mike
  • 41
  • 1
  • 6
  • Don't compare with 0, make decimal distance calculation instead and compare it with reasonable small number, i.e. `if (abs(x-0.001) > 0.001) { // ... }` – Brian Cannard Nov 27 '13 at 22:49
1

JavaScript:

We should use "==" and "===" appropriately.

== : type-converting equality comparison

=== : strict equality comparison

For example, '1'==1 is true, but '1'===1 is false.

Many people use "==" instead of "===" unconsciously.

grayger
  • 931
  • 8
  • 19
1

If there's a value type that has certain constraints on its value, make a class where those constraints are enforced by code. Some examples:

public class SanitizedHtmlString
{
private string val;

public SanitizedHtmlString(string val)
{
  this.val = Sanitize(val);
}

public string Val
{
  get { return val; }
}

//TODO write Sanitize method...
}


public class CarSpeed
{
private int speedInMilesPerHour; 

public CarSpeed(int speedInMilesPerHour)
{
  if (speedInMilesPerHour > 1000 || speedInMilesPerHour < 0)
  {
    throw new ArgumentException("Invalid speed.");
  }
  this.speedInMilesPerHour = speedInMilesPerHour; 
}

public int SpeedInMilesPerHour
{
  get { return speedInMilesPerHour; }
}
}
RossFabricant
  • 12,364
  • 3
  • 41
  • 50
1

Crash-Only software, in short instead of requiring some shutdown procedure along with some seldomly used (and hence probably buggy) recovery code, always stop the program by "crashing it" and thus always run the recovery code when starting.

This is not applicable to everything, but in some cases it's a very neat idea.

janneb
  • 36,249
  • 2
  • 81
  • 97
0

Not needing to contend with the language's limitations is the best defense I can employ in my program's logic. Sometimes it is easier to state when things should stop.

For example you have this kind of loop:

while(1)
{
  // some codes here

  if(keypress == escape_key || keypress == alt_f4_key 
     || keypress == ctrl_w_key || keypress == ctrl_q_key) break;

  // some codes here
}

If you want to put the condition on loop header, instead of battling the language for not having an until construct, just copy the condition verbatim and put an exclamation mark:

while(! (keypress == escape_key || keypress == alt_f4_key 
     || keypress == ctrl_w_key || keypress == ctrl_q_key) )
{ 
    // some codes here
}

There's no until construct on C-derived languages, so just do the above, otherwise do this(possible in C/C++, use #define ;-)

until(keypress == escape_key || keypress == alt_f4_key 
     || keypress == ctrl_w_key || keypress == ctrl_q_key)
{ 
    // some codes here
}
Michael Buen
  • 38,643
  • 9
  • 94
  • 118
  • The loops are not exactly the same, that's why there's a difference between do until and while. Do until guarantees at least one execution. Your while might actually never be executed. – Jorge Córdoba Jan 29 '09 at 17:38
  • This 'until' is very useful in lot of defensive loop code, IMO. – Brian Cannard Nov 27 '13 at 22:41
0

Rather then var.equals("whatever") in java I do "whatever".equals(var). That way, if var is null I don't have to worry about a nullpointer exception. That works great when dealing with things like URL parameters, etc.

Chad Okere
  • 4,570
  • 1
  • 21
  • 19
0

Hardly clever, but a decent practice, perhaps. In C/C++:

Always return from a function at the bottom, never in the middle. The sole exception to this is a check for null on required arguments; that always comes first and immediately returns (otherwise I'd just be writing a big "if" condition at the top which just looks silly).

int MyIntReturningFuction(char *importantPointer)
{
    int intToReturn = FAILURE;
    if (NULL == importantPointer)
    {
        return FAILURE;
    }
    // Do code that will set intToReturn to SUCCESS (or not).
    return intToReturn;
}

I have seen a lot of arguments for why it doesn't really matter, but the best argument for me is simply experience. Too often I've scratched my head, asking "Why the heck doesn't my break point near the bottom of this function get hit?" only to find that someone other than me had put a return somewhere above (and usually changing some condition that should have been left alone).

I've also found that having very simple rules like this makes me a much more consistent coder. I never violate this rule in particular, so sometimes I have to think of alternative ways of handling things (such as cleaning up memory and such). So far, it has always been for the better.

Adam
  • 433
  • 5
  • 11
  • Doesn't "my break point near the bottom doesn't get hit" === "must be returning before the breakpoint"? Isn't that more useful than "my breakpoint is getting hit" && "something's wrong in the code before that"? Ie, looking specifically for a return, rather than just "something is wrong somewhere"... – jTresidder Jan 31 '09 at 13:59
  • Yes, it could; or the function isn't even being entered when expected. I often debug the function chain first. If a bp isn't being hit, I assume something further of the chain caused a fork, not something within the function where I've set my bp. Mostly, it's a rule that helps me organize my code. – Adam Feb 02 '09 at 08:02
  • IMO if it's not immediately obvious that there is a `return ` somewhere in the function it is likely too long and/or too complex and should be refactored into smaller functions (as always there are exceptions). On the other hand allowing `return` only at the end often makes for longer/more complex code (due to additional `if`s and such), making it harder to find errors – Grizzly Aug 30 '12 at 22:37
0
  • When executing SQL queries from your code, always use placeholders
  • MySQL has a useful non-standard extension of the DELETE statement: DELETE FROM sometable WHERE name IS LIKE 'foo%' LIMIT 1. This way you won't wipe the whole table in case of mistake.
Eugene Morozov
  • 15,081
  • 3
  • 25
  • 32
0

Language agnostic : issue : reporting and dealing with portions of a whole. Whenever calculations and percentages are bing displayed, I always keep a running total and for the last entry its value is not calculated like the rest, but by subtracting the running total from 100.00. In this fashion, if some interested party chooses to add up all the componenet percentages they will add exactly to 100.00

guzzibill
  • 81
  • 6