最近在做一个网关项目,分享一下在设计模块的接口时的一个小心得。
网络通信少不了对数据的处理,举个例子,下行的网关发给设备的某类消息中的数据格式如下:
这是json格式的数据,还有很多发下来的消息也是json格式的,因此需要一个json模块来专门进行数据解析以及组json格式的包。可以从网上下载针对嵌入式的小型json模块直接移植过来,但这里考虑到数据协议并不复杂,嵌套层数不多,最多也就两层,所以自己写算了。
首先需要设计解析json数据的接口,该设计成什么样?请看下面两种方法。
方法一
定义一个结构体:
定义数据处理函数如下:
输入:要处理的数据data,数据长度len
处理:把数据中的一项一项的值解析出来存到结构体outdata中对应的元素中去
输出:outdata;
返回:0(正常)/-1(异常);
比如上述数据,输出:
方法二
定义数据处理函数如下:
输入:要处理的数据data及其长度len,要从json数据中获取内容的属性名称 attribute;
输出:属性的值value;
处理:从数据data中获取attibute的值,赋给value;
返回:0/-1.
比如,输入上面数据赋给data,attribute="msg",输出value="DEVICE_CONTROL"
总结
上面两种方法哪种方法更好?乍一看,方法一好像很好,很省心对吧?你只需要输入数据,在里面处理一番,输出的东西都给你弄好了。但是,仔细想想,这个函数里面会怎么实现呢?第一步是从data中去获取"msg"属性的值,赋值给结构体中的type,第二步是从data中获取”id”属性的值赋给结构体中id,这不就是方法二函数在做的事情吗?所以方法一里面还是要调用方法二中函数的,方法一并没有把最小单位的重复动作设计成一个函数。
另一方面,方法一中直接把数据中的各属性输出到结构体,实际上是杂糅了业务相关的东西在里面,也就是说,如果换一个项目,仍然有json数据要处理,但是属性名字不是这些,而是其他命名的,那么方法一中的函数就不能直接复用移植,方法一并不是纯处理json格式数据的函数,杂糅了具体项目业务的协议在里面了,不够纯粹。方法一中函数适合放在具体业务处理的模块里面,方法二中函数才是json模块函数,可移植性比较好。
另外在进行模块设计时,有一个原则是“高内聚,低耦合”,显然如果方法一中的函数放到json模块中去,那就不够内聚了,与业务模块有一些耦合了。
6.2019年第2期《单片机与嵌入式系统应用》电子刊新鲜出炉!