从开源项目学习 C 语言基本的编码规则

本文由 伯乐在线 - 清蒸竹马 翻译自 CoderGears Team。未经许可,禁止转载!

欢迎加入:翻译小组,通过 翻译频道 贡献一份力量。

每个项目都有自己的风格指南:一组有关怎样为那个项目编码约定。一些经理选择基本的编码规则,另一些经理则更偏好非常高级的规则,对许多项目而言则没有特定的编码规则,项目中的每个开发者使用他自己的风格。

所有代码都保持一致风格的大型库,更容易让人理解。

有许多资源是关于能让人采取的更好的编码规则的,我们可以通过以下方式学到好的编码规则:

阅读书或杂志

浏览网站

与同事交流

参加培训

另一个更有趣的方法是通过研究一个成熟的知名开源项目来得知其开发者是怎样编写代码的。对于C语言来说,Linux内核是个不错的选择。

对初级甚至中级的C开发者而言,可能不太容易深入到Linux内核的代码中,但是我们的目标不一定得是对它的源码做出贡献,而是探索它是怎样实现的。

让我们以来自Linux源码中的一个函数实现为例:

这段代码看起来非常干净,实际上这个函数

仅有几行代码

签名定义得好

注释写得好

缩进安排得好

变量名非常清晰

同样的功能可以被另一个开发者以下面这种方式实现

编码风格对源码的可读性影响甚巨,投入一些时间培训开发者以及周期性评审代码总有利于轻松地维护和升级代码。

让我们使用CppDepend深入到Linux内核的源码中,发现一些它的开发者们采用的编码规则。

模块化

模块化是一种提升使用不同独立部分构建软件的程度的设计技巧,你可以轻松地管理维护模块化的代码。

对于像C这种没有名字空间(namespace)、组件(component)或者类(class)等逻辑构件的过程语言,我们可以使用目录和文件实现模块化。

下面是一些可能的情形:

把所有的代码放在一个目录中

分离出与一个模块或子模块有关的文件,再放入一个特定的目录

Linux内核使用目录和子目录来模块化核心源码:

封装

封装是指隐藏一份实现内部的功能与数据。在C中,封装是通过使用关键字static实现的。这些实体称为文件域的函数和变量。

让我们通过执行下面的CQLinq查询语句查找一下所有的静态函数:

使用Metric视图,我们可以清楚地看到有多少个函数是静态的。在Metric视图中,代码库由树形图(Treemap)描述。树形图(Treemap)是一种使用嵌套矩形来展示树结构数据的方法。CppDepend中树形图使用的树结构就是通常的代码层次结构:

项目包含目录

目录包含文件

文件包含结构体,函数和变量

树形图视图为描述一条CQLinq请求的结果提供了一种有用的方式,所以我们能够可视化地看到与该请求有关的类型。

正如我们所见,许多函数都声明为静态的

现在我们来查询静态域:

和函数的标记一样,许多变量都声明为静态属性。

在Linux内核源码中,只要函数和变量对于文件域而言是私有的,就使用封装的手法。

使用结构体存储你的数据模型

在C编程中,函数使用变量达到不同的处理要求,这些变量可以是:

静态变量

全局变量

局部变量

结构体变量

每个项目都有一些可以被很多源文件使用的数据模型,可以使用全局变量,但这不是好的解决方案,更推荐使用结构体对数据分组。

让我们搜索一下属于基本类型的全局变量:

仅有几个变量与该查询匹配,也许我们可以把这些变量中的一些分组到结构体中,例如(elfcorehdr_addr and elfcorehdr_size),或者是(pm_freezing and pm_nosig_freezing)这样。

让函数短小而干练

下面是来自linux编码风格网页的一份关于函数长度的建议:

函数应该短小而干练,并且一个函数只做一件事。它们应该恰好占据一屏到两屏(我们都知道ISO/ANSI标准屏幕的大小为80×24),只做一件事并且做得很好。

