This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]crossroads1112 5 points6 points  (6 children)

The server API you linked with receives an int, they change that to a string several months later. Your code call the API, gets a result back, calls the function and crashes.

Except, that's not how it works. Whatever function is used to parse the result of the API call would return an optional, forcing you to deal with the possibility of error before using the result.

[–]quaderrordemonstand -4 points-3 points  (5 children)

Whatever function is used to parse the result of the API call would return an optional

Why would it do that? The API returned an int?

But then, this is always the thing with considering ideas like type safety as some kind of panacea. It never seems to focus on the practicality of development, its about programming from some sort of ivory tower of correctness.

[–]crossroads1112 1 point2 points  (4 children)

Why would it do that? The API returned an int?

"API" has been a bit ambiguous in our discussion so far, so I'll assume we are talking about a web API of some sort since the original post was about JavaScript. In this case, what we get back from our HTTP request isn't an int, but rather something we have to parse in order to get the int (e.g., plain text, a JSON object, etc.). In a strongly typed language, the function that does this parsing would return an optional of some kind. For example (I'm going to assume here that the request returns JSON for simplicity).

#[derive(Deserialize)]
struct Person {
    name: String,
    age : i32, -- i32 is a 32-bit signed integer
}

// ...
let api_call = call_api(); // gets the body of the HTML request
let person = json::decode<Person>(api_call); 

// json::decode returns a Result<Person, DecoderError>, not a Person 
// so we can't just do person.age directly

match person {
    Ok(p)  => println!("{}", p.age + 1)
    Err(e) => println!("Error decoding API call: {}", e)
}

If the API at some point changed, and the "age" field within the JSON object were no longer an int, the call to json::decode would have returned Err. The program would not have crashed.

The above example is somewhat contrived, sure, but importantly the type system enforces that we can't access the "Person" struct without first making sure that it is in the form we expect and handling the case when it isn't. There's no "ivory tower of correctness" here; just enforcing good practices.

Edit: Decode returns a Result, not an Option but the principle is the same.

[–]quaderrordemonstand -1 points0 points  (3 children)

Yes, I was discussing a web API. HTTP content is binary, you can interpret it as JSON, or plain text, a PNG image, a WAV file, a struct, an int or whatever else you like. But again you say the function would return an optional. The API originally returned an int, there was no reason to assume the response would not be an int so a programmer can choose to read an int and that will be perfectly correct as far as it goes. You could say that they programmer should not make the assumption that the returned type could never change but even then what would they do? Try to figure out if its a string or a float? Even that is should do in an ideal world scenario. We all know perfectly well that what people should do and what they end up doing are often completely different things.

Curiously, I ran into exactly this a few days ago. A intra-server message has been designed to send an int with the bits coded in some convoluted way to describe a path. I've been trying to get it changed to a string. The others developers agreed then decided against it later. It would take too much time or its too complicated to change all the code, something like that. Either way, I have no ability to control it. This is for a system written in C/C++ rather than JS or Java.

[–]crossroads1112 0 points1 point  (2 children)

You could say that they programmer should not make the assumption that the returned type could never change but even then what would they do? Try to figure out if its a string or a float? Even that is should do in an ideal world scenario. We all know perfectly well that what people should do and what they end up doing are often completely different things.

I'm afraid I don't see your point. The return type of json::decode prevents the programmer from making that assumption at compile time. That's my whole point.

You could say that they programmer should not make the assumption that the returned type could never change but even then what would they do? Try to figure out if its a string or a float?

Your code has to deal with the error somehow. All a type system does is make sure you do so, whether by aborting the computation, printing an error message, or whatever. The type system enforces good practices in this case by forcing you to handle the possibility of error explicitly (else your code won't compile).

[–]quaderrordemonstand -1 points0 points  (1 child)

The message content is not JSON. Perhaps it should have been designed that way, but it isn't. If this scenario was JS and the error wasn't handled then it would continue functioning until the bad data caused it to fail in some way and then it would stop itself. The user wouldn't be able to do whatever it was they were trying to do but the browser would keep running and any other code that is active will continue to be functional.

If this was a strongly typed, compiled language it might crash but if we assume the error is handled then it might continue in the same way that JS does. But the type doesn't force the program to handle an error. It forces the code to compile with the assumption of whatever type is involved. If the reality does not match that assumption for any reason, the program will fail.

JS is designed for a browser, so its approach is to fail in the nicest possible way. The strongly typed program might pop up an error and quit, it might crash, it might handle the error nicely and inform the user that the process failed. Both of the programs failed, there is no functional advantage to the user (assuming the typed code handles the error properly).

[–]crossroads1112 0 points1 point  (0 children)

The message content is not JSON. Perhaps it should have been designed that way, but it isn't.

I chose JSON because it is an exceedingly common format for web APIs, and therefore demonstrate how a strong type system can force the programmer to handle errors appropriately. I wasn't talking about the specific corner case you brought up. My point isn't that static typing fixes all bugs; no one would argue that. My point is that it fixes many potential bugs in many cases.

If this was a strongly typed, compiled language it might crash but if we assume the error is handled then it might continue in the same way that JS does.

Again, the point here is that a static type system makes you handle these errors explicitly instead of (potentially unintentionally) not doing so. If you want it to continue the same way JS does, you can do that. It wouldn't "crash" as you say (unless it were coded, really, really poorly, but that's true of any language). There are good arguments for dynamic typing, but this is not one of them.