unassert - encourage reliable programming by writing assertions in production

Embed Size (px)

Text of 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

  • Takuto Wada Twitter: @t_wada github: @twada

  • Do you write tests?

  • 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

    Im the author of power-assert-js!

    power-assert

  • Wrestling with Babel6 recently

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

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

    unassert family

  • '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

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

    browserify -t unassertify src.js > dest.js

  • '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

  • Users voice

  • https://www.mapbox.com/

    https://www.mapbox.com/

  • 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

  • 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

  • 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

  • preconditions?

    postconditions?

    invariants?

  • {P} A {Q}

  • Design by Contract by Bertrand Meyer

  • 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)

  • 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)

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

    Not only preconditions

  • 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

  • Not only preconditions

  • What ifwe use power-assert instead of assert?

  • 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

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

    unassert in prod, power-assert in dev

  • $ $(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!

  • users voice

  • One more thing

  • unassert is now babel6 ready!

  • power-assert is not babel6 ready yet

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

  • power-assert now works with async/await

  • # 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

  • Encourage reliable programming by writing assertions in production code,

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

    to recap

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

    unasserthttps://github.com/twada/unassert

    Thank you!

    https://github.com/power-assert-js/power-asserthttps://github.com/twada/unassert