Sunday, January 18, 2009

Typed Method Signatures in Joose/JavaScript (parseInt never again)

Typed method signatures have landed in Joose. This is what you get from the new feature:
  • You can define type constraints, classes and roles that a method parameter must match
  • If the type checks fail there is a runtime exception
  • If you enable coercions, Joose tries it's best to convert the parameter types to the one you want!
That is why I call type coercions the death of parseInt (and friends). JavaScript client side programming deals with a lot of user provided string data that needs to be validated and converted to domain values. With type coercions, once you have defined your types (or the use the built-in types), input validation and conversion is completely transparent to your code.

Lets consider this example: If you want to write code that adds the number 3 to the value of this input field: (Just an input-field with a 2 inside (for the feed readers))

To make this reliable, you need to
  • check whether the value of the input field is actually something that can be added to (in a numerical sense)
  • convert the value from a string to a number
This is where Joose type coercions can help you. Here is the code doing all that using type coercions:
    // Make a class thats adds to its instance variable "amount"
Class("Adder", {
has: {
amount: { is: "rw" }
methods: {
// add is a method with a signature
add: {
signature: [Joose.Type.Int], // the first parameter must be an integer
method: function add (num) {
return num + this.amount // add the argument num to our instance var amount
coerce: true // enable coercions for arguments

// Make an adder that always adds 3
var addTo3 = new Adder({ amount: 3 })

// add 3 to the value of the input field
If you would run the above code without type constraints and coercions the result of the method would actually be "23". The code above, however, does the right thing and alerts 5.
This is obviously a lot of code for such a trivial use case, but once things start to become more complicated you save a lot of typing, produce code that might have less bugs and document your parameters a little more thoroughly. The extra benefit of the Joose built in types is that we already wrote unit tests for them (allthough there is always room for more) so you don't have to.
I'm aware that a lot of JavaScript purist will find this totally over the top, but as we go into writing ever more complex JS applications things like this have their place. I, personally, find it great that I get extra security while being lazy at the same time.

Thanks again for the great input from the discussion on the best builder syntax. The current syntax is not final, however. I chose it, because
  • it fits well into Joose
  • the types are close to the actual signatures
It is not ideal, because
  • unless, you repeat (which is bad) the method name in the function declaration, your methods will be called "method" in firebug and similar tools.
  • is is pretty verbose
New ideas that would eliminate these short comings are very welcome.
You might have noticed, that coercions needs to be enabled by opt-in. This is due to the fact, that coercions come with a pretty heavy performance penalty. It is absolutely no problem in a use case where you have a "front-end" function to parse user input (DOM access is magnitudes slower) but might be too big for your canvas ray tracer.

No comments: