Last active
August 29, 2015 14:21
-
-
Save egonelbre/d04f8002465b7f07dc06 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Account(code, balance) { | |
return { | |
get code(){ return code; }, | |
get balance(){ return balance; }, | |
increase: function(by){ balance += by; }, | |
decrease: function(by){ balance -= by; } | |
}; | |
} | |
function Bank(){ | |
var accounts = {}; | |
return { | |
openAccount: function(code, initialBalance){ | |
accounts[code] = Account(code, initialBalance); | |
}, | |
accountByCode: function(code){ return accounts[code]; } | |
} | |
} | |
Transfer = Context( | |
function(bank, from, to, amount) { | |
Source = bank.accountByCode(from); | |
Destination = bank.accountByCode(to); | |
Amount = amount; | |
Source.give(); | |
}, { | |
Amount: {}, | |
Source: { | |
give: function() { | |
if(Source.balance < Amount){ | |
throw new Error("Insufficient funds."); | |
} | |
Source.decrease(Amount); | |
Destination.receive(); | |
} | |
}, | |
Destination: { | |
receive: function() { | |
Destination.increase(Amount); | |
} | |
} | |
}); | |
var bank = Bank(); | |
bank.openAccount("alice", 132); | |
bank.openAccount("bob", 23); | |
console.log("Before:"); | |
console.log("alice ", bank.accountByCode("alice").balance); | |
console.log("bob ", bank.accountByCode("bob").balance); | |
Transfer(bank, "alice", "bob", 100); | |
console.log("After:"); | |
console.log("alice", bank.accountByCode("alice").balance); | |
console.log("bob", bank.accountByCode("bob").balance); | |
// DCI implementation | |
function Context(init, roles, debug){ | |
// scoped role players | |
var sfn = " var " + Object.keys(roles).join(",") + ";\n"; | |
// creates the function | |
var mkName = function(role, fn){ return role + "$" + fn; }; | |
// redirects all role method calls | |
var fixMethod = function(fn){ | |
fn = fn.toString(); | |
for(var roleName in roles){ | |
var role = roles[roleName]; | |
for(var fnName in role){ | |
// replaces Role.method(arg1,arg2,arg3) with | |
// with Role$method.call(Role, arg1, arg2, arg3) | |
var rx = new RegExp( "(?!\\.)" + roleName + "\\s*\\.\\s*" + fnName + "\\s*\\(", "g"); | |
fn = fn.replace(rx, mkName(roleName, fnName) + ".call(" + roleName + ","); | |
} | |
} | |
// hack-fix Role$method.call(Arg,) | |
fn = fn.replace(/,\)/g, ")"); | |
return fn; | |
}; | |
// define role methods in to the context | |
var methods = []; | |
for(var roleName in roles){ | |
var role = roles[roleName]; | |
for(var fnName in role){ | |
methods.push(" var " + mkName(roleName, fnName) + " = " + fixMethod(role[fnName])); | |
} | |
} | |
sfn += methods.join(";\n") + ";\n"; | |
// return the init | |
sfn += " return (" + fixMethod(init) + ").apply(null, arguments);"; | |
if(debug){ | |
console.log(sfn); | |
} | |
return (new Function(sfn)); | |
} |
Author
egonelbre
commented
May 15, 2015
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment