Thursday, February 4th, 2010

jsContract: Design by Contract library

Category: JavaScript

<>p>Fan of Eiffel or the design by contract pattern that it espouses?

Øyvind Kinsey is, and he just created jsContract an alpha library to give you some pre and post condition abilities.

Here is an example:

javascript
< view plain text >
  1. function _internalMethod(a, b){
  2.     Contract.expectNumber(a);
  3.     Contract.expectNumber(b);
  4.     Contract.expectWhen(config.mode === "divide", b > 0, "Divisor cannot be 0");
  5.     Contract.expectWhen(config.mode === "multiply", a > 0 && b > 0, "The multiplicands cannot be 0");
  6.     Contract.guaranteesNumber();
  7.     Contract.guarantees(function(result){
  8.         return result > 0;
  9.     }, "Result must be > 0");
  10.  
  11.     if (config.mode == "divide") {
  12.         return a / b;
  13.     }
  14.     // At this point config.mode must be "multiply"
  15.     return a * b;
  16. }

A lot of contract code for little functionality…. good old contracts ;)

It is interesting to read how Øyvind instruments the code. Run a test through the translator tool and you get:

javascript
< view plain text >
  1. function _internalMethod(a, b){
  2.     arguments.callee.isInstrumented = true;
  3.     /*preconditions*/
  4.     Contract.expectNumber(a);
  5.     Contract.expectNumber(b);
  6.     Contract.expectWhen(config.mode === "divide", b > 0, "Divisor cannot be 0");
  7.     Contract.expectWhen(config.mode === "multiply", a > 0 && b > 0, "The multiplicands cannot be 0");
  8.     var __return = (function(a, b){
  9.         if (config.mode == "divide") {
  10.             return a / b;
  11.         }
  12.         // At this point config.mode must be "multiply"
  13.         return a * b;
  14.     }(a, b));
  15.     /*postconditions*/
  16.     Contract.guaranteesNumber(__return);
  17.     Contract.guarantees(__return, function(result){
  18.         return result > 0;
  19.     }, "Result must be > 0");
  20.     return __return;
  21. }

Related Content:

Posted by Dion Almaer at 6:07 am
24 Comments

+++--
3.4 rating from 29 votes

24 Comments »

Comments feed TrackBack URI

Already saw this a few days ago and looks similar to JS Interface implementations. The obvious drawback however, is that it adds more function calls and more redundant processing. It costs performance.

We need something native for this kind of programming style to be even remotely plausible.

Comment by BenGerrissen — February 4, 2010

Still kudos, this is a lot cleaner and more maintainable then if/else madness for arguments.

Comment by BenGerrissen — February 4, 2010

Is there any advantage in using Contract programming instead of proper unit test ?

I may miss something, but unit testing seems like a much proper approach than embending a contract in the contractor.

Comment by ywg — February 4, 2010

What on earth is the point of this.

Comment by CliveDangerous — February 4, 2010

@ywg, @CliveDangerous, it’s mitigation from a Classical OO programmer point of view, ‘solving’ the lack of strict typing and interfaces.
.
The lack of a compiler can be very traumatising for programmers comming from another discipline dabbling with JavaScript… Or worse *cough* real programmers *cough* are giving this chap a hard time about JS.

Comment by BenGerrissen — February 4, 2010

@Ben
The main purpose of DbC isn’t simple type checking.. DbC doesn’t replace unit tests – but neither does the opposite.

Comment by FredrikB — February 4, 2010

@BenGerrissen
Code Contracts are not supposed to be present in production code – they are mainly used during development until the point where you can _guarantee_ that your code does what it is supposed to.

@ywg
With unit testing you are only testing the code with known inputs and checking for the correct output. With code contracts you can put code in real use (for instance as a beta) and with proper error handling you will detect the areas where the input is not properly guaranteed for due to browser quirks etc

Other than that, during development it both serves to document your code, it does input validation and it helps you implement complex functions by explicitly stating the contract that it must comply with.

