模式名称
- Navigator/导航者, 一种通信软件报文处理模式
意图
- 封装报文数据复杂的内部结构, 通过提供有业务含义的寻址操作来避免危险的指针运算, 以减少重复和出错的可能, 并提供更清晰的业务意义
动机
在网络通信软件的开发中, 为了传输效率或完整性的考虑, 通常在应用层协议的定义中, 一次可以发送多个单位的净荷数据, 其具体数量可用报文头中的某个字段来描述. 另外一些时候报文体的长度是不定的, 通常也用报文头中的某个字段来表示实际的报文多长.
而此类软件通常以C语言开发完成. 经典的实现方案是为报文定义如下的数据结构, 并以指针运算来寻址特定的数据. 而当数据结构有嵌套时, 其指针运算将变的异常复杂和易错:
typedef struct SecondLevelPayload {
int field_1,
char field_2,
float field_3
} SecondLevelPayload;
typedef struct TopLevelPayload {
int some_top_level_field,
int second_level_payload_count,
SecondLevelPayload* payload //payload之间有嵌套
} TopLevelPayload;
typedef struct Message {
int count,
TopLevelPayload* payload
} Message;
void print_datagram(Message* message) {
TopLevelPayload* current = message->payload;
for(int i = 0; i < message->count; i++) {
PrintTopLevelPayload(current++);
//or PrintTopLevelPayload(message->payload[i]);
}
}
上面最后的函数试图循环打印所有TopLevelPayload, 但寻址方式却是错的, 因为第二个TopLevelPayload的地址并不是第一个的地址加上其自身结构体的长度. 这里的症结在于C语言缺乏描述动态集合的设施, 只有指向首地址的指针, 而指针的大小和其指向的数据的大小是不同的. 又因为数据流是连续的, 因此据此定义的结构体的大小和实际数据的大小是不一致的. 初步的改正如下:
void print_datagram(Message* message) {
TopLevelPayload* current = message->payload;
for(int i = 0; i < message->count; i++) {
PrintTopLevelPayload(current);
current = (TopLevelPayload*)((char*)current + sizeof(TopLevelPayload) + current->second_level_payload_count * sizeof(SecondLevelPayload));
}
}
这样代码就变得晦涩, 看不出意图. 而指针运算容易出错, 且当其它代码需要在报文内部寻址的时候需要重复一遍代码来再算一次, 当报文协议/结构体定义变化的时候, 需要检查所有现存的指针运算看是否还合适. 我们需要更好的设计.
方案
这里的问题是寻址. 而现实生活中, 当我们需要去某个地址的时候, 我们借助导航. 它可以是一部仪器, 也可以是熟悉当地环境的路人. 但接口是一致的: 我们只需要告诉他我们要去哪, 不需要提前了解地形. 在C语言中, 它可以是围绕着报文首地址指针提供的一组有业务含义的接口函数:
TopLevelPayload* goto_nth_toplevel_payload(Message* message, int nth_toplevel_payload) {
TopLevelPayload* addr = message->payload;
for(int i = 0; i < nth_toplevel_payload; i++) {
addr = (TopLevelPayload*)((char*)addr + sizeof_toplevel_payload(addr));
}
return addr;
}
SecondLevelPayload* goto_nth_secondlevel_payload(TopLevelPayload* top, int nth_secondlevel_payload) {
return top->payload + nth_secondlevel_payload;
}
static int sizeof_toplevel_payload(TopLevelPayload* payload) {
return sizeof(TopLevelPayload) + payload->second_level_payload_count * sizeof(SecondLevelPayload);
}
这样, 通过报文首地址和goto_nth_toplevel_payload(), goto_nth_secondlevel_payload()两个函数, 客户代码就可以在报文体中任意巡航, 而无需理会其内部表示, 无需涉及易错和晦涩的指针运算. 当报文协议变化时, 我们也只需要修改navigator, 无需修改客户代码.
相关模式
Page Object模式描述了在web应用测试领域针对易变的web页面进行封装的方法, 其中也涉及对页面不同元素的导航. 其解决的主要问题是减少相对频繁的页面变化对测试代码的稳定性造成的冲击, 并更清晰的描述测试意图.
分享到:
相关推荐
DOM导航器允许键盘浏览DOM元素(←↑→↓)的库。安装凉亭bower install dom-navigator --saveNPM npm install dom-navigator --save手册。 然后将dom-navigator-###.min.js到您HTML页面中。用法纯JavaScript var el...
evil-tmux-navigator:无缝导航Emacs和tmux拆分
Cloudera Navigator SDK是一个客户端库,它提供的功能可帮助用户从Navigator中提取元数据,并使用自定义元数据模型,实体和关系丰富Navigator中的元数据。 样例用例 增量元数据提取 某些应用程序需要出于自身目的从...
可用脚本在项目目录中,可以运行:yarn start 在开发模式下运行应用程序。 打开在浏览器中查看它。 如果您进行编辑,则页面将重新加载。 您还将在控制台中看到任何棉绒错误。yarn test 在交互式监视模式下启动测试...
Navigator具有精致的业务和公司元素,并拥有丰富的版式,它是轻量级的,快速加载,响应Swift且经过W3C验证的,给访问者留下了深刻的第一印象。 基于Bootstrap 4的导航器,并提供了惊人的设计布局。 这些图像仅用于...
航海家 网络导航工具。
Navigator.nvim :sparkles: 在拆分和窗格之间平滑导航 :sparkles: 要求 Neovim每晚(0.5) 安装 使用 use { ' numToStr/Navigator.nvim ' , config = function () require ( ' Navigator ' ). setup () end } ...
GPS导航程序,采用惯性导航技术实现,具有高准确性,低误差的优点。适合作为商业导航器使用。
npm-导航器 直观地导航npm依赖项 API 目录 allModules 模块缓存 loadModule 加载和缓存模块 参数 wiredPanels id version depth 返回模块 安装 ...npm install npm-navigator 执照 BSD-2-条款
Business Navigator ERP 由 3 名开发人员组成的团队设计。 我们的主要目标是为学习曲线低的中型企业提供低成本的 ERP 解决方案。 这是一个免费使用和分发的开源 ERP 项目。 我们唯一的条件是保留“Business ...
vim-tmux-navigator:在tmux窗格和vim分割之间无缝导航
着重研究了基于WinCC Web Navigator技术的一种自动化车间模式,利用Web Navigator这种"瘦客户"系统,有效地解决了车间远程控制方面的难题,对工厂自动化的普及具有重要的现实意义。
你可以使用Source-Navigator: 分析某处源码的变化对其他模块的影响 查找某个函数被调用的地方 查找所有包含某个头文件的文件 利用grep工具在源码中进行搜索 Source-Navigato... 显示详细内容... 开发语言: C...
石油钻井-Navigator Drilling Studio定向井水平井轨迹设计及计算机分析系统 Navigator Drilling Studio是石油钻井行业的计算机辅助工程系统,旨在帮助定向井工程师设计和分析定向井和水平井的轨迹。该系统提供了...
LJ-Navigator基恩士项目实例使用方案,2D扫描仪,读取值记录数据库
场景转换默认为本机平台模式,但可以根据需要进行更改。 在iOS和Android上均运行该示例,以查看实际效果:D 航海家 Navigator是管理所有场景( Scene )过渡的根级组件。 导航器内部使用组件,但使它易于使用和直观...
航海家 Navigator是用于go服务的分布式框架。 导航器可以用作分布式层。 它的重量很轻,只包含一组用于分布式系统的库 组件 1. Discovery: Used to discover new nodes ...4. Navigator: Implementation of distribut
ATT&CK:registered:导航器 ATT&CK导航器旨在提供矩阵的基本导航和注释,这是当今人们已经在诸如Excel之类的工具...ATT&CK Navigator通过GitHub Pages进行实时托管。 。 ATT&CK导航器的4.0版在应用程序的单个实例中
服务器导航器 Minecraft服务器导航软件 特征 翼龙基整合 游戏内GUI的控制服务器 启动停止的服务器 停止运行服务器 创建新服务器 删除服务器 调整内存或CPU 可编辑模板 基于纸张的定制翼龙蛋
草图导航器 草图的画板导航(具有自动完成功能)。 观看演示: : 阅读有关信息: : 下载 演示版 需要线框图模板吗? 安装 下载并解压缩该插件。 双击Sketch-Navigator.sketchplugin进行安装。 导航 使用Command ...