Skip to content

Instantly share code, notes, and snippets.

@mbrowne
Last active March 7, 2019 13:17
Show Gist options
  • Save mbrowne/52ae253fdee9a300d6273da071f94202 to your computer and use it in GitHub Desktop.
Save mbrowne/52ae253fdee9a300d6273da071f94202 to your computer and use it in GitHub Desktop.
DCI in native Javascript using symbols
const addEntry = Symbol('addEntry'),
getBalance = Symbol('getBalance');
export default class Account {
constructor(ledgers) {
const roles = {
ledgers: {
[addEntry](message, amount) {
ledgers.push(new LedgerEntry(message, amount));
},
[getBalance]() {
return ledgers.reduce((sum, ledger) => (
sum + ledger.amount
), 0);
}
}
};
if (!ledgers) ledgers = [];
this.ledgers = ledgers;
//role binding
Object.assign(ledgers, roles.ledgers);
}
increaseBalance(amount) {
this.ledgers[addEntry]('depositing', amount);
}
decreaseBalance(amount) {
this.ledgers[addEntry]('withdrawing', 0 - amount);
}
get balance() {
return this.ledgers[getBalance]();
}
}
class LedgerEntry {
constructor(message, amount) {
this.message = message;
this.amount = amount;
//ledger entries are immutable
Object.freeze(this);
}
}
import Account from './Account';
import TransferMoney from './TransferMoney';
const source = new Account();
source.increaseBalance(30);
const dest = new Account();
dest.increaseBalance(30);
TransferMoney(source, dest, 10);
console.log('source balance', source.balance);
console.log('destination balance', dest.balance);
const transfer = Symbol('transfer'),
withdraw = Symbol('withdraw'),
deposit = Symbol('deposit');
export default function TransferMoney(sourceAccount, destinationAccount, amount) {
const roles = {
banker: {
[transfer]() {
sourceAccount[withdraw]();
destinationAccount[deposit]();
}
},
sourceAccount: {
[withdraw]() {
if (this.balance < amount) {
throw Error('Insufficient funds');
}
this.decreaseBalance(amount);
}
},
destinationAccount: {
[deposit]() {
this.increaseBalance(amount);
}
}
};
// Role binding
const banker = {};
Object.assign(banker, roles.banker);
Object.assign(sourceAccount, roles.sourceAccount);
Object.assign(destinationAccount, roles.destinationAccount);
// Run the use case
banker[transfer]();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment