后记与总结

这篇提到的方案, 经过第二天静下心来, 分析实践细节, 认定, 主要问题在于: 咖啡.

"当时我一定是咖啡中毒, 处于脑力过剩无处释放的状态, 误把想象力当成创造力...."

具体原因:

  1. 在通信接口上思考软件的设计, 这样的通信模型思考"侵入"了本属于用语言实践时该思考的范畴, 屏蔽了特定语言提供的设计方法, 比如 支持多继承的, 支持mixin的; 也抛弃了很多已有客户端设计思路, 比如mvc.

  2. 很多通信上的特殊需求, 比如加密需求, 这些事情统统会侵入软件设计

  3. 没有适用的场景. 不同场景适用不同通信协议, 如果是快速开发, 直接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; 支持重载的语言, 也可以提供使用其他类的接口. 但含义与逻辑必须与前者一直.

接下来还有更多的细节, 也需要更多的思考, 准备通过写一点代码来明晰.