Skip to content

Instantly share code, notes, and snippets.

@brendandahl
Created April 9, 2012 16:39
Show Gist options
  • Save brendandahl/2344630 to your computer and use it in GitHub Desktop.
Save brendandahl/2344630 to your computer and use it in GitHub Desktop.
Ready to Assemble Design Pattern

Ready to Assemble Design Pattern

IKEA Furniture Design Pattern (Assembly Service Included)

Motivation:

In pdf.js we need to do as much processing as possible in the worker thread. The result of this work is then often used in the main thread to rebuild an object. There is currently no consistent way to do this.

Ready to Assemble Furniture Process:

Producer

  • Build - Take pieces and do as much work and assembly on the product as possible.
  • Package - Take the partially assembled pieces and put them in packaging for transport.
  • Send - Send the product to the consumer.

Consumer

  • Receive - Receive the package from the producer.
  • Assemble - Create the final product from the partially assembled pieces ready for use.

Relating this to pdf.js using how PostScript functions work as an example:

Producer (Worker Thread)

  • Build - Take raw PDF objects(strings, numbers, dicts, ...) and do as much processing as possible. For PS functions we parse the function.
  • Package - Create a JSON representation with enough information to build the final object. This is very similar to our current getIR.
  • Send - Automatically handled by messaging e.g. mainThread.postMessage(package)

Consumer (Main Thread)

  • Receive - Automatically handled by messaging e.g. worker.onMessage(package)
  • Assemble - Create the final object that is usable by the main thread. This could be considered our fromIR.

##How this differs from just serialize/deserialize: With searlize/deserialize the object you use in the main thread would be exactly the same. In this model we aren't trying to re-create the object exactly since most of the time we don't need everything that was in the worker thread.

How this could make things easier:

  • creates an easy to understand analogy (I think)
  • breaks chunks of work up into defined tasks
  • assembly could be made semi-automatic

In Code

This really isn't much code, it's more a method to organize things.

/**** Approach 1) Object for each, separate consumer/producer ****/
function PostScriptProducer(data) {
  this.data = data;
}
PostScriptProducer.prototype = {
  build: function() {
    parseTheData();
    return aPackage /* a JSON object or maybe Package Object*/;
  }
}

function PostScriptConsumer(package) {
  this.package = package;
}
PostScriptConsumer.prototype = {
  assemble: function() {
    var postScriptEvaluator = createPostScriptEvalutor();
    return postScriptEvaluator;
  }
}

function AssemblyService() {
  this.assemblers = {};
}
AssemblyService.prototype = {
  addAssembler: function(name, assembler) {
    this.assemblers[name] = assembler;
  },
  assemble: function(package) {
    var assembler = new this.assemblers[package.name]();
    return assembler.assemble(package);
  }
}

/*** Approach 2) Module(ish), separate consumer/producer ****/
var PostScriptConsumer = (function() {
  return {
    build: function(args) {
      parseTheData();
      return aPackage /* a JSON object or maybe Package Object*/;
    }
  }
});
var PostScriptProducer = (function() {
  return {
    assemble: function(package) {
      var postScriptEvaluator = createPostScriptEvalutor();
      return postScriptEvaluator;
    }
  }
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment