嵌入式开发中从设计模式角度优化自己的代码

软件开发是一种智力活动,阅读不同经验的软件工程师写出来的代码,你会发现实现同样的功能,资深软件工程师写出来的代码会高大上很多。以下举例来说明一下:

先来看一个通讯协议相关的例子,数据帧定义如下:

帧长度 传感器类型 数据
1字节 1字节 n字节

传感器数据格式定义如下:

传感器 类型号 数据格式
压力传感器 整型数据(4字节)
流量传感器 整型数据(4字节)

初级工程师的实现代码可能如下:

static int parse(const char *data,size_t n)
{
    int len = data[0];
    int type = data[2];
    int value;
    switch(type){
        case 1:
            value = *(int *)&data[3];
            printf("press= %d\r\n",value);
        case 2:
            value = *(int *)&data[3];
            printf("flow= %d\r\n",value);
        default:
            printf("parse error\n");
    }
    
}

上面这段代码,在传感器数据比较少的时候,看起来还比较简洁,但是我们系统中如果要添加更多的传感器类型,势必需要向switch case 语句中增加更多的case 语句。使得parse函数变得越来越臃肿。

当然,我们可以采用,如下方式规避一些问题

static int parse_press(const char *data,size_t len)
{
    assert(len == 4);
    int value = *(int *)data;
    printf("press= %d\r\n",value);
}
static int parse_flow(const char *data,size_t len)
{
    assert(len==4);
    int value = *(int *)data;
    printf("flow = %d\r\n",value);
}

static void parse(const char *data,size_t len)
{
    int data_len = data[0];
    int data_type = data[1];
    switch(type){
        case 1:
            parse_press(data+2,data_len-2);
            break;
        case 2:
            parse_flow(data+2,data_len-2);
            break;
        default:
            break;
    }
}

上面的代码相比与第一次实现有所改善,但是我们采用命令模式实现后,会看到,无论是可读性,可扩展性,都会得到相当程度的提高。

typedef int (*parse_func)(const char *data,size_t len);

struct parse_handler{
    int type;
    parse_func func;
}

static int parse_press(const char *data,size_t len)
{
    assert(len == 4);
    int value = *(int *)data;
    printf("press= %d\r\n",value);
}
static int parse_flow(const char *data,size_t len)
{
    assert(len==4);
    int value = *(int *)data;
    printf("flow = %d\r\n",value);
}

static struct parse_handler handlers = {
    {1,parse_press},
    {2,parse_flow},
};

#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
static parse_func parse_func_find(int type)
{
    int i;
    for(i=0;i

如上,需要增加或者修改传感器的时候,我们只需要关注handlers这个数组。

static struct parse_handler handlers = {
    {1,parse_press},
    {2,parse_flow},
};

这样写的优势

传感器类型和解析实现直接写在了同一行,非常直观,也没有必要将传感器类型数据定义为宏。
添加传感器的时候,只要在结构体数组中添加一行即可,如果是第二种实现,则需要在parse函数中,添加一个case语句,若是遗忘了break很容易导致错误。

这种实现方式,基本是此类问题的最优解。被称为命令模式。一个type被称为一个命令,解析函数对应于命令的实现。

你可能感兴趣的:(嵌入式开发中从设计模式角度优化自己的代码)