Tuesday, September 29, 2015

Tape === awesome

tape is awesome. Nobody likes writing thousands and thousands of lines of unit tests, but I'd have to say that tape makes it easy. It takes a lot less time and code to write the tests. Compare these two assertions in Mocha and tape:

(I'll shamelessly admit I yanked many of these from Mocha's website.)

// Mocha
var assert = require("assert")
describe('Array', () => {
  describe('#indexOf()', () => {
    it('returns -1 when the value is not present', () => {
      assert.equal(-1, [1,2,3].indexOf(5))
    })

    it('returns the index when the value is present', () => {
      assert.equal(2, [1,2,3].indexOf(3))
    })
  })
})

// tape
var t = require('tape')
t.test('Array', t => {
  t.test('#indexOf()', t => {
    t.equal(-1, [1,2,3].indexOf(5), 'returns -1 when the value is not present')
    t.equal(2, [1,2,3].indexOf(3), 'returns the index when the value is present')
  })
})

Also, if you're dealing with asynchronous code, it's just as easy.


// Mocha
describe('User', () => {
  describe('#save()', () => {
    it('saves without error', done => {
      var user = new User('Luna')
      user.save(done)
    })
  })
})

// tape
var t = require('tape')
t.test('User', t => {
  t.test('#save()', t => {
    t.test('saves without error', t => {
      t.plan(1)
      var user = new User('Luna')
      user.save(err => t.end(err))
    })
  })
})

The beauty of all of this is that it's so simple. You also don't have any global pollution. The tape tests can be run with node test.js. The tape command line runner does this very thing; it just runs the directory recursively when given one. And as for pretty output, there's a lot of tools out there that only need piped into. If you like the output of a C program that accepts it from stdin, you can use that reporter as well. No opinions needed.

And that's why I like tape. Tests made simple.

Monday, July 27, 2015

Objects linked to other objects - Simplifies so much

I recently made my first npm module (babel-plugin-proto-to-create), but this just stems from my general frustration with class-based OO. Not saying it's a terrible thing at all, or that I can't understand it at all, but there's nothing simpler than objects linked to other objects. Nothing more elegant than this:


const Vehicle = {
  new(make, model) {
    return {
      __proto__: this,
      make, model,
    }
  },

  toString() {
    return [
      "Type:  " + this.type,
      "Make:  " + this.make,
      "Model: " + this.model,
    ].join("\n")
  },
}

const Car = {
  __proto__: Vehicle,

  type: "Car",
}

const Truck = {
  __proto__: Vehicle,

  type: "Truck",
}

Merely creating an instance is as simple as this:


let car = Car.new("Nissan", "Ultima")

I really love the simplicity of this, pure prototypal OO. It's simple, concise, and beautiful. Or, if you'd prefer, you could always use ES6 classes:



class Vehicle {
  constructor(make, model) {
    this.make = make
    this.model = model
  }

  toString() {
    return [
      "Type:  " + this.type,
      "Make:  " + this.make,
      "Model: " + this.model,
    ].join("\n")
  }
}

class Car extends Vehicle {
  constructor(...args) {
    super(...args)
    this.type = "Car"
  }
}


class Truck extends Vehicle {
  constructor(...args) {
    super(...args)
    this.type = "Truch"
  }
}

Lot more boilerplate. Extending mixins in ES6 classes are also a little more complicated:


function mixin(Class, ...srcs) {
  class C extends Class {}
  Object.assign(C.prototype, ...srcs)
  return C
}

class Foo extends mixin(Bar, Baz) {}

// Or, if you want to mixin classes...

function mixin(Class, ...others) {
  class C extends Class {}
  Object.assign(C.prototype, ...others.map(D => D.prototype))
  return C
}

class Foo extends mixin(Bar, Baz) {}

Why do classes, even JS prototypal-based classes, have to be so complicated?



function mixin(Type, ...others) {
  return Object.assign({__proto__: Type}, ...others)
}

const Foo = {
  __proto__: mixin(Bar, Baz),
}

And with ES7's object spread, the mixin picture is only going to make this nicer:


const Type = {
  __proto__: Foo,
  ...Mixin1,
  ...Mixin2,

  method() {},
}

Very lightweight mixins that don't need any syntactical support. Not to mention you could even define these is-a/has-a relationships conditionally at object creation time:


const Type = {
  new(condition) {
    return {
      __proto__: this,
      ...(condition ? Mixin1 : Mixin2),
    }
  }
}

I know of no other language with this kind of flexibility.