上一篇,还是在一年多前。为什么会有这篇续呢?因为笔者这边又进化了,找到了真正想要的开发模式。并且经过时间的检验,这种模式和架构是科学并合理的。
从上一篇可以看出,在试图解决C/S或者B/S中烦人的约定以及接口的问题,不断的用户交互以及在这些中间所涉及到的约定以及乱七八糟的维护问题。
上一篇的结构是这样:
拖几个控件做界面-> 访问桥接层初始化方法->初始化实体数据
响应界面操作->访问桥接层业务方法->访问业务层->获取实体对象->转换桥接层业务实体->显示业务结果
前端访问流程:
做好的界面->通过网络访问->访问桥接层业务方法->返回桥接层业务实体->显示业务结果
我们试图使用实体类来直接传输业务信息,但是为了契合不同的业务,比如一个简单的场景:
1.一个玩家信息面板,需要显示装备和金钱
2.一个玩家信息预览面板,需要显示金钱和经验
于是,我们会生成这样2个返回:
1.玩家信息面板返回:{ 装备,金钱}
2.玩家信息预览面板返回:{金钱,经验}
当我们在2面板上增加一个拥有宠物。
返回就就变成了:{金钱,经验,宠物}
在不断的业务推进的过程中,我们的消息数量变得异常的庞大,不断的修改各个版本的API,让人疲于应付。
为了试图避免这种问题,这里提出了新的解决方案:(世界映射,这边叫Themis)
依然是上面的场景,服务端我们构建一个这样的类:
玩家信息{
装备列表{
装备1,
装备2,
}
金钱,
经验,
宠物
}
客户端也拥有同样的定义类。
面板1,需要做的是
绑定玩家信息里面的金钱信息,以及装备信息。
面板2. 需要做的是
绑定玩家信息里面的金钱信息,以及经验信息。
第一次请求的事情就完成了。。然后就是本文的重点了。
如何变化,比如玩家获得100金钱。
原来的做法:
当服务器返回你获得了100金钱时,你更新面板1,面板2。。。如果有更多面板估计还要继续更新。
新的做法:
直接修改客户端中的金钱。
(这好像不对,直接修改怎么会变动?这里说下绑定,绑定的说明,直接显示数据,并且当他改变的时候,需要刷新显示。)
经过这样的修改,那么接口变得简单,没有任何不恰当的返回定义,只需要关心接口是否成功或失败!
(当然一些额外的数据,依然可能需要定义,但是这个就变得比较简单了。)
各个显示面板只关心自己需要关心的数据,与业务逻辑基本分离。方便任务的切分以及开发。
这样我们就给出了新的解决方案和工作流程:
1.需要一个通用数据同步协议来保持客户端的镜像与服务端一致。
2.需要一个通用的推送协议
公司目前正在使用框架特性:
1.支持http或者tcp推送
2.支持最低10ms内的消息推送
3.允许延迟补偿(当你某个推送失败后,重新连接后,依然能更新到最新版本仅Http)
4.较低的框架开销(正在优化中,大约单机1000人 50MS推送,60fps)
5.低代码侵入
6.目前支持简单的分布式架构(多台服务器共享数据,并且实时切换,较低的切换延迟,暂时没有精力做复杂的分布式)
7.高效的兼容性(就算客户端低好几个版本,不要修改到旧的数据映射,依然可以运行)
8.统一的RPC调用接口
PS:也许会考虑剥离后开源
新工作流程
1.定义服务端实体类
2.定义开放接口
3.映射客户端实体类(可用代码生成器)
4.绑定界面UI
5.调用服务端接口(接口依然可用代码生成器)
再次进化,(还未实现,可能是未来的方向)
单机开发模式:
1.定义共享实体类
2.定义共享接口和服务端私有逻辑
3.界面UI绑定
4.绑定方法调用
5.C/S 或 B/S模式生成(通过拆分调用方法和接口权限)