I know firsthand that when writing javascript applications with >20k lines you will never be able to really guarantee that the input (from browser events, etc) will be valid, and at all conditions are met.

Comment by oyvindkinsey — February 4, 2010

Think of it this way, its sort of like a unit test for each function, not just for the entire black box – it actually tests that all input and all output adheres to a strict contract, thereby guaranteeing that as long as the internal logic is correct, it will never fail.

How many pieces of code doesn’t rely on ‘magic’ to work? (and by magic I mean undefined values, “” being evaluated as boolean false, “false” and “true” as true, undefined as boolean false, numbers being passed as strings etc … )

Comment by oyvindkinsey — February 4, 2010

@oyvindkinsey
I see. This is tipically the sort of thing you don’t ship in the final product.
.
Will the preprocessor tool give an option to output a contract-less build for production ?

Comment by ywg — February 4, 2010

@ywg Yes – this is not for production code as it does mean extra processing. The preprosessor will be extended with several options, removing contracts, adding jsDoc with the contract in human-readable form etc. (Did you notice that it can load and transform code dynamically at runtime? )

The ContractErrors will also be extended so that they better explain which condition failed.

I’m thinking also to have an option to insert timing statements, try/catch blocks with a specified error handler – bundled with tools like http://eriwen.com/javascript/js-stack-trace/ and proper error reporting this can really help improve code quality.

Comment by oyvindkinsey — February 4, 2010

I admire the effort, but isn’t this just a clunky way of trying to impose strong typing on a language that is better off without it?

Comment by AngusC — February 4, 2010

@AngusC
Thats really not the point. You can use it to enforce types if you want to, but it is really used to enforced that the input is within an allowed range.
Take for instance a method that takes an object as input, and when done doing its magic returns obj.someProperty (which it thinks is a number).
What if the object given as input has no such property, or if this property is invalid? Then you will end up returning either ‘undefined’ or some value you really did not mean to return – and you are non the wiser.
If you had an expect statement on the input, you would know at once that the argument did not match the contract.
And if you only had the guarantee statement then you would at least know that the output from your function was invalid.

Comment by oyvindkinsey — February 4, 2010

That’s a lot of code for multiplying and dividing 2 numbers. I like the idea of this, but it makes my wrists hurt looking at the code.

I would prefer an interface that’s a little more fluent like:


Contract.expectNumber (a, 'a')
.expectNumber (b, 'b')
.expectWhen(config.mode === "divide", b> 0, "Divisor cannot be 0")
...

I prefer unit testing, TDD to be exact because your test code is separated into its own file, no need to write a tool to remove all this, or extensive commenting out.

My 2 cents.

Comment by someguynameddylan — February 4, 2010

I’m not an DbC evangelist or something, I have just dipped my toes in it, and I do see many advantages with using this – and I am not saying that this should be used instead of unit testing – but I am saying that it fits nicely with TDD as you can start by specifying the contract and then improve the code until it doesn’t fail anymore – just like Red-Green testing.

The advantage this does have over unit testing is that unit tests will by definition never run under the intended conditions, in a browser with a stupid user doing all sorts of things he is not supposed to do, request timing out, connection failing etc..

Code contracts on the other hand CAN, they can be in effect under normal usage and can help identify all the small things that you never ever imagined could happen – like a function that returns .childNodes[0] of some div suddenly returns a textnode instead of the DIV you KNOW is there, wtf?

Comment by oyvindkinsey — February 4, 2010

For those who want a better example, see this one http://kinsey.no/projects/jsContract/test2.html

Comment by oyvindkinsey — February 4, 2010

All that bulk is fine during debugging but worth marking with some comments for stripping before putting into production if possible.

function foo(a, b) {
/* DEBUG BEGIN */
// checks here
/* DEBUG END */
// normal body of function for production
}

Comment by PeterMichaux — February 5, 2010

At first I was skeptical, but it seems quite handy, I’ll certainly give it a try.
.
I think that what disturb people the most is the confusion between contract and production code. Using regular javascript syntax introduce noise and make the function harder to read. If you use some alternative notation I think it’ll be easier for people to dip in.
.
Something like java annotations
@contract expectNumber(a);

or a special inline documentation field
/**
* @contract-start
* expectNumber(a);
* @contract-end
*/

Comment by ywg — February 5, 2010

@PeterMichaux
I use js-build-tools for things like that, if offers conditional statements like
// #ifdef debug
codeThatRunWhenTheDebugFlagIsSet();
// #endif
// #ifdef contract
….
@ywg
I’ll think about just parsing comments and generating the contracts from this – but this means that you will always have to instrument it even to have the input validated.

Comment by oyvindkinsey — February 5, 2010

@BenGerrissen, I understand the point of Design by Contract, I just don’t really see much benefit adding it to Javascript. I’ve worked on a few very js-heavy websites, and I can’t imagine DbC doing anything other then making development take twice as long.

Comment by CliveDangerous — February 5, 2010

@CliveDangerous
One of my biggest projects involve over 18k lines (not counting any frameworks) and uses webservices for data access. The primary page might not be reloaded for weeks (some of our customers keep the application open at all times), and is used from all platforms with browsers ranging form IE6 to Chrome – if one piece of data become inconsistent it will probably affect many different areas of the code, these errors will be extremely hard to debug.

If I had pre- and postconditions on all of my methods that interface with the user (dom-events etc) and that manipulated data I would KNOW where the bug FIRST occurred, where the bug IS, not just where it became noticeable, where it caused hours of work to be lost by the client.

Comment by oyvindkinsey — February 5, 2010

@CliveDangerous, it’s for bulky complex ES applications. It’s indeed not for websites with minute ammounts of ES code.
.
@oyvindkinsey & FredrikB, thats basically what classical OO, type casting, strict typing and interfaces is used for in for example Java, thats currently my only point of reference for domain specific languages ;) The compiler then sorts and tests it on argument correctness etc. but then Java is hardly a dynamic language.
.
This kind of utility is exceptionally useful, but requires a compilation step. I love these kind of innovations and tools, though what we really need at this point, is fantastic IDE love and a good compiler to allow for non ES standard extra utility. I want the WHOLE package, not a snippet ;)
.
And there also lies the jest of things… ES developers are still split between IDE/Tools and just doing everything with .js files manually. As soon as someone mentions the word ‘compiler’ people will stand on their hindlegs because it means change. For me it’s irritating as hell to see domain specific language/platform dependence in great tools.
.
I am rambling offtopic.. so shutting up now =P

Comment by BenGerrissen — February 5, 2010

Couldn’t you use an AOP approach instead of a compilation step? You would only be able to check the inputs and output of a function, but that seems to be the main use case. An advantage is you could keep all the contract code in its own file, like a unit test, though unlike a unit test it would be mixed in to live code.

Comment by zaach — February 5, 2010

@BenGerrisen You are absolutely right here, by doing this we are taking a step beyond just write > execute. But then again, anyone doing javascript for ES should already be running the scripts through tools like JSLint etc as part of the build process any way, this is just the same.
.
For instance, with my easyXDM project components are spread on several files for easy editing, but during ‘compilation’ they are all combined, checked for validity using jslint, strings are being replaced, the code separated into different versions based on conditional statements in comments, and finally its compressed. Adding this on top should not be a hassle for anyone _really_ javascript development.
.
Now, something that would be fun would be to extend the parser used by JSLint to support JSDoc statements – then that could actually check for types! I’m gonna look into this :)

Comment by oyvindkinsey — February 5, 2010

@zaach – i agree. it would seem like AOP would be a better approach than compilation. this is an interesting post about AOP with JavaScript and Dojo.

Comment by neonstalwart — February 6, 2010

Leave a comment

You must be logged in to post a comment.