Spend some time with src/node.js, src/node.cc,
and lib/*.
Don't use Node's source as a model. Tuned for performance, not for
simplicity.
Solutions, workarounds, gross hacks
Tools
'use strict';
jshint
node debug
Testing and benchmarking framework included with Node's source.
Use Node's core abstractions
EventEmitters
streams -- in.pipe(out) if nothing else
domains
use ES5
forEach, map, and reduce
are built into Array.
Object.keys() is a simple way to enumerate object properties.
Function.bind() is a cleaner way of capturing this
Monkeypatching
var http = require('http');
var _request = http.request;
http.request = function () {
console.log("requestin'");
return _request.apply(this, arguments);
};
Monkeypatch safely
Fail via early return rather than throwing:
function wrap(nodule, name, wrapper) {
if (!nodule || !nodule[name] || !wrapper) return;
// other stuff
}
Monkeypatch safely
Log everything:
var logger = require('logger');
function wrap(nodule, name, wrapper) {
logger.debug("Attempting to wrap %s.%s", nodule, name);
if (!nodule || !nodule[name]) {
logger.warn("no function to wrap provided");
return;
}
if (!wrapper) {
logger.warn("no wrapper function provided");
return;
}
// other stuff
}
Monkeypatch safely
Leave visible traces:
function wrap(nodule, name, wrapper) {
// setup
var wrapped = wrapper(nodule[name]);
wrapped.__WRAPPED = "yo dawg";
nodule[name] = wrapped;
}
Monkeypatch safely
Wrap and unwrap idempotently:
function wrap(nodule, name, wrapper) {
// other setup
if (nodule[name].__WRAPPED) return;
var original = nodule[name];
var wrapped = wrapper(original);
wrapped.__WRAPPED = "yo dawg";
wrapped.__UNWRAP = function () {
nodule[name] = original;
};
nodule[name] = wrapped;
}
function unwrap(method) {
if (method.__UNWRAP) method.__UNWRAP();
}
Monkeypatch safely
Always return the results of wrapped calls:
function wrapper(original) {
return function () {
console.log("yo dawg: before");
var returned = original.apply(this, arguments); // XXX
console.log("yo dawg: the dawggening");
return returned;
};
}
Keep it simple: Don't try to metaprogram in JavaScript
Magic is bad.
Magic is super fun.
Metaprogramming is magic.
Therefore, metaprogramming is super
fun.
Therefore, metaprogramming is bad.
How not to metaprogram in JavaScript
Leave req and res alone: prefer composition to extension.
Object.defineProperty() and friends can be
confusing and slow.
Don't control flow via function arity.
Keep it simple: Use ONE strategy for control flow
raw events / streams, async, a promises library, TameJS,
streamline, fibers, monads, reducers, Iced
CoffeeScript, something you wrote yourself...