程序员 2014-11-6 每日奇妙之旅
发布于 10 年前 作者 leogiese 3625 次浏览 最后一次编辑是 8 年前 来自 分享

原文 http://forjs.org/book/xyfULqrrXg/section/lkls30u5rvl

程序员 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 回复

看不懂哎~

这是domain框架,有时间可了解了解

domain框架是啥啊?

domain 框架是代替jsdm的一个框架

代码再何处?

还是看不懂啊。。。好难

你搜索一下 cqrs看看理论知识

回到顶部