9

I'm a fan of using assertions in the code to check for preconditions. The question is whether is it wise to use assertions in public methods to check the precondition?

My personal opinion is, that if my method can not handle the absence of a parameter (or some invalid value of it) and it is part of an API but does not rely on user input, then the issue (bad parameter) must be handled during the development process (at least by the integration tests) and not later when the software is used on field. For this reason I do use assertions even in public methods.

I mean something like this:

public class SomeMagic implements MagicAPI {

    public WoW doSomeMagic( Stuff source ) {
        assert source != null : "Incorrect use of the API";

        // if assertions are deactivated (should be the case in production environment)
        // this line will throw a NpEx 
        if ( source.isPlainStuff() ) {
            // some magic with a plain stuff
        }

        return Wow.beSurprised;
    }
}
GeT
  • 193
  • 5

5 Answers5

13

It's context sensitive. I once tried to create a "guideline" when to use assertions vs error handling. I called it a "degree of trust" trade-off and illustrated like this:

!!!!!!!!!!!!!    a) user input
...!!!!!!!!!!    b) external data input (network, ...) 
......!!!!!!!    c) internal data input (other process)
*.........!!!    d) library (external)
**..........!    e) library (internal)
****.........    f) public functions (team)
********.....    g) public functions (own code)
************.    h) private functions

! extra validation needed (anything can be thrown in), never ever any assumptions!
. standard validation
* assertions only possible

In your case (internal library API?) I would tend to validate more than use assertions. It's very difficult to anticipate all (ab)uses of library by caller code and integration testing coverage tends to be patchy. If there's no limitation you can also leave assertions in the production code to keep validation (they would turn into exception).

MaR
  • 702
  • 5
  • 8
  • It is pretty the same how I see it. Your "guideline" is pretty good, since it reflects that it is not a binary question. Thanks – GeT Mar 09 '12 at 11:01
4

In my opinion the visibility of your methods doesn't matter at all. After all, all your private methods are ultimately called from public methods in every case, or they wouldn't be needed!

To be sure, a failed precondition to a private method is not always caused by a failed precondition to a public method, but often it is, and anyway the point of assertions is not to keep score in a match of blame-game between the library developer and the application developer. If a precondition is violated, there is a programming error somewhere, and you either want to be informed of that by a runtime crash or you don't. That's the question that decides whether to assert or not.

Kilian Foth
  • 107,706
  • 45
  • 295
  • 310
4

In case of a public library (that some other people will also use) you should throw an exception instead of putting assert. This is also the way how Java API is designed.

And one day your code may be turned into a library...

So I personally always throw IllegalArgumentException in such cases or as in your specific example it can also be NullPointerException.

Dime
  • 295
  • 1
  • 6
2

I think you've got it right. Asserts are for failing fast after a programmer error is detected.

If you know the application will crash or otherwise be left in a bad/unknown state, then assert.

Mike Weller
  • 176
  • 2
  • 9
1

I suspect mine may be a minority view, but personally I view asserts in anything other performance bottlenecks as a premature optimization.

Generally if a pre-condition is worth checking in debug mode it is worth checking in release mode. Of course if you have profiled your code and discovered that you need to wring every last clock cycle out of a function then asserts bridge the gap between no pre-condition checking (which may be necessary if you need to meet a timing constraint even in debug mode) and speed in release mode.

i.e. don't disable pre-condition checks unless you have to

jk.
  • 10,216
  • 1
  • 33
  • 43