一个函数的最大长度与它的复杂程度和缩进层级成反比。所以,如果你有一个概念上简单的函数,这个函数包含着冗长的(但是简单)case语句,而每个case分支都对应着为不同情况而不得不进行简单处理,那么这个函数长点也没多大关系。

让我们找找多于30行的函数:

多于30行的方法仅有几个。

函数参数的个数

拥有多于8个参数的函数调用起来可能很伤神,还可能降低函数的性能。一个替代方案是提供一个专职传参的结构体。

仅有2个方法的参数多于8个。

局部变量的个数

方法的局部变量超过8个,会让方法难以理解,也难以维护。超过15个就非常复杂,这时应该拆分成两个更小的方法(使用工具自动生成的除外)。

仅仅5个函数的局部变量超过15个。

避免定义复杂的函数

有许多度量复杂函数的指标,上面提到的代码行数、参数个数和局部变量个数是基本的。

还有些其他有趣的指标:

环路复杂度在过程软件中是一个广为使用的指标,等于一个过程可以接纳的决议的个数。

嵌套深度是一个定义在方法上的指标,该指标与方法体中最深嵌套作用域成正比。

最大嵌套循环等于嵌套在一个函数中最深循环层级。

这些指标的可接受最大值更多依赖于团队的选择,并没有标准参考值。

让我们找找可能需要重构的函数:

只有很少几个可以被认为是复杂的函数。

命名约定

命名约定没有标准,每个项目经理都可以选择他们认为更好的规范,重要的是遵守选择的约定,让项目拥有一致的命名。

例如在Linux中,结构体必须以小写字母开头,我们可以验证一下这条规则在整个核心代码中是否成立,执行下面的查询:

仅有4个结构体以“_”代替小写字母开头。

缩进

缩进非常有利于让代码容易阅读,下面这段摘自linux编码风格网页的文字,说明了隐藏在使用缩进背后的动机。

原理阐释:缩进背后整体思想是为了清楚地定义一个控制块的开始与结束。特别是当你已经持续对着屏幕长达20个小时的时候,你更容易发现缩进是怎样发挥功效的(如果你有大量的缩进)

当前,有的人会声称,八字符的缩进会让代码行右端伸太远,这会是代码在80字符宽度的终端屏幕上难以阅读。对此的答案是:如果你需要多于3级缩进的话,不管怎么说,你已经陷入囹圄,你应该修改你的程序。

结论

探究一些知名开源项目总是有利于提高你的编程技巧,没必要下载生成该项目,你从——比如说——GitHub上就可以发现这些代码。

本文由 伯乐在线 - 清蒸竹马 翻译自 CoderGears Team。未经许可,禁止转载!

欢迎加入:翻译小组,通过 翻译频道 贡献一份力量。

每个项目都有自己的风格指南:一组有关怎样为那个项目编码约定。一些经理选择基本的编码规则,另一些经理则更偏好非常高级的规则,对许多项目而言则没有特定的编码规则,项目中的每个开发者使用他自己的风格。

所有代码都保持一致风格的大型库,更容易让人理解。

有许多资源是关于能让人采取的更好的编码规则的,我们可以通过以下方式学到好的编码规则:

阅读书或杂志

浏览网站

与同事交流

参加培训

另一个更有趣的方法是通过研究一个成熟的知名开源项目来得知其开发者是怎样编写代码的。对于C语言来说,Linux内核是个不错的选择。

对初级甚至中级的C开发者而言,可能不太容易深入到Linux内核的代码中,但是我们的目标不一定得是对它的源码做出贡献,而是探索它是怎样实现的。

让我们以来自Linux源码中的一个函数实现为例:

这段代码看起来非常干净,实际上这个函数

仅有几行代码

签名定义得好

注释写得好

缩进安排得好

变量名非常清晰

同样的功能可以被另一个开发者以下面这种方式实现

编码风格对源码的可读性影响甚巨,投入一些时间培训开发者以及周期性评审代码总有利于轻松地维护和升级代码。

让我们使用CppDepend深入到Linux内核的源码中,发现一些它的开发者们采用的编码规则。

