前几天,看了一段代码,很有感触,于是自己进行了些思考,现将之撰文写出与诸君共勉。
这段代码是实现什么需求的呢?
需求是 设备网元中有多个单板,单板上对应多个命令字。我要随意的给对应单板上对应命令字的指令下发到设备上。
大家不用知道所谓的网元和单板是什么,反正该需求的目的就是要实现一个二维数组中的数据发出去。
按照正常的设计思路,我会设计一个二维数组,如下:
Param[MAX_BOARDID][MAX_CMDID]。
1)假如我要下发该数组中对应的一个元素到其他模块中,我会像如下这样来书写:
Send(Param[0][0]);
2)假如我要对一块单板下发所有的命令,我会像如下编写:
for (int i = 0; i < MAX_CMDID; i++)
{
Send(Param[0][i]);
}
3)假如我要对一个单板按照顺序下发所有的命令,我会多定义一个优先级表,在组成数组前将Param[0]排好序,伪码如下:
static const OrderTable[]; //优先级表
SetParamByOrder(data, OrderTable); //优先级作为入参,也可以直接在函数中调用,这里只是示例一下。
然后再执行上例的for循环。
4)假如我要对一个单板只下发另一单板以前下发过的命令。
那就要这么来写:
for (int i = 0; i < SizeofAnotherBoardParam; i++)
{
SetParamToMyBoard(i);
}
我们来看看这个原作者代码如何写的?
首先他定义了一个最小的元素Param,这里只有Get/Set,其类结构如下:
ParamGroup 组 --包含50个ParamRepository,通过BoardID查询
ParamRepository 库 --包含5个Param,通过CmdID查询
Param 元素
另外设计了ParamConfig类,实现对以上元素的管理。
ParamSynchronizer类,实现元素的创建,类似于工厂类
ParamPipe类,实现与设备通讯
ParamSwitcher类,实现倒换时处理,可以保存参数。
还有CfgParam实现传参作用,包含元素BoardId, CmdID
我们来看下上面的假如这里如何实现的。
1)假如我要下发该数组中对应的一个元素到其他模块中,我会像如下这样来书写:
ParamSynchronizer()->ParamPipe->Send(CfgParam);
2)假如我要对一块单板下发所有的命令,我会像如下编写:
int len = GetSizeOfParamRepository;
for (int i = 0; i < len; i++)
{
CfgParam = ParamRepository.At(i);
ParamSynchronizer()->ParamPipe->Send(CfgParam);
}
3)假如我要对一个单板按照顺序下发所有的命令,我会多定义一个优先级表,在组成数组前将Param[0]排好序,伪码如下:
static const OrderTable[]; //优先级表
在ParamRepository中添加时调整顺序即可。
然后再执行上例的for循环。
4)假如我要对一个单板只下发以前下发过的命令,那我只能先想办法将以前下发过的命令保存下来,然后才能下发。
在ParamRepository中已经包含了所有的历史命令
int len = GetSizeOfParamRepositoryAnotherBoard;
for (int i = 0; i < len; i++)
{
CfgParam = ParamRepositoryAnotherBoard.At(i);
ParamSynchronizer()->ParamPipe->Send(CfgParam);
}
上面用面向对象的方式把二维数组分解了一下,大家可以看一下,
其好处是一目了然,代码结构清晰了,在应用层只关心自己的内容,
循环遍历数组边界的东西没有,这些东西都隐藏在单独的类里,代码可读性,可维护性,
及犯错误的几率都小了很多。
仔细回味,有感:This is 面向对象的好处啊。