2

We use assertions to check for illegal behaviour which just shouldn't happen if everything is working as it should be, such as using NULL as argument when it clearly shouldn't.

This is all very well when you write public functions since you can't trust that the programmer who will use them won't make a mistake. But what about private functions, which won't be accessible from the outside? Of course, the function which uses those private functions may contain a bug (i.e. you made a mistake), but should we always use assertions in private functions? Is there a line where we can say "Hey, we don't need an assertion here because due to previous assertions and usage of the private function, we can assume that the parameters are always safe"?

Now I myself am a bit skeptical about that last part - can we ever safely assume that things are always as they should be?

3
  • If a private function is sufficiently large, and something should not have happened, then why not assert? They should not cost anything in a production code. Now ... if you are using a non-pointer, high-level language such as Java, C#, Python, then perhaps you would want to throw an exception once in a while, since some checks are best done in Release mode as well. Some things become a tautology, such as if (x == null) { throw new ArgumentNullException("x"); } :), so do not overdo it.
    – Job
    Commented Mar 25, 2011 at 23:38
  • 1
    You should probably specify what do you mean by assertions (and in what language) for the readers with different backgrounds/experience. For example in C#, you should never use Assert for null values in arguments, neither public, nor private. Instead, you should use exceptions (NullArgumentException) or can use code contracts. Commented Mar 26, 2011 at 0:00
  • Yes include them. In fact, if an important enough method, then you should even consider having unit tests for it. Unfortunately, this would typically mean that the scope for the method would have to be at least internal (not private), but it's usually worth the tradeoff. (Again, if the method is important and non-trivial enough.) Commented Mar 26, 2011 at 0:16

5 Answers 5

3

Honestly, unless you writing seriously time critical code then using assertion in what ever form they show up (could be as simple as checking return values or validating passed parameters) are extremely helpful especially in production software. I can identify at least 2 reasons that this is true.

First, client/customers do not want their software to crash. If your software blows up (whatever that means) it looks way worse from a reputation and customer satisfaction stand point than simply failing gracefully. Often you might get feedback such as "This one feature seems to be broken, but the rest of system works fine...just wanted to let you know...its not high priority." If blows up then it makes your software look bad.

Second, it is invaluable from a debug stand point. Your code will have bugs. I don't care how good you think you are, something is going to break. If you have checks or assertions and possible a way of notifying or logging this condition then it will always be faster and easier to find and fix the problem.

Third and I know I said I had only two, define public interface. If someone is modifying your code can you still make the "assertion" that the private function is private? From a maintainability standpoint assertions or checks are a lifesaver. I don't how many time I have seen a bug related to fact the the C std lib does not check for null pointers...i.e. strdup(). Plain and simple, it is just good defensive programing to use assertions and/or checks.

1
  • "client/customers do not want their software to crash ". That depends on the situation. For example, if an iPhone app crashes, you just tap on the app, and it runs again - there are users who don't even notice this! While an app that "fails gracefully" can leave the user in a situation where they don't know how to proceed.
    – gnasher729
    Commented May 20, 2015 at 16:20
1

Now I myself am a bit skeptical about that last part - can we ever safely assume that things are always as they should be?

Yes we can, right after we've asserted it of course.

Assertions are good. Avoid expensive computation in assertion, and optimize the check:

// C (in debug mode)
// unlikely is a hint to the compiler that the branch is unlikely to be taken
#define assert(x) if(unlikely(!(x))) { abort(); }

Assertions bring you:

  • an added level of safety (on top of the tests)
  • help with debugging (when you read the function looking for the bug, the assertions at the top establish preconditions)

The only question is what to do in case an assertion fires.

Personally, I recommend a different behavior between the Debug and Release build:

  • in Debug: abort, and make sure to get a memory dump. This way you cannot overlook it and you have (almost) all you need to track it down.
  • in Release: throw (and log, if possible), this way, you can recover gracefully, which is important for a delivered product or a running server.

The latter is obviously wishful thinking, if profiling shows that some assertions cause a performance hit, then you'll have to strip them from the release build (and write a comment indicating why they were stripped).

0

Well, there's a legitimate argument whether you should use assertions at all, but if you do, why do you want to use them less in your own functions? If anything, you should handle failure more gracefully in a public interface (?)

They're not supposed to go off as such, but to make it as clear as possible (second only to a static type check) under what context you're supposed to use the function. Think of them like a comment that says "// this argument should never be null", but where you really mean it.

After all, if you do get it right, you don't care if they're there or not. And if you don't (and believe me, it will happen sooner or later), would you rather the error was immediately clear? Or buried in the implementation of the function (or worse, in the result)?

0

Assertions are generally good for developing, good for testing and good for documentation.

The only real issue is whether there is an unacceptable performance hit. If so, remove them at final compilation. If not then leave them.

3
  • Don't they typically effectively disappear in a release build?
    – Job
    Commented Mar 25, 2011 at 23:39
  • That's true for C/C++; there is an option in Java which I have used aiming for "fail early rather than run wrong".
    – Henry
    Commented Mar 26, 2011 at 0:07
  • 2
    @job: typically yes, but imo it's way better to have them in release builds as well, especially to track down those nasty bugs only occurring in release builds
    – stijn
    Commented Mar 26, 2011 at 9:36
0

Some Languages (Scala, Haskell) have special types instead of null-checks, named Option and Maybe.

In statically typed languages, you can per se implement many checks with the type system.

Maybe you have a framework with unit-tests, to prevent foreseeable errors.

Checking your private methods in the one way or the other seems more important to me, than how to check it.

Not the answer you're looking for? Browse other questions tagged or ask your own question.