关于ACROS的设想
后记与总结
这篇提到的方案, 经过第二天静下心来, 分析实践细节, 认定, 主要问题在于: 咖啡.
"当时我一定是咖啡中毒, 处于脑力过剩无处释放的状态, 误把想象力当成创造力...."
具体原因:
在通信接口上思考软件的设计, 这样的通信模型思考"侵入"了本属于用语言实践时该思考的范畴, 屏蔽了特定语言提供的设计方法, 比如 支持多继承的, 支持mixin的; 也抛弃了很多已有客户端设计思路, 比如mvc.
很多通信上的特殊需求, 比如加密需求, 这些事情统统会侵入软件设计
没有适用的场景. 不同场景适用不同通信协议, 如果是快速开发, 直接web service最快, 用c#之类, 或者Java RMI之类 就可以了, 如果是要求传输速度, 包体积小, 同时不需要长期维护(N年), 比如网游, 自己面向字节设计特定的协议就可以了.
之所以还留在这里, 是为了保留最初的想象力痕迹, 和未来的自己头脑风暴一下...
先总结到这里, 我去冲杯咖啡...
原文开始:
引:
为了不让人类发展出人工智能, 上帝让程序员说不同的语言.
不过后来有了Protocol Buffer, 数据开始有了共同的语言.
现状:
目前的移动互联网开发, 服务器软件的现状:
- RESTful 风格是事实上的标准, 但存在JSON格式和HTTP协议的冗余低效问题.
- SOAP 是一个挺完备的 SOA 架构的方案, 现在几乎不见了踪影.
- 存在一些基于RPC/SOA思路的方案, 比如Apache Thrift, 但都有些缺陷, 比如Thrift的Service不是面向对象的, Service只是一个集合, 里面是一些静态的方法.
思考:
- RESTful 成功的原因: 1. 性能; 2. 容易让人理解接受;
- SOAP 失败的原因: 慢.
RESTful新的不足:
现在NoSQL数据库逐渐流行, 关系型数据库设计的成果 不再 易于 通过ORM生成数据访问对象(DAO)来实践, 以往, 先实现功能, 再通过数据库管理员优化的开发模式被打破了. 现在, 开发人员在分析清实体关系的基础上, 进一步分析各种应用场景, 充分结合所选的数据库的特性, 手工来生成"DAO". 这些所谓的DAO, 是可以包含一些借由数据库特性实现的高层业务逻辑的.
如此这般, 以往REST除了纯封装接口的功能, 还兼顾根据接口组织业务逻辑的作用. 现在, 组织业务逻辑的功能也被淡化了, REST本身的缺陷, 就进一步被放大了.
新风格的思考:
- SOAP 基于 HTTP/XML 实现, 冗余过重, 速度偏慢, 而且其内部逻辑定义使其不易于 被Cache, 更是无可救药.
- 业界返璞归真的心态渐浓, 比如Web Socket. 由基于Request-Reply的HTTP 返回 Socket 形式, 更加自由, 更加轻巧.
- Java 的 Builder 模式, "级联"风格的调用被大家所喜爱.
综上: 如果是将 High Level 的 DAO + SOA/RPC + 级联风格的调用, 是否可以直接作为接口?
关于新风格ACROS的设想:
ACROS 指的是 Accessing Cascaded Remote Object Style 的缩写.
通过一套接口, 让对象/方法可以被级联调用, 而且组合的级联调用将作为一次请求发出, 以减少请求次数.
所谓级联调用
必须解释一下, 指的是这种风格:
// Java
List<User> follower = new User().setBasicInfo(name, sex, age).setAvatar(image).getFollowers();
(这个例子其实可以举得更精彩, 但凡有些代码经验的同学, 想必都会比较喜欢这种API, 一串点下来, 非常爽)
编程体验
- 让用户在调用接口时, 通过一串点的编写方法, 从容的组织逻辑.
- 而返回的对象则是异步结果, 如果是Java, 则是一个实现 Future<?> 的对象, 如果是Go, 则是 chan .
- 如果是不具备异步对象的编程语言, 也可以用回调函数 或者 消息 的形式, 返回.
- Client可以发起多组级联式调用, 然后再通过一个对Context的 commit()操作发送整个命令组, 构成一种批处理操作.
- 除了上述批处理, 还可以在基础链式调用上有分支. 比如:
//Go
user := Context.GetUser(id)
follower := user.setBasicInfo(name, sex, age).getFollwers()
isValid := user.isValid()
- 整个Batch之间不存在逻辑关系, 比如分支控制, 循环.
- 默认的调用顺序是乱序的, 如果需要保证顺序时, 可以调用
Context.Transact()
开始记录调用顺序. - 方法的返回值, 必须是单值形式, 因为许多语言不支持多值返回.
- 方法的参数表, 不推荐含有其他类, 涉及其他entity, 默认使用id; 支持重载的语言, 也可以提供使用其他类的接口. 但含义与逻辑必须与前者一直.
接下来还有更多的细节, 也需要更多的思考, 准备通过写一点代码来明晰.