Assertive programming with JavaScript

2019-03-25 08:19发布

I know why assertive programming is good, so I want to use it with JavaScript. However, I don't want to show users error boxes, and it's unusual thing. Just ignore it and make them retry could be better.

For example this code will make an error box and interrupt users.

function getDomainFromURL(url) {
    assertTrue(url, 'URL should not be null');

    ...parsing
}

So, I'd make like this.

function getDomainFromURL(url) {
    if (!url) return;

    ...parsing
}

Second one is good for usability, I think, and first one is good for developing. Therefore, IMO it would be the best to combine these and make the assert disappear on production code.

Question 1 Do you think so? Or have any different idea?

Question 2 If you think so, is there any good way to do it with Spring3 framework?

6条回答
劳资没心,怎么记你
2楼-- · 2019-03-25 08:43

There is always a need for conditional error handling when you are dealing with asynchronous and user-driven data. It happens. Users and networks screw up. Such is life. Your best bet is to have, at a minimum the second example if and only if it is reasonable to expect the data can be corrupt. If you are responsible for providing the data that you are testing, then you need to make sure before hand that the data is valid.

Why not have a combination:

function getDomainFromURL(url) {
    if( !assert( url != undefined, 'URL should not be null.' ) ) 
        return ''; 
    // '' is optional, but I don't like returning null if I expect a value.
    /* blah blah blah */
}

// as lightweight a function as you can have.
function assert( val, msg )
{
    if( !val )
    {
        console.log( msg );
        return false;
    }
    return true;
}

Actually, come to think of it, I use that exact pattern quite frequently.

查看更多
Ridiculous、
3楼-- · 2019-03-25 08:45

Asserts should not be used for validating any kind of user input data. They shouldn't be used for error checking either. Assert is the way to make debugging for a programmer easier in case tests fail. Also it is a way to make your code easier to understand.

Consider this example:

function calculateSomeCrazyFormula(a,b,c) {
    var d = a+b+c;
    ....
    k = (x + y)*2;

    assert(k != 0);
    l = d/k;        
    ....
    return x;
}

My formula by it's specification assures that k will never be 0. Here I used assert almost as a comment in my code. It does not validate the logic - it's completely the opposite. With asserts I validate if my implementation of that complex logic is correct. Later, when I come back to my code and see l = d/k I won't get suspicious about what happens when k is 0, because I see my assert there and understand that 0 should never happen.

Also, if there is an error somewhere and 0 does happen, you will usually see some deeper error. For example:

function otherFormula(a,b,c) {
    var x = calculateSomeCrazyFormula(a,b,c);

    var y = doSomeStuff(x);
    var z = doOtherStuff(y);
    return z;    
}

Without asserts you will get the wrong result of this function. You will have no idea why you are receiving 0 when it should be 1. You will have to start debugging the code line by line and understanding what went wrong.

With asserts, however, you will instantly notice the "assertion failed" error and will instantly minimize the scope to look for the problem.

Asserts are useful in any programming language including Javascript, however they shouldn't be there in Live environment. Therefore, some postprocessor system should remove all of the asserts out of your code before the release.

查看更多
姐就是有狂的资本
4楼-- · 2019-03-25 08:47

I don't think the second one is particularly good at all. If you return nothing from a method that is always expected to return something, the code will likely just fail somewhere else, instead of close to where the actual problem is i.e. within the getDomainFromURL function.

If on the other hand, it's perfectly OK for this method to return nothing when the parameter is null, then it doesn't make sense to add the assertion.

Personally, I would use the first form everywhere, in both development and production. If the assertion fails in production, then you'll get very useful feedback (in the browser, logs, etc.) about the cause of your problem. If you remove the assertion, you'll still have a bug, but it'll just be more difficult to track down

Aside

This style of programming - checking pre-conditions - is part of what is known as contract-based programming. I've never heard of the term "assertive programming" before.

查看更多
smile是对你的礼貌
5楼-- · 2019-03-25 08:52

Just ignore it and make them retry could be better.

Silently failing is not a good idea. From a usability perspective, users should have immediate feedback on their actions, even in the case of errors. You should show a simple error page when something exceptional happens in your code. The idea here is, fail fast.

I would make your assert function redirect to an error page if the condition is not met, and log it. You can do this in Javascript by setting window.location.href and log your error by posting with an XHR.

查看更多
不美不萌又怎样
6楼-- · 2019-03-25 08:53

You could use it like this:

function getDomainFromURL(url) {
   assert(url != null, "url is null");
   if (!url) return;
    ...parsing
}

Some people would disagree but I would try and find a way of removing assert statements in production code, maybe by using a preprocessor or as part of an obfuscation step, if you have one. This could improve performance and code size, but you would need to make sure that the code you call from within the assert doesn't change the state of your program. This could be tricky as well. My conclusion is that writing large and robust programs in javascript requires discipline.

As a bonus, have a look at the assert that can be found here:

http://aymanh.com/9-javascript-tips-you-may-not-know/

查看更多
萌系小妹纸
7楼-- · 2019-03-25 08:55

I don't think it's good to have assertive programming in Javascript for a couple of reasons:

  1. i don't like the fact that error checking like that should be done in a production environment.
  2. People developed unittesting framework specifically for this purpose (JsUnit)
  3. this assert statement increases code size, which increase the download time, and the execution time.

The best way to do this is to write unittests. This way you can ensure your code don't break when you update it, and also it means that assert won't appear in your production code. Granted, you may NEED to have things such as if (condition) error(); as those condition may depend on the user, rather than the developer. Those will be unavoidable and you will need to code them by hand.

Rule of thumb:

  • use if (condition) error(); when the condition depends on the user
  • write unittests if the condition is dependent on the developer.

Lastly, with unittesting, you can check if your code errors properly. I'm not too sure about JsUnit, but in you could probably do something like this in your tests:

assertThrow(somefunc, args, YourError);

to go along with your if (condition) error(); in your code

查看更多
登录 后发表回答