15

Considering that sometimes error messages in node are particularly unhelpful I like to liberally use asserts in my functions so that programming errors are caught asap and I can get a message which in general pinpoints the problem.

function doSomething(arg1, arg2){
  assert(!arg1, "arg1 is undefined");
  assert(!arg2, "arg2 is undefined");
  assert(!arg1.expectedFn, "arg1 does not have expectedFn");

  arg1.expectedFn(function(blah){
    ...
  }
}

Is this a particularly bad thing to do in node/javascript programs? Does this have an impact on performance?

1 Answer 1

7

(this is more of an opinion than fact post, so take it for what it's worth)

Asserts definitely do nothing good for performance, but used in moderation I doubt they have a serious enough of an impact to matter. That said, generally speaking good test coverage is preferable to asserts whenever possible. Also, what asserts you do write should not be redundant to what errors will naturally be thrown at runtime, unless they are particularly opaque.

Let's consider a modified (and somewhat contrived) version of doSomething -

function doSomething(arg1, arg2){
  var res = arg1.expectedFn(function(blah){
    ...
  }
  return res + arg2;
}

I would argue there's no point in checking arg1 for existence or it contains a function name expectedFn. If either are undefined, the javascript runtime will throw a fairly understandable TypeError that will say exactly what happened; the asserts are redundant.

However, you may find it desirable to test arg2 here. Suppose it's undefined, and res is a string or number - you'd then end up with "undefined" appended to the string, or NaN returned. Both are fairly subtle errors that can exist for a long time without anyone noticing - if you want it to fail sooner rather than later for debugging purposes, then you may want to add a few asserts to ensure it's the correct type.

In general, if you're concerned about rigor, I believe that energy would be better put to use in writing comprehensive tests: writing tests that fully cover the cases when doSomething is called will likely lead to a better, more robust development process than asserts. There are a few cases where asserts are appropriate, but they're limited to cases where malformed results can exist for a long time without any direct errors, but still able to cause undesirable side effects.

Sign up to request clarification or add additional context in comments.

5 Comments

There is certainly no substitute for testing. However my opinion is that when you are creating an API the errors are part of the API itself so saying "You passed an invalid argument" would be preferable to "expectedFn does not exist on undefined" would you agree?
That's a tough call Moiz, and I'm not sure I have any great, general rule for it. I would say in this case it's still not necessary, since I don't believe that knowing a specific argument in a function is undefined will help any more than knowing that an undefined variable was encountered in a function (you also get the benefit of a more specific error message in this case). It's also pretty hard to assert yourself to total victory - what if arg1 has expectedFn, but it doesn't take a function as an argument?
However, I believe more comprehensive errors would be very useful for polymorphic functions that API's often implement, as errors when you're allowed a variety of types aren't very transparent. Though for variable-type arguments, you're likely to have some statements at the head of the function that unpack the arguments in a more actionable format for itself - usually, I'd directly throw the errors from here rather than rely on an assert.
The Joyent testing bible certainly agrees with Moiz's liberal asserts approach: "Missing or invalid arguments are programmer errors, and you should always throw when that happens."
what asserts you do write should not be redundant to what errors will naturally be thrown at runtime – an error caught early and specifically (i.e. by verifying some smoke testing like .isDirectory() or notEmpty() or whatever is imho by far more digestible and debuggable than „letting stack trace hell happen“ — in Javascript and many more languages...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.