应用服务器的设计(下)
每个程序员都知道软件开发的阶段分为需求分析,概要设计,代码开发,调试,和维护。
可惜的是为应用程序定义灵魂的需求分析阶段我们花的时间最少,在需要变换莫测的环境中,时间都在调试bug修改设计中的消失。在功能黑盒测试后匆匆发布。在面对实际出来的应用功能,我们的需求人员又会有新的点子出现,甚至是颠覆原来的设计。
怎么办,怎么办。尤其是产品在线上运行期间,如何打补丁。
盼望着能够替换某个功能的程序代码。可如果这系列代码还耦合了其他代码,特别是在逻辑计算代码被嵌入一个数据结构中。当程序中有多个这样的数据结构,一旦我们想要替换这段逻辑计算的代码,噩梦发生了。同样当数据要更新时,其中的逻辑代码更是个大麻烦。
不论是事件触发还是命令驱动,每个计算的请求都应该被派发到处理接口不同的实现中,这样我们就可以在运行时进行代码替换了,因为没有耦合,旧的实现没有在其他地方留下引用句柄,每次有请求过来我们都可以使用新的实现。可惜的是我们的处理类不是简单的计算加减乘除,我们还需要其他算法和模块来支持。比如说,在组队语境下杀死怪物,物品和经验的分享计算就设计到队伍模块和经验分配算法来共同完成。
在负责攻击的handlet中,队伍模块和经验分配算法,最简单的做法是每次需要时都从一个黑盒中取出,持有句柄完成计算。缓存下这两个句柄要比每次获取要有效率,所以替换handlet或者替换队伍模块保持引用的完整性成了关键所在。
AlgorithmsCenter{name,algorithm}
AttackHandlet implements UpdateListener{
Function initial(AppContext){
teamRef=AppContext.getModeCenter.get(teamNaming);
expRef=AppContext.getModeCenter.get(expNaming);
}
Function handle(Args){
Do something
}
Function onNewPublish(Republishable){
expRef=republishable;
}
}
新的实例产生时必须执行initial函数,解决缓存问题。
AlgorithmsCenter implements Publisher{
Function reload(naming){
//reload something
}
Function publish(naming){
algonthms =algonthms.get(naming);
Collection<Listener> lc=listeners.get(naming);
Loop ls
l.onNewPublish(algonthms);
}
}
新算法替换后通过控制台发布到感兴趣的代码中。