- 内容提要
- 序 1:程序里的世界
- 序 2:最后一层表象
- 关于本书
- 致谢
- 引言:简单的本源
- 篇一:计算系统
- 第 1 章 数,以及对数据的性质的思考
- 第 2 章 逻辑
- 第 3 章 抽象
- 篇二:语言及其面临的系统
- 第 4 章 语言
- 第 5 章 从功能到系统
- 篇三:程序设计的核心思想
- 第 6 章 数据结构:顺序存储
- 第 7 章 数据结构:散列存储
- 第 8 章 执行体与它在执行过程中的环境
- 第 9 章 语法树及其执行过程
- 第 10 章 对象系统:表达、使用与模式
- 篇四:应用开发基础
- 第 11 章 应用开发的背景与成因
- 第 12 章 应用开发技术
- 第 13 章 开发视角下的工程问题
- 第 14 章 应用程序设计语言的复杂性
- 篇五:系统的基础部件
- 第 15 章 分布
- 第 16 章 依赖
- 第 17 章 消息
- 第 18 章 系统
- 篇六:系统的基本组织方法与原理
- 第 19 章 行为的组织及其抽象
- 第 20 章 领域间的组织
- 附一:主要编程范式 及其语言特性关系
- 附二:继承与混合,略谈系统的构建方式
- 附三:像大师们一样思考——从 UML 何时死掉 谈起
- 附四:VCL 已死,RAD 已死
20.2 数据的规格化要尽量远离具体的处理逻辑
一个 HTTP Request 通常要经过与服务器端的多次通信才能完成提交,过程大致如下:
- Web 服务器只负责接收数据,并在适当的时候将执行权转换到应用的框架层(Framework);
- 框架层会解析这些接收到的数据并构建(Build)请求对象,或将某些数据持久化(例如文件上传);
- 最后,框架层将一个请求对象作为应用可以理解的数据格式,例如 Java 对象,提供给应用逻辑来处理。
在这个过程中,如果数据有效性验证发生在应用逻辑中,将是效率最差的。相较而言,较好的位置是放在框架层“构建(Build)请求对象”这一环节中(A 方案),而更好的位置则是放在服务器接收数据这一环节中(B 方案)。
B 方案通常是通过 Web 服务器插件来实现,它不太方便的地方在于:如果在其中加入大量逻辑,对服务器整体的稳定性将构成影响,并且这些逻辑可能是重复而无意义的。举例来说,如果我们试图以 B 方案在一个插件中实现预结构化 URL 中的请求数据,那么 Web 服务器需要解析 HTTP 请求的 Head 部分,读取 URL 并解码、定位字段、验证……而这些过程既拖慢了服务器响应,而且相同的逻辑还需要在框架层上再做一次。所以虽然 B 方案中看起来是“更好的位置”,但对于我们这里要解决的问题来说,却是相当不妥的。 2
A 方案通常是应用服务器内部的逻辑。为避免细节,这里只提及一个问题:需要“将 HTTP Request 转换为一个数据对象”完全完成之后,才能进行后续处理吗?这个问题是“数据如何进行结构化,以及在哪里进行结构化”的核心。举例来说,如果客户端具备规格化数据的能力,那么我们可以要求“在一个有效的 HTTP Request 中,字段数据的第一项必须是 SessionId” 3 。将这作为一个约定时,我们看看 B/S 框架的各层之间是否能实现这一协议:
- 在浏览器端,可以通过在 URL 后添加字段数据的方法使 Get/Post 请求都满足上一协议。以 Post 请求为例,当请求的 URL 中带有“?SessionId=xxxx”时,它可以被提交到服务端作为 Request Fields 数据。
- 在服务端,当解析 HTTP Request 并尝试 Build 时,可以从 URL 中顺序读取到 Action 信息,以及接下来的 SessionId 信息,这应当是在一次解析过程的前后连续动作中发生的(先是 Action,接下来是 Query Fileds)。因此可以按顺序逻辑来实现“判断第一个 Field 是否是 SessionId,并判断它是否有效”这一行为。
- 在服务端,如果上述判断为“否”,则框架层完全有能力响应浏览器端请求,例如(1)重定向到登录页面,或(2)返回标准错误信息,或(3)保存当前请求作为事务数据,以开始一个“登录+重新提交”的过程。
接下来让我们看看这一系列的复杂过程有何收益?其一,当一个客户端请求发生时,服务器可以在没有完全接收数据的情况下作出响应,这提高了客户端的体验;其二,一个无效的请求在抵达(执行过程将更占用 CPU 的)应用层之前,在仅需最少的执行周期的情况下,就已经获得了正确的判断信息并处理了。
从这一过程中,我们可以得到一个结论:数据的结构化阶段离处理阶段越远,其系统的整体收益也就越高,即数据要“尽可能早地”结构化。但结构化是一个逻辑过程,需要相应的部署环节的支持,例如我们需要考虑 Web 客户端层的整体系统结构。
只有在部署许可的情况下,我们才有讨论“结构化与预结构化”的位置的可能性。例如基于客户端与基于 Web 的即时信息(IM, Instant Messaging)软件,就非常不同,前者对数据的预结构化能力非常有限。通常在系统中,我们寄期望于数据的发出者具备结构化的能力,并尽量提供在多个子系统 4 之间的标准(Standard)、基础(Base)和基元(Meta)信息格式。如果这一点不能满足,我们也通常不在具体应用逻辑中处理格式,而是将这一过程交由中间层来实现。例如将来源数据读取为内存数据库,或添加数据接收服务器,来将端口或远端数据转换为系统内部支持的格式。
以尽量远离处理逻辑的方式实现数据规格化,即使仅仅是形成了类似“Name/Value”这样粗粒度的数据索引 5 ,也会给后续处理逻辑带来巨大的收益。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论