模块化

模块化是一种提升使用不同独立部分构建软件的程度的设计技巧,你可以轻松地管理维护模块化的代码。

对于像C这种没有名字空间(namespace)、组件(component)或者类(class)等逻辑构件的过程语言,我们可以使用目录和文件实现模块化。

下面是一些可能的情形:

把所有的代码放在一个目录中

分离出与一个模块或子模块有关的文件,再放入一个特定的目录

Linux内核使用目录和子目录来模块化核心源码:

封装

封装是指隐藏一份实现内部的功能与数据。在C中,封装是通过使用关键字static实现的。这些实体称为文件域的函数和变量。

让我们通过执行下面的CQLinq查询语句查找一下所有的静态函数:

使用Metric视图,我们可以清楚地看到有多少个函数是静态的。在Metric视图中,代码库由树形图(Treemap)描述。树形图(Treemap)是一种使用嵌套矩形来展示树结构数据的方法。CppDepend中树形图使用的树结构就是通常的代码层次结构:

项目包含目录

目录包含文件

文件包含结构体,函数和变量

树形图视图为描述一条CQLinq请求的结果提供了一种有用的方式,所以我们能够可视化地看到与该请求有关的类型。

正如我们所见,许多函数都声明为静态的

现在我们来查询静态域:

和函数的标记一样,许多变量都声明为静态属性。

在Linux内核源码中,只要函数和变量对于文件域而言是私有的,就使用封装的手法。

使用结构体存储你的数据模型

在C编程中,函数使用变量达到不同的处理要求,这些变量可以是:

静态变量

全局变量

局部变量

结构体变量

每个项目都有一些可以被很多源文件使用的数据模型,可以使用全局变量,但这不是好的解决方案,更推荐使用结构体对数据分组。

让我们搜索一下属于基本类型的全局变量:

仅有几个变量与该查询匹配,也许我们可以把这些变量中的一些分组到结构体中,例如(elfcorehdr_addr and elfcorehdr_size),或者是(pm_freezing and pm_nosig_freezing)这样。

让函数短小而干练

下面是来自linux编码风格网页的一份关于函数长度的建议:

函数应该短小而干练,并且一个函数只做一件事。它们应该恰好占据一屏到两屏(我们都知道ISO/ANSI标准屏幕的大小为80×24),只做一件事并且做得很好。

一个函数的最大长度与它的复杂程度和缩进层级成反比。所以,如果你有一个概念上简单的函数,这个函数包含着冗长的(但是简单)case语句,而每个case分支都对应着为不同情况而不得不进行简单处理,那么这个函数长点也没多大关系。

让我们找找多于30行的函数:

多于30行的方法仅有几个。

函数参数的个数

拥有多于8个参数的函数调用起来可能很伤神,还可能降低函数的性能。一个替代方案是提供一个专职传参的结构体。

仅有2个方法的参数多于8个。

局部变量的个数

方法的局部变量超过8个,会让方法难以理解,也难以维护。超过15个就非常复杂,这时应该拆分成两个更小的方法(使用工具自动生成的除外)。

仅仅5个函数的局部变量超过15个。

避免定义复杂的函数

有许多度量复杂函数的指标,上面提到的代码行数、参数个数和局部变量个数是基本的。

还有些其他有趣的指标:

环路复杂度在过程软件中是一个广为使用的指标,等于一个过程可以接纳的决议的个数。

嵌套深度是一个定义在方法上的指标,该指标与方法体中最深嵌套作用域成正比。

最大嵌套循环等于嵌套在一个函数中最深循环层级。

这些指标的可接受最大值更多依赖于团队的选择,并没有标准参考值。

让我们找找可能需要重构的函数:

只有很少几个可以被认为是复杂的函数。

命名约定

命名约定没有标准,每个项目经理都可以选择他们认为更好的规范,重要的是遵守选择的约定,让项目拥有一致的命名。

例如在Linux中,结构体必须以小写字母开头,我们可以验证一下这条规则在整个核心代码中是否成立,执行下面的查询:

仅有4个结构体以“_”代替小写字母开头。

缩进

缩进非常有利于让代码容易阅读,下面这段摘自linux编码风格网页的文字,说明了隐藏在使用缩进背后的动机。

原理阐释:缩进背后整体思想是为了清楚地定义一个控制块的开始与结束。特别是当你已经持续对着屏幕长达20个小时的时候,你更容易发现缩进是怎样发挥功效的(如果你有大量的缩进)

当前,有的人会声称,八字符的缩进会让代码行右端伸太远,这会是代码在80字符宽度的终端屏幕上难以阅读。对此的答案是:如果你需要多于3级缩进的话,不管怎么说,你已经陷入囹圄,你应该修改你的程序。

结论

探究一些知名开源项目总是有利于提高你的编程技巧,没必要下载生成该项目,你从——比如说——GitHub上就可以发现这些代码。


相关文章

  • 通用投票管理系统的设计与实现
  • 大连东软信息学院 毕业设计(论文) 论文题目:通用投票管理系统的设计与实现 系 所: 计算机科学与技术系 专 业: 学生姓名: 韩阔 学生学号: 指导教师: 闫海珍 导师职称: 副教授 完成日期: 2014 年 04 月 27 日 大连东软 ...查看


  • 11社区可行性分析报告
  • 可行性分析报告 项目名称_________11社区__________ 拟 制 人____ __ 审 核 人_________ _____________ 批 准 人____ __ 目录 一.引言...................... ...查看


  • 初入IT业如何做好角色转换
  • 导读: 2006年9月23日-24日,由希赛网承办的2006中国软件工程大会暨系统分析员年会在湖南长沙召开.以下是与会专家漆英"初入IT业如何做好角色转换"主题演讲具体内容. 漆英在做"初入IT业如何做好角色转 ...查看


  • 高校教师管理系统
  • 课程设计说明书 课程名称:项目名称: 学 院: 专 业:班 级:姓 名:指导教师:完成时间: 信息系统分析与设计课程设计 高校教师管理系统 计算机工程学院 XXX XXX XXX XXX 2013年1月6日 目 录 摘 要......... ...查看


  • 软件测试理论知识
  • 开篇第一章 测试基础 软件测试的定义: 使用人工和自动的手段来运行或测试某个系统的过程.其目的是检验它是否满足规定的需求或弄清预期结果与实际结果间的差别. 软件测试的目的: 证明 检测 预防 证明: 1) 获取系统在可接受风险范围内可用的信 ...查看


  • 人力资源管理系统软件工程毕业设计论文
  • 摘要 人力资源管理系统是现代企业的核心业务系统之一,人力资源管理的状况和水平对企业的运作和效率至关重要.现代企业人力资源管理的内容非常丰富,可能包含档案管理.合同管理.薪酬管理.招聘管理.绩效管理.系统管理等很多部分.在本次毕业设计中,我们 ...查看


  • 软件开发工作总结
  • 软件开发工作总结 1. 分享第一条经验:学历代表过去.能力代表现在.学习力代表未来.其实这是一个来自国外教育领域的一个研究结果.相信工作过几年.十几年的朋友对这个道理有些体会吧.但我相信这一点也很重要:重要的道理明白太晚将抱憾终生!所以放在 ...查看


  • 基于短语的阿拉伯语到中文的机器翻译系统
  • 第26卷第6期2009年6月 计算机应用研究 ApplicationResearchofComputers Vol.26No.6Jun .2009 基于短语的阿拉伯语到中文的机器翻译系统 李 凯,郑 洁,蒋同海 (中国科学院新疆理化技术研究 ...查看


  • 流媒体/流媒体文件格式详解
  • 摘  要   流媒体文件格式在流媒体系统中占有重要地位,设计合理的文件格式是提高流媒体服务器工作效率最直接和最有效的办法.该文在剖析常用流媒体系统和文件格式的基础上,特别地对美国xiph.org基金会的开源流媒体工程Ogg文件格式子项目做了 ...查看


热门内容