Skip to content

Instantly share code, notes, and snippets.

@haru01
Last active August 29, 2015 14:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save haru01/06c6b53a279f0d6ce9ed to your computer and use it in GitHub Desktop.
Save haru01/06c6b53a279f0d6ce9ed to your computer and use it in GitHub Desktop.
Event 中心に
// 学習用
// * See Also http://ookami86.github.io/event-sourcing-in-practice/#how-eventsourcing-works/04-restoring-objects-5.md
// * http://martinfowler.com/eaaDev/EventSourcing.html
//
function BanckingAccount(id, owner, balance, version) {
this.id = id || 0;
this.owner = owner || "";
this.balance = balance || 0;
this.version = version || 0;
}
BanckingAccount.prototype.applyAll = function(evnts) {
var result = this;
for (var i = 0; i < events.length; i++) {
result = result.applyTo(events[i]);
//console.log(result);
}
return result;
}
BanckingAccount.prototype.applyTo = function(evnt) {
return evnt.process(this);
}
function BanckingAccountCreated(accountId, owner, version) {
this.accountId = accountId;
this.owner = owner;
this.version = version;
}
// id を持っているけど、 Immutable & Side effect free スタイルで書いてみたが。。。
BanckingAccountCreated.prototype.process = function(account) {
if (this.version <= account.version ) {
return account;
}
// 初回であること
return new BanckingAccount(this.accountId, this.owner, account.balance, this.version);
}
function DepositPerformed(accountId, amount, version) {
this.accountId = accountId;
this.amount = amount;
this.version = version;
}
DepositPerformed.prototype.process = function(account) {
if (this.version <= account.version ) {
return account;
}
// idが一致すること
// create後であること
return new BanckingAccount(this.accountId, account.owner, account.balance + this.amount, this.version);
}
function WithdrawalPerformed(accountId, amount, version) {
this.accountId = accountId;
this.amount = amount;
this.version = version;
}
WithdrawalPerformed.prototype.process = function(account) {
if (this.version <= account.version ) {
return account;
}
// create後であること
// id が一致すること
return new BanckingAccount(this.accountId, account.owner, account.balance - this.amount, this.version);
}
function OwnerChanged(accountId, newOwner, version) {
this.accountId = accountId;
this.newOwner = newOwner;
this.version = version;
}
OwnerChanged.prototype.process = function(account) {
if (this.version <= account.version ) {
return account;
}
// create後であること
// id が一致すること
return new BanckingAccount(this.accountId, this.newOwner, account.balance, this.version);
}
// eventsのリスト、replay可能ってことは Rxの可能性??
var events = [new BanckingAccountCreated(1, "eiji", 1),
new DepositPerformed(1, 200, 2),
new DepositPerformed(1, 50, 3),
new WithdrawalPerformed(1, 10, 4),
new WithdrawalPerformed(1, 100, 5),
new OwnerChanged(1, 'yoshi', 6)];
//-----
var account = new BanckingAccount();
account = account.applyAll(events);
console.log(account);
// => BanckingAccount {id: 1, owner: "yoshi", balance: 140, version: 6, applyAll: function…}
console.log("-- start snap---");
var snap = new BanckingAccount().applyTo(events[0])
.applyTo(events[1])
.applyTo(events[2]); // snap;
snap = snap.applyAll(events);
console.log(snap);
// => BanckingAccount {id: 1, owner: "yoshi", balance: 140, version: 6, applyAll: function…}
// TODO
// ステートフルなBankingAccountにdepositメソッドを用意してイベント発行する版を書く。
// Eventの永続化の機構
// EventSourcingに移行
// Rxで書きなおす。
// CQRS
// idの振りかた。たぶんUUIDのほうが扱いやすい
// 疑問
// * 通常だと ステートフルなbankingAccountを中心にそえて、 create, depositPerformed, withdrawalPerformed, ownerChangeの
// メソッドがあって,ステータス変更後にイベントを発行するだろうけど、
// まずさきにイベントがあって、イベントからステートフルなBankingAccountを復元でも十分オブジェクトモデルが作れるはず。
// * eventsが永続化できれば、必ずしもはbankingAccountは永続化する必要なし??
// * events中心であれば、DBへのアクセスは、INSERTとSELECT中心で、UPDATE, DELETEの出番が殆ど無い??
// * DDD読んでると、events にマーキングしてチェリーピックやrebase -i みたいなことをしたくなるニーズ があるみたいだが??
// * id発行はuuidか?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment