Skip to content
RunnablePublic

About

A Javascript library for refactoring critical paths.

Resources

Stars

17 stars

Watchers

10 watching

Forks

Latest commit

 

History

80 Commits

Folders and files

Repository files navigation

Scientist

Build Status Coverage Status js-standard-style NPM Version

A Javascript library for carefully refactoring critical paths. Influenced heavily from github/scientist.

Scientist is built with and accepts Promises (or Functions that return Promises) in any experiment.

How to Science!

Here's a quick and dirty example of how to Science!

var Experiment = require('node-scientist').Experiment

var experiment = new Experiment('getData')
// use: the control. value will be returned by `.run`.
experiment.use(function () { return Promise.resolve().return(true) })
// try: the candidate. value will be reported in `.publish`.
experiment.try(function () { return Promise.resolve().delay(10).return(false) })
// run: run the experiment.
experiment.run()
  .then(function (result) {
    // result === true, from `.use`.
  })

Science within Models

var Scientist = require('node-scientist')

function MyModel () {}
util.inherits(MyModel, Scientist)

MyModel.prototype.myMethod = function (cb) {
  var experiment = this.science('myMethod', { Experiment: MyExperiment })
  // use: the control. value will be returned by `.run`
  experiment.use(function () { return Promise.resolve().delay(10).return(7) })
  // try: the candidate. value will be reported in `.publish`.
  experiment.try(function () { return Promise.resolve().delay(5).throw(new Error('foo')) })
  // run: run the experiment.
  // NOTE: bluebird allows `.asCallback`, which can help in models w/ callbacks.
  experiment.run().asCallback(cb)
}

var m = new MyModel()
m.myMethod(function (err, value) {
  // err === undefined, candidate error is not passed through.
  // value === 7, from `.use`.
})

Publishing Results

A very simple publisher that will print results to the screen.

var Experiment = require('node-scientist').Experiment
var find = require('101/find')

function MyExperiment (name) {
  Experiment.call(this, name)
}
util.inherits(MyExperiment, Experiment)

/**
 * Publisher function. Takes a result, must return a Promise.
 * @param {Result} result Result object from Scientist.
 * @return {Promise} Promise resolved when publishing is done.
 */
MyExperiment.prototype.publish = function (result) {
  var control = find(result.observations, hasProperties({ name: 'control' }))
  var candidate = find(result.observations, hasProperties({ name: 'candidate' }))
  console.log('Results:')
  console.log('Correctness (were the candidates correct?):', !result.mismatched() ? 'yes' : 'no')
  console.log('Values (control, candidate):', control.value, candidate.value)
  console.log('Candidate Time:', candidate.duration)
  console.log('Control Time:', control.duration)
  console.log('Improvement Time (+larger is better):', control.duration - candidate.duration)
  return Promise.resolve(true)
}

This publisher is used like so:

// as the first case, with just an Experiment:
var experiment = new MyExperiment('foobar')

// if you want to include the Scientist in the model:
SomeModel.prototype.myMethod = function (cb) {
  var experiment = this.science('myMethod', { Experiment: MyExperiment })
  // and continue with the experiment...
}

About

A Javascript library for refactoring critical paths.

Resources

Stars

17 stars

Watchers

10 watching

Forks

Releases

Packages

Used by

Contributors

Languages