Transcript
Page 1: unassert - encourage reliable programming by writing assertions in production

unassertEncourage Design by Contract (DbC) by writing assertions in production code, and compiling them away from release

Takuto Wada Nov 7, 2015 @nodefest Tokyo 2015

Page 2: unassert - encourage reliable programming by writing assertions in production

Takuto Wada Twitter: @t_wada github: @twada

Page 3: unassert - encourage reliable programming by writing assertions in production

Do you write tests?

Page 4: unassert - encourage reliable programming by writing assertions in production

assert(typeof item.id === 'strong') | | | | | | | false | | "foo" | Item{id:"foo",name:"bar"} "string"

--- [string] 'strong' +++ [string] typeof item.id @@ -1,6 +1,6 @@ str -o +i ng

I’m the author of power-assert-js!

power-assert

Page 5: unassert - encourage reliable programming by writing assertions in production

Wrestling with Babel6 recently…

Page 6: unassert - encourage reliable programming by writing assertions in production

unassertEncourage Design by Contract (DbC) by writing assertions in production code, and compiling them away from release

Page 7: unassert - encourage reliable programming by writing assertions in production

•unassert •unassertify •babel-plugin-unassert •webpack-unassert-loader

unassert family

Page 8: unassert - encourage reliable programming by writing assertions in production

'use strict';

var assert = require('assert');

function add (a, b) { console.assert(typeof a === 'number'); assert(!isNaN(a)); assert.equal(typeof b, 'number'); assert.ok(!isNaN(b)); return a + b; }

before

src.js

Page 9: unassert - encourage reliable programming by writing assertions in production

babel --plugins babel-plugin-unassert src.js > dest.js

browserify -t unassertify src.js > dest.js

Page 10: unassert - encourage reliable programming by writing assertions in production

'use strict';

var assert = require('assert');

function add (a, b) { console.assert(typeof a === 'number'); assert(!isNaN(a)); assert.equal(typeof b, 'number'); assert.ok(!isNaN(b)); return a + b; }

after

dest.js

Page 11: unassert - encourage reliable programming by writing assertions in production

User’s voice

Page 12: unassert - encourage reliable programming by writing assertions in production

https://www.mapbox.com/

Page 13: unassert - encourage reliable programming by writing assertions in production

“In internal / private methods, we check preconditions with assert, helping us catch mistakes within the library.

For performance, these checks are removed from the production build with unassertify.”

CONTRIBUTING.md

where / when unassert

Page 14: unassert - encourage reliable programming by writing assertions in production

“I don't think we should use this primarily for type checking, but for preconditions -- parts of API contracts that cannot be statically checked.”

@jfirebaugh

why unassert

Page 15: unassert - encourage reliable programming by writing assertions in production

“Flow & TypeScript are compile-time, and preconditions could be runtime.”

“Mapbox GL JS is pretty minimal in terms of transforms - envify, brfs, glify - such that all JS is vanilla.”

@tmcw

why not flow / typescript

Page 16: unassert - encourage reliable programming by writing assertions in production

preconditions?

postconditions?

invariants?

Page 17: unassert - encourage reliable programming by writing assertions in production

{P} A {Q}

Page 18: unassert - encourage reliable programming by writing assertions in production

Design by Contract by Bertrand Meyer

Page 19: unassert - encourage reliable programming by writing assertions in production

If you promise to call routine with precondition satisfied then I, in return, promise to deliver a final state in which postcondition is satisfied.

Design by Contract (DbC)

Page 20: unassert - encourage reliable programming by writing assertions in production

• redundant checks can and indeed will hurt • simplicity becomes a crucial criterion • complexity is the major enemy of quality •whose responsibility it is to enforce it: the client's, or the supplier's.

Design by Contract (DbC)

Page 21: unassert - encourage reliable programming by writing assertions in production
Page 22: unassert - encourage reliable programming by writing assertions in production

switch (name) { case 'foo': doSomething(); break; case 'bar': doAnother(); break; default: assert(false, 'Cannot be here'); }

Not only preconditions

Page 23: unassert - encourage reliable programming by writing assertions in production

add(path) { assert(path instanceof PathElement, `path should be PathElement but was: ${ typeName(path) }`); this.paths.push(path); assert.deepEqual(this.paths, sortedPathElements(this.paths), 'this.paths should always be sorted'); }

Not only preconditions

Page 24: unassert - encourage reliable programming by writing assertions in production

Not only preconditions

Page 25: unassert - encourage reliable programming by writing assertions in production

What if…we use power-assert instead of assert?

Page 26: unassert - encourage reliable programming by writing assertions in production

import assert from 'power-assert';

class Calc { add (a, b) { assert(!(isNaN(a) || isNaN(b))); assert(typeof a === 'number'); assert(typeof b === 'number'); return a + b; } }

const calc = new Calc(); console.log(calc.add(3, NaN));

calc.js

write assertions with power-assert

Page 27: unassert - encourage reliable programming by writing assertions in production

{ "env": { "development": { "plugins": [ "babel-plugin-espower" ], }, "production": { "plugins": [ "babel-plugin-unassert" ] } } } .babelrc

unassert in prod, power-assert in dev

Page 28: unassert - encourage reliable programming by writing assertions in production

$ $(npm bin)/babel-node calc.js

AssertionError: # calc.js:5

assert(!(isNaN(a) || isNaN(b))) | | | | | | | | | | true NaN | false 3 true false

power-assert output appears!

Page 29: unassert - encourage reliable programming by writing assertions in production

user’s voice

Page 30: unassert - encourage reliable programming by writing assertions in production

One more thing…

Page 31: unassert - encourage reliable programming by writing assertions in production

unassert is now babel6 ready!

Page 32: unassert - encourage reliable programming by writing assertions in production

power-assert is not babel6 ready yet

update: 2015/11/13 power-assert now supports babel6!!

Page 33: unassert - encourage reliable programming by writing assertions in production

power-assert now works with async/await

Page 34: unassert - encourage reliable programming by writing assertions in production

# test/some_test.js:6

assert((await bigOrSmall(input)) === big) | | | | | | | "big" "small" 3 false

--- [string] big +++ [string] await bigOrSmall(input) @@ -1,3 +1,5 @@ -big +small

power-assert now works with async/await

by @jamestalmage

Page 35: unassert - encourage reliable programming by writing assertions in production

Encourage reliable programming by writing assertions in production code,

and compiling them away from release (if you want).

to recap

Page 36: unassert - encourage reliable programming by writing assertions in production

power-asserthttps://github.com/power-assert-js/power-assert

unasserthttps://github.com/twada/unassert

Thank you!