一个合格的平台化组件应该是什么样的(linux C语言)

2024-03-11 23:48

本文主要是介绍一个合格的平台化组件应该是什么样的(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 开发&维护流程
  • 开发流程
确认需求
编写原理文档
建立平台化组件开发目录
确定代码主要框架
编写确定对外提供头文件
编写单元测试代码
编写demo代码
开发组件代码
单元测试和demo验证
  • 维护流程
邮件发布组件
源码or库+头文件
使用文档
协助第一次集成,接收各产品线反馈
调整组件,更新文档
单元测试和demo验证
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语言)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/799475

相关文章

Linux使用nload监控网络流量的方法

《Linux使用nload监控网络流量的方法》Linux中的nload命令是一个用于实时监控网络流量的工具,它提供了传入和传出流量的可视化表示,帮助用户一目了然地了解网络活动,本文给大家介绍了Linu... 目录简介安装示例用法基础用法指定网络接口限制显示特定流量类型指定刷新率设置流量速率的显示单位监控多个

ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法

《ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法》本文介绍了Elasticsearch的基本概念,包括文档和字段、索引和映射,还详细描述了如何通过Docker... 目录1、ElasticSearch概念2、ElasticSearch、Kibana和IK分词器部署

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

Linux流媒体服务器部署流程

《Linux流媒体服务器部署流程》文章详细介绍了流媒体服务器的部署步骤,包括更新系统、安装依赖组件、编译安装Nginx和RTMP模块、配置Nginx和FFmpeg,以及测试流媒体服务器的搭建... 目录流媒体服务器部署部署安装1.更新系统2.安装依赖组件3.解压4.编译安装(添加RTMP和openssl模块

linux下多个硬盘划分到同一挂载点问题

《linux下多个硬盘划分到同一挂载点问题》在Linux系统中,将多个硬盘划分到同一挂载点需要通过逻辑卷管理(LVM)来实现,首先,需要将物理存储设备(如硬盘分区)创建为物理卷,然后,将这些物理卷组成... 目录linux下多个硬盘划分到同一挂载点需要明确的几个概念硬盘插上默认的是非lvm总结Linux下多

Go语言中三种容器类型的数据结构详解

《Go语言中三种容器类型的数据结构详解》在Go语言中,有三种主要的容器类型用于存储和操作集合数据:本文主要介绍三者的使用与区别,感兴趣的小伙伴可以跟随小编一起学习一下... 目录基本概念1. 数组(Array)2. 切片(Slice)3. 映射(Map)对比总结注意事项基本概念在 Go 语言中,有三种主要

linux进程D状态的解决思路分享

《linux进程D状态的解决思路分享》在Linux系统中,进程在内核模式下等待I/O完成时会进入不间断睡眠状态(D状态),这种状态下,进程无法通过普通方式被杀死,本文通过实验模拟了这种状态,并分析了如... 目录1. 问题描述2. 问题分析3. 实验模拟3.1 使用losetup创建一个卷作为pv的磁盘3.

C语言中自动与强制转换全解析

《C语言中自动与强制转换全解析》在编写C程序时,类型转换是确保数据正确性和一致性的关键环节,无论是隐式转换还是显式转换,都各有特点和应用场景,本文将详细探讨C语言中的类型转换机制,帮助您更好地理解并在... 目录类型转换的重要性自动类型转换(隐式转换)强制类型转换(显式转换)常见错误与注意事项总结与建议类型

Linux环境变量&&进程地址空间详解

《Linux环境变量&&进程地址空间详解》本文介绍了Linux环境变量、命令行参数、进程地址空间以及Linux内核进程调度队列的相关知识,环境变量是系统运行环境的参数,命令行参数用于传递给程序的参数,... 目录一、初步认识环境变量1.1常见的环境变量1.2环境变量的基本概念二、命令行参数2.1通过命令编程

Linux之进程状态&&进程优先级详解

《Linux之进程状态&&进程优先级详解》文章介绍了操作系统中进程的状态,包括运行状态、阻塞状态和挂起状态,并详细解释了Linux下进程的具体状态及其管理,此外,文章还讨论了进程的优先级、查看和修改进... 目录一、操作系统的进程状态1.1运行状态1.2阻塞状态1.3挂起二、linux下具体的状态三、进程的