本文主要是介绍一个合格的平台化组件应该是什么样的(linux C语言),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 1. 为什么要开发平台化组件
- 2. 平台化组件是什么
- 2.1 平台化组件的定义
- 2.2 定义说明
- 3. 如何做好平台化
- 3.1 合理的开发目录
- 3.2 框架必要结构
- 3.3 开发&维护流程
- 3.4 组件更新日志类型
- 3.5 平台化组件代码基本规则
- 3.6 平台化组件代码必要注释信息
- 3.7 平台化组件版本说明
- 4.8 自动化处理脚本工具
- 4. 几个思考
- 5. 结尾
1. 为什么要开发平台化组件
- 项目或者业务越来越复杂的情况下,组件化开发更适合快速迭代,在添加修改组件时候不需担心影响其他组件
- 解决业务模块划分不清晰,耦合度大,较难维护
- 可单独开发,测试,发布一个组件,不需要像以前一样开发完某个功能,就需要编译、运行、打包整个项目
- 某个组件出现问题,可直接对组件进行处理,不必担心会因为修改而影响到整个工程
- 组件划分后,组件的开发不受其他业务影响,可以多个组件并行开发,加快开发进度
- 组件可以很好的提升代码的可重用性(而非可复制性),如果有其他项目需要该组件可以直接引入使用,而不是拷贝代码,拷贝资源等
- 组件单独测试方便,测试完成后进行集中测试,如果后期有修改组件,只要组件提供的能力或者接口不发生改变,就不需要再次进行集中测试,减少测试工作量
- 如果有新人的加入,可以直接分配组件进行开发,而非需要熟悉整个项目,可以从一个组件的开发使新进人员比较快速熟悉项目、了解到开发规范
- 组件中包含有基础组件,这些组件也算是技术的一种积累,为未来开发新项目提供更快速的响应
- 可以更早下班
组件化就是将一个产品拆分成一个个小的功能模块,每个功能模块完成属于自己这部分独立的功能,使得整个项目的管理和维护变得非常容易。
保证代码在高质量完成需求的同时具备良好的可读性、可维护性。
2. 平台化组件是什么
2.1 平台化组件的定义
- 一个包含源代码、说明文档、demo、成果物自动输出脚本的代码目录
- 一个源代码为高内聚低耦合的代码集合
- 一个源代码至少包含
组件初始化
、组件销毁
、组件运行
、组件回调函数注册
四大接口的框架 - 一个可适用于多个嵌入式平台的组件
2.2 定义说明
- 高内聚低耦合:demo可单独运行在嵌入式平台
- 上述四大接口需要在对外提供的头文件中体现
- 组件初始化:分配组件运行需要的空间与资源,如存放回调函数结构体的内存,初始化锁、信号量等
- 注册回调函数:组件与外部调用者之间的协议数据交互、日志回调函数注册
- 组件运行:数据收发、流程处理
- 销毁组件:释放组件相关资源
3. 如何做好平台化
3.1 合理的开发目录
Component_name //平台化组件名称
├── Makefile //打包生成库
├── README.md //简要说明组件用途
├── demo //演示组件库接口使用
│ ├── Makefile
│ └── src
├── docs //存放组件相关文档
│ ├── 使用说明.html
│ ├── 使用说明.md
│ ├── 概要设计.doc
│ └── 详细设计.doc
├── include //组件需要依赖的头文件
├── lib //组件需要依赖的库
├── src //组件源代码
├── test //单元测试代码
├── third_party //组件需要依赖的第三方源码
├── tools //组件相关的工具,如脚本
└── output //组件输出成果物└── gcc-arm-none-xxx //交叉编译链└── Component_name //组件名称├── include //对外提供头文件│ └── Component_name│ └── Component_name.h└── lib //对外提供封装库└── libComponent_name.a
- makefile的编写方法参考我这篇文章
3.2 框架必要结构
- 大多数情况下,至少包含
组件初始化
、组件销毁
、组件运行
、组件回调函数注册
四大接口的框架 - 开源框架参考:https://github.com/jobbole/awesome-c-cn#frameworks
3.3 开发&维护流程
- 开发流程
- 维护流程
3.4 组件更新日志类型
- [ADD]新增
- [OPT]优化
- [CHG]修复
- [DEL]移除
3.5 平台化组件代码基本规则
代码中,如果不符合以下原则,必须特别说明。
以下规则的目的是为了降低开发中犯错的概率,仅供参考
- 变量定义时必须赋初值
- 较大的内存要从堆上分配,不能从栈上分配
- switch语句必须有default选项
- switch语句中,每个case必须加break(多个case有相同处理流程除外)
- if语句必须有else项,如果if语句内含有不会依次向下执行的语句除外(return,break,continue)
- if语句中,变量与0做比较
- 布尔:if(flag), if(!flag)
- 整型:if(0 == value), if(0 != value)
- 指针:if(NULL == ptr), if(NULL != ptr)
- 浮点:const float EPSINON = 0.00001; if ((x >= - EPSINON) && (x <= EPSINON)
- 遇到if/else/return的组合,应该写为 return (condition? x:y);
- 不要用return语句返回指向“栈内存”的指针
- 定义一个结构体必须要对齐(提高内存空间利用率,在内存共享的情况下防止数据错位)
https://blog.csdn.net/TAlice/article/details/82016508?spm=1001.2014.3001.5501 - 不允许使用全局变量,但可以使用静态全局变量(防止增大代码耦合度)
- 只在当前C文件内调用的函数,定义时必须加上static关键字
- 循环操作里要有超时机制
- 禁止对指针求sizeof,这样做有可能会将指针的长度视为指针所指向地址的长度,导致犯错
- 函数入参必须检查其合法性
- 添加必要的注释,但没有注释比错误的注释好(保证必要的注释的正确性)
- 代码的编写要简单易懂,同时要考虑到后期的低成本维护
- C语言写的代码,声明时需加宏限制
#ifdef __cplusplus extern "C" { #endif#ifdef __cplusplus } #endif
3.6 平台化组件代码必要注释信息
- 文件头版权信息
/********************************************************************************** Copyright: (C) 2018 Wang Tao* All rights reserved.** Filename: thread.c* Description: This file * * Version: 1.0.0(2018年05月15日)* Author: wang tao <TAlicer@163.com>* ChangeLog: 1, Release initial version on "2018年05月15日 00时34分04秒"* ********************************************************************************/
- 函数说明信息
/** @brief Example function for orange project * * Example text * * @param[in] param1 description for param1* @param[out] param2 description for param2* @return none*/
3.7 平台化组件版本说明
软件和说明文档版本A.B.C这些数字分别代表什么意思
以Spark1.6.0为例子来说明。
- 第一个数字:1
major version : 代表大版本更新,一般都会有一些 api 的变化,以及大的优化或是一些结构的改变;
- 第二个数字:6
minor version : 代表小版本更新,一般会新加 api,或者是对当前的 api 就行优化,或者是其他内容的更新,比如说 WEB UI 的更新等等;
- 第三个数字:0
Patch version,代表修复当前小版本存在的一些 bug,基本不会有任何 api 的改变和功能更新;
4.8 自动化处理脚本工具
- 当前工具能自动生成平台化组件目录、必要基础文档框架、基础Makefile框架,链接
- 使用方法:
wangtao@DESKTOP-1D526UH:~/Demo$ ./cmptTool.sh
Please input Component_name:test_component
Please input Author_name:wangtao
Successfully generated test_component
4. 几个思考
-
需求与代码哪个重要?
- 并不是所有的产品都能提出合理的需求,当你面对一个提出不合理需求的产品的时候,你需要坚持自己的原则,不能妥协。
-
什么是测试驱动代码?
- 测试驱动代码,你写的代码要可以执行单元测试。如果你发现你的代码很难写单元测试,那么你就要思考你的代码是不是已经不整洁了,或者说已经乱成一团了。
-
什么是简单的代码?
- 能通过所有测试
- 如果某段代码在程序设计中反复出现,就证明想法在代码中没有很好的体现出来。总之,不要重复代码,只做一件事,小规模抽象。
-
平台化组件向外(各产品线)提供成果物的形式(库or源码)
- 不做平台化:前期快、中期慢、后期更慢
- 提供成果物的形式-源码:前期慢、中期快、后期慢
- 提供成果物的形式-库:前期慢、中期快、后期更快
那我们到底要如何抉择:
- 无论哪一种,都应该以开发一个库的标准去要求自己,这样才能保证代码的高内聚与高度模块化
- 建议先以源码的形式提供平台化组件,等功能稳定、对外接口固定后再以库+头文件的形式提供平台化组件
-
单元测试在实际过程中存在的问题(以下观点来自某大佬)
作为C程序员,为什么我们在工作过程中很少被要求做单元测试,以至于工作一两年之后甚至都没听说过单元测试,但是大多数开源项目都是有做单元测试的?我认为有以下几点原因:- C程序员大部分都是做嵌入式工程师,偏底层,多多少少都和硬件沾边,以至于弱化了软件设计;
- 嵌入式岗位的产品大多数做是靠实体产品挣钱,不是靠软件服务,普遍不注重软件维护;
- 单元测试也是写代码,也会占用工作时间,上班的都知道,工作是做不完的,所以不愿意去写单元测试;
- 公司决策,公司、部门专注于产品快速迭代,以完成软件功能为首要,反正有专门的测试团队,要求程序员快速完成功能,却不对代码质量做把控;
- 开源项目不一样,开源项目可能会被每个程序员查看,代码写得太差,可没关注量,个人、团体、公司的形象就上不去;
- 开源项目一般都会持续迭代,使用单元测试优势特别明显,能快速迭代,快速测试;而且开源项目由于其特性,以至于每个人都可以使用简单的环境进行测试,如果使用人工测试的方法就很难满足;
- 开源项目使用的技术理念相对比公司内更激进,接纳意愿更高,大环境也更容易满足。
那我们到底要如何抉择:
- 写良好的软件,我认为应该是每个程序员的基本专业、职业素养,要有这样的心态去写代码;
- 如果你的公司、部门要求做单元测试,我觉得这是幸运的;
- 如果公司没要求,你可以提建议,谈谈单元测试的优势,要是有不可逆因素拒绝了你的提议,那你可以在开发之余为你的代码编写单元测试;
- 如果你是在做开源项目,应该没有太多说的,懂的都懂。
从cmockery入门C语言单元测试
5. 结尾
不知不觉,毕业已经快三年了,见过很多很好的代码,也见过不少的烂代码。最后我几乎绝望的发现,无论是谁写的代码,只要经过时间的洗礼,都会变成一堆屎山。我们就像不断重复把一块巨石推上山顶的西西弗斯,而我们唯一能做的,就是向好代码学习,向烂代码反省。正如团长说的那样,“一尘不染的事情是没有的,我们每天都在吸进灰尘,但不妨碍把事情做得好一点啊。”
这篇关于一个合格的平台化组件应该是什么样的(linux C语言)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!