程序员 2014-11-6 每日奇妙之旅
推荐:《精通Node.js开发》 《Angular.js视频详解》 腾讯QQ
1405491181
微信号forjs_org
说实话今天让我很期待,对domain框架的进一步完善,和优化,让我对越来越感觉软件不单纯是技术,而是一门艺术。
从7年前刚刚接触 DDD 建模方式,那时候banq老头子是主流,现在百花齐放,把这种思想应用到很多领域中,而我主攻的Javascript领域,也在前两年开发了JSDM框架。
而现在我又一次感到,CQRS和 Actor 结合是一种更好的模式,所以推出了domain framework。
好了,感慨到这里了,我还是开始今天奇妙之旅吧。我深深的感受到HTML5&Node.js的舞台之美好,但这只是工具,让我在上面谱写自己的创造。
早上大米饭+洋葱炒蛋+黑咖啡,让我精力充沛,感脚不只是萌萌达,而且精神神的。
今天的计划是完善框架,和录制视频教程,另外我想写一个domain相关的文章。
domain框架的优化
EventBus 应具有保存监听器的功能。它在publish事件时候,要同时emit多次。
es.useEventPublisher(function (evt) {
var event = Event.reborn(evt);
emitter.emit(evt.targetType + "." + evt.targetId + ":" + evt.name, event);
emitter.emit(evt.targetType + ":" + evt.name, event);
emitter.emit("." + evt.targetId + ":" + evt.name, event);
emitter.emit(":" + evt.name, event);
emitter.emit(evt.targetType, event);
if (evt.contextId) {
emitter.emit(evt.targetType + "." + evt.targetId + ":" + evt.name + "&" + evt.contextId, event);
emitter.emit(evt.targetType + ":" + evt.name + "&" + evt.contextId, event);
emitter.emit("." + evt.targetId + ":" + evt.name + "&" + evt.contextId, event);
emitter.emit(":" + evt.name + "&" + evt.contextId, event);
emitter.emit(evt.targetType + "&" + evt.contextId, event);
}
})
事件全称定义方式是 eventname + &contentId 。
Actor会产生listen事件,对应EventBus的listen方法
listen(actor, eventname, handleName, contextId, onlyContext) {
this.emitter.on(handleName + onlyContext && contextId ? "&" + contextId : "", event=> {
this.domain.call(actorId, handleName, event, event.contextId)
})
}
眼下这样写,并不完善,但应该可用。之后还要考虑listener的持久化问题。
开发到这里,需要考虑Repository和Domain了。
完善 Repository
构建repository构造器
constructor(Actor, eventstore) {
this.Actor = Actor;
this.eventstore = eventstore;
this.getFromSnapShot = thunkify(this.eventstore.getFromSnapshot).bind(this.eventstore);
this.createSnapshot = thunkify(this.eventstore.createSnapshot).bind(this.eventstore);
this[cache] = {}
}
创建actor的方法
*create(data) {
let actor = new this.Actor(data);
let stream = (yield this.getFromSnapShot(actor.id))[1];
yield this.createSnapshot({
aggregateId: actor.id,
aggregate: this.Actor.typeName,
data: actor.json,
revision: stream.revision
})
this.emit("create",actor);
this[cache][actor.id] = actor;
return actor;
}
获得actor对象的方法
*get(id) {
let actor;
if (actor = this.getFromCache(id)) {
return actor;
}
let result = yield this.getFromSnapShot(id);
if (actor = this.getFromCache(id)) {
return actor;
}
let snapshot = result[0];
let stream = result[1];
if(!snapshot){
return null;
}
let snap = snapshot.data;
let history = stream.events;
actor = new this.Actor();
// mix aggregate object.
actor.loadSnap(snap);
var historyv = [];
history.forEach(function (e) {
historyv.push(e.payload);
})
actor.loadEvents(historyv);
this[cache][actor.id] = actor;
return actor;
}
测试Repository
测试实例化
it("#new", function () {
repos = new Repository(User,es);
})
测试创建actor
it("#create", function (done) {
co(function *() {
var user = yield repos.create({name:"leo"});
uid = user.id;
user.get("name").should.eql("leo");
var getFromSnapShot = thunkify(es.getFromSnapshot).bind(es);
var rs = yield getFromSnapShot(user.id);
var snap = rs[0];
should.exist(snap);
done();
})()
})
测试获取actor方法
it("#get", function (done) {
co(function* () {
repos.clear(uid);
var user = yield repos.get(uid);
user.get("name").should.eql("leo");
done();
})()
})
非常lucky,全部通过。得健身去了,人鱼线小了。
8 回复