面向接口编程思想及其实现

人生秃如其来,体重无福消瘦。

这是我的第二十九篇原创文章

来工作了这么久,其实嘛,也学到了一些东西,实实在在东西就不说了。比如XXX驱动,XXX开发板呀啥的。我觉得嘛,我们做程序员的,不应该是码农,应该努力做一个工程师。他们有啥区别呢?

于我而言,码农,就是纯粹敲代码的人。在国内,绝大多数应该都是码农。大多没多少的创造力,因为我们现在所做的东西,95%都能在百度找到,还有的4%应该能在google中找到,最后的1%就是大神们创造的。码农的工作实际上只是为了完成任务而存在的。而对于工程师而言,他们是有一定的自我创造能力的,他们是为了解决某个具体的问题而存在的,或者在某一项领域中小有研究,能在其中找到灵感。

在某种意义上,我也是码农。所以我一就直认为,我们做程序员的,我们的工作意义不是写代码,而是理解为什么要这样写以及这样写的好处是啥,应该了解他背后的深层次的含义。

好吧好吧,扯的有点多。这周就聊聊从开始工作至今,我工作中的一些编程的想法和技巧,如果能耐心看完这篇文章的话,我想应该还是有所帮助的。

1

面向对象(接口)的编程思想

对于像我一样的嵌入式程序员来说,学会面向对象的编程思想是非常有必要的,为啥呢?因为我是做嵌入式的,举个我工作中的例子呗。

例如要开发一款OLED液晶屏驱动,好,你写好了,给客户发过去了,客户也使用你的驱动,用的很爽,也将他的工程写好了。后来发现他选择的OLED似乎不满足要求,客户要求重新写驱动,但是不能改接口,因为代码量太大了,难以维护。

这时候问题来了,重写?但是函数命名问题和接口定义怎么办?显然这样代码的可扩展性和复用性都特别的低。那为什么不一开始定义好接口,写通用的接口呢?下面我就说说我在工作中的做法吧。这里就以oled为例子讲解咯。

2

通用服务句柄

首先定义通用的服务句柄,这里用句柄的原因主要是给设备做分类,一个句柄就表示一个(类)设备。为啥要这样呢?继续往后看。通用句柄定义如下:

里我就简单的列出几个功能函数,讲解方便点,如果需要添加,也就是依葫芦画瓢而已。结构体定义如下:

这几个函数就是具体的OLED驱动驱动给上层接口提供的,这些接口都是抽象的行为函数,类似一个虚函数表,那具体的实现就应该在具体的驱动实现。因为每个函数实现都需要一个设备传入,但是每个设备的句柄都不同,我们又要做的是通用接口,所以只能做一个数据的封装(void * ),让具体的驱动自己解析句柄。下面是行为函数,定义如下:

以上就是一个通用接口的设计了,但是我这个通用接口只有一堆的虚函数,没有具体的实现,显然是不可以使用的。下面我们虚拟一个设备来实现来实现。

3

添加设备

我们要使用通用接口,那具体的设备肯定要继承他的方法咯。然后就是拓展具体设备自己的属性。示例如下:

例如例子中的oled1设备结构体就是继承及通用接口的方法,继而拓展自己的属性设备信息。设备结构体定义完毕了,接下来就是来初始化这个设备。因为每个设备都有初始化差异,不想他们的行为一样的有共性,所以不能是通用接口。这个就得向外提供设备自己的初始化和解初始化函数。我的例子如下:

因为设备初始化中肯定是用户自己的配置,所以肯定是用户传入的。一般情况下这些初始化配置信息用户只需要配置一次,所以考虑用信息表的形式写入。这样的一个好处就是,我初始化一个设备,不需要参数进来,只需要修改参数表的信息就可以。

4

设备信息设置

新建一个配置&&初始化文件,这里是一个例子,所以配置就写了一个,如果需要拓展,自己发挥咯。我的设备信息定义如下:

所以我们就向外提供2个函数,实例初始化和解初始化函数。简化了用户使用复杂度。好, 现在简单的框架已经搭建好了,要做的只有具体实现接口了。

5

驱动实现

我们先来实现初始化函数和解初始化函数。初始化函数除了要初始化设备本身应该初始化的功能之外,在这之前应该填充这个设备句柄信息,示例如下:

初始化函数中有一个功能函数的赋值,这个全局变量就是这个结构的重点,我们就是利用这个赋值实现的通用接口,该全局变量定义如下:

这里利用了一些宏,主要是利用这些宏,便于读者阅读函数,一些类型定义和声明的宏定义如下:

到这里为止,就是已经实现一个通用OLED接口定义了,那具体能不能用呢? 拉出来溜溜就知道了。

6

测试代码

测试代码如下:

上面代码所有的函数都测试一遍了,除了初始化和解初始化函数,其他的我们都用调用通用接口我们写一个makefile编译运行下咯,makefile如下:

运行结果如下:

看吧,运行一切正常。如果我们一开始使用的是这样的接口,那添加新的驱动就太容易了,只需要向接口层提供一套功能函数就可以了,其他代码都不用动的 ,对于用户来说,还一个驱动只需要还一个初始化函数而已,其他不用改动,是不是将代价降到了最低,这个就是我们常说的高内聚低耦合。不仅仅如此,我们如果思维在开阔点,我们使用这个方式是不是可以实现驱动的跨平台呢?

-END-

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181124G1IULT00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券