||
好的编程习惯,可以提高编程效率,不仅可以使代码容易修改,也容易给别人看懂,便于交流。我们不仅要写出“给机器读懂的代码”,也写出“给人看得懂的代码”。
本文根据一些目前搜索到的文献和自己的一些使用心得,整理出这个文档,大家可以根据经验提出自己的心得,相互促进,共同提高。
1,命名规则
(1) 变量
a, 使用英文。变量名最重要的原则就是,一看就知道这个变量是什么意思。由于程序大部分是字母,所以最好还是有英文字母表示意思比较靠谱。如果英文稍微差点,一下子不知道变量的英文怎么写,可以查字典,现在在线词典很多,这样还可以使自己的英文水平提高,二则可以提高程序可读性。比如,我们要表达“风速”,“windSpeed”比“fengsu”要好,时间久了,你再看“fengsu”的的时候,还必须得拼一下,搞不好就弄成“风俗”。
b, 变量名应该以小写字母开头的大小写混合形式。
例如,maturityDay,anthesisDay。
注意:有些人喜欢用“下划线”把词语隔开,maturity_day,athesis_day,这样也一目了然,但是在MATLAB中,不推荐这么用,因为下划线会在Tex解释程序中为下标的转换符,比如:xlabel(“maturity_day”),在图中会显示成“maturityday”。
c, 用大范围意义的变量名应该带有意义的名称,但下范围的变量名可以用短变量名。
例如:stepSize:大范围意义
dt(δt):小范围
d, 前缀n用在作为数值对象申明
例如:nRows
e, 遵循的一个有关复数变量的惯例
所有变量名要么为单数形式,要么为复数形式。两个变量只是最后相差一个字母s加以区别的情况应该避免,apple和apples区别2个变量,看着头大。可以用一个代表复数的标示,如:appleArray
f, 代表单个实体数据的变量可以加以后缀No或者是前缀i
例如,tableNo,employeeNo,
g, 循环变量应该以i,j,k为前缀
例如,iFiles,jPositions。不使用i,j,的原因是:因为这两个在matlab里面是虚数。
h, 嵌套循环,循环变量要以字母顺序
for iFile = 1:nFiles
for jPosition = 1:nPositions
…
end
end
i, 避免否定式的布尔变量命名。
例如:命名isNotFound,在使用判断的时候,~isNotFound,搞半天才知道啥意思。所以不适用否定式布尔变量命名。
j, 缩写形式,即使是通常的大写缩写,也应该于小写字母混合使用。
采用:html,isUsaSpecific,checkTiffFromat()
避免使用:hTML,isUSASpecific,checkTIFFFormat()
(2) 常数
a, 命名常数(包括全局变量)应该采用大写字母,用下划线分割单词。
例如:MAX_ITERATIONS,COLOR_RED
b, 参数可以以某些通用类型名作为前缀
COLOR_RED,COLOR_GREEN,COLOR_BLUE
(3) 结构体
a, 结构体的命名应该以一个大写字母开头
这是区别一般变量,例如:ParameterSet
b, 结构体的命名应该是隐性的,并且不需要包括字段名
用Segment.length.
避免Segment.segmentLength
(4) 函数
a, 函数名应该采用小写字母,且将函数名与它的m 文件名保存为相同
b, 函数名应该有具体的意义
避免短的函数名,这经常使得其名字含糊不清。
例如:
采用: computetotalwidth()避免: compwid()
c, 单输出变量的函数可以根据输出参数命名
例如,mean,std
d, 没有输出变量或者返回值为句柄的函数应该根据其实现的功能命名
例如:plot
e, 前缀get/set 应该作为访问对象或者属性的保留前缀
例如:getobj(.)
f, 前缀 compute应该用在计算某些量的函数的地方
例如:ComputWeightedAverage()
g, 前缀find可以用在那些具有查询功能的函数的地方
例如:FindOldestRecord(.);FindHeaviestElement(.);
h, 前缀initialize可以用在对象或者是概念(concept)建立的地方
例如:InitializeProblemState(.);
i, 前缀is应该用在布尔函数的命名的地方
例如:IsOverPriced(.)
j, 避免无意识地覆盖
有时候我们取的名字,可能在MATLAB中含有这个函数名了,可以用exist检查是否含有了。
k, 避免缩写
采用:ComputeArrivalTime(.)避免:CompArr(.).
l, 考虑使得名字可以拼读
2,文件与程序结构
(1) M文件
a, 模块化
编写一个大程序的最好的方法是将它以好的设计分化为小块(通常采用函数的方式)。
这种方式通过减少为了理解代码的作用而必须阅读的代码数量使得程序的可读性、易于理解性和可测试性得到了增强。超过编辑器两屏幕的代码都应该考虑进行分割。并且设计规划很好的函数也使得它在其他的应用中可用性增强了。
b, 确保交互过程清晰
函数通过输入输出参数以及全局变量与其他代码交互通信。使用参数几乎总是比使用
全局变量清楚明了。采用结构可以避免那种一长串儿的输入输出参数的形式。
c, 分割
所有的子函数和所有的函数都应该只把一件事情做好。每个函数应该隐藏(hide)一些东西。
d, 利用现有的函数
开发一个有正确功能的、可读的、合理灵活性的函数在一项有重大意义的任务。或许寻找一个现成的提供了要求的部分、甚至全部功能的函数应该更快也更具有正确性。
e, 任何在多个m文件中出现的代码块都应该考虑用函数的形式封装起来
f, 子函数
只被另外一个函数调用的函数应该作为一个子函数写在同一个文件中。这使得代码更加利于理解与维护。
g, 测试脚本
为每一个函数写一个测试脚本。这样可以提高初期版本的质量和改进版本的可靠性。
(2) 输入与输出
a, 编写输入/输出模块
输出要求可以无需特别注意就可以根据变化而改变,输入的格式与内容根据变化的时候经常很混乱。找到处理输出的地方进行改善,提高其可维护性。避免将输入/输出部分的代码与计算功能的代码混淆在一起,单个函数的预处理的时候除外。各种功能混合的函数的可再用性一遍很小。
b, 格式化输出使得其易于利用
如果输出很大可能是人工阅读,那么就让输出采用易于越多的描述性的方式。
如果输出更多的可能是通过其他软件调用而不是人,那么应该使得输出易于解析。
如果这以上两种情况都很重要,将输出表达成易于解析的格式,并编写一个格式化输出的函数用来产生一个人工可读的输出版本。
3,基本语句
(1) 变量与常数
a, 变量不应该重复使用
通过确保所有的概念都只有唯一的意义可以加强代码的可读性,以及通过消除误解的定义可以减少错误的可能。
b, 同种类型的相近的变量可以在同一个语句中定义
c, 不相近的变量应该不要在同一个语句中定义
d, 注意在文件开始部分的注释中为重要变量编写文档
MATLAB不需要变量申明,这种信息就可以在注释中提供。
示例:%pointArray Points are in rows with coordinates in columns.
e, 注意在语句行注释的最后为常数编写文档
示例: THRESHOLD = 10;%Maximumnoise level found by experiment。
(2) 全局变量
a, 应该尽量少地使用全局变量
(3) 循环语句
a, 循环变量应该在循环开始前立即被赋值。
这可以提高循环的速度,有助于防止循环没有执行所有的可能索引而产生的虚假值。
示例:
refult= zeros( nEntries,1);
forindex = 1:nEntries
result(index)= foo(index);
end
b, 在循环中应该尽量少用break与 continue
这些结构可以与goto 相比较,只有当他们可以证明用这些结构可以比他们相应的结构化部分有更好的可读性的时候,才可以使用。
c, 在嵌套式循环的时候应该在end行加上注释
在长的嵌套循环的end命令行添加注释可以有助于弄明白哪些语句在那个循环体内、在此处之前已经完成了哪些功能。
(4) 条件语句
a, 应该避免复杂的条件表示式,而采用临时逻辑变量进行替代
通过对表达式指定逻辑变量,使得程序更能够自为文档,使得程序结构更易于阅读
与调试。
示例:
避免使用:
if(value>=lowerLimit)& (values<=upperLimit)&~ismember(value,valueArray)
……
……
end
而应该用如下的方式代替:
isValid = (value=lowerLimit)& (values<=upperLimit);
isNew =~ismember(value,valueArray)
if ( isValid &isNew)
……
……
end
b, 在if else 结构的时候,发生较频繁的事件应该放在if 部分,例外情况放在else部分
这样通过将例外情况排除在常规执行路径之外可以提高程序的可读性。
示例:
fid = fopen(fileName);
if(fid~ = -1)
…
else
…
end
c, 条件表达式if 0 是应该避免的,除非在对临时程序块进行注释的时候
如果确信表达式在程序正常执行的时候不会发生,首选的方法是采用编辑器的块注释。
d, 一个 switch语句应该包含otherwise条件
将otherwise情况遗漏在外是一种通常错误,这或许会导致不可预测结果。
正确示例:
switch(condition)
case ABC
处理语句;
case DEF
处理语句;
otherwise
处理语句;
end
e, switch 变量应该通常是字符串
字符串在这种情况下能够很有效,通常他们比采用列举值的形式意义更丰富。
(5) 其它
a, 采用附加说明
MATLAB对于操作运算有个优先级的文档,但是谁愿意记住它们的具体内容呢?如果在某些地方有任何疑问,采用附加说明使得表达清楚。特别是在扩展的逻辑表达式的时
候尤其有用。
b, 尽量在表达式中少用数字。
可能会改变的数字应该用常数代替如果一个数字它的本身没有明确的意义,采用将它命名为常数可以加强程序的可读性。并且,改变参数的定义比改变文件中所有的相应出现地方的数字要容易得多。
c, 浮点常数应该在小数点前面写上一个阿拉伯数据
这是坚持数学习惯的语法要求,而且,0.5 比.5 更具有可读性,因为.5 很有可能被误认为是整数5。
d, 浮点数的比较应该要小心
二进制表达可能导致麻烦,如下面的例子所示:
shortSide = 3;
longSide = 5;
otherSide = 4;
longSide^2 ==(shortSide^2+otherSide^2)
ans =
1
scaleFactor = 0.01;
(scaleFactor*longSide)^2 = =((scaleFactor*shortSide)^2+(scaleFactor*otherSide)^2
ans =
0
e, clc;clear;close all
在一般的M文件开头,写这三个东西,可以初始化MATLAB,把打开的表,工作空间清理。
4,排版、注释与文档
(1) 排版
a, 应该将代码内容控制在前80列之内
对于一个编辑器、终端仿真器、打印机、调试器以及文件的通常列数是80列,因此通常几个人的程序共享的时候,大家通常将内容控制在前80列之内。在程序员之间传递文件的时候,避免无意识的分行可以增强程序代码的可读性。
MATLAB的M文件编排,有这个线提示。
b, 在恰当的地方应该将行进行切分
当语句长度超过80 列的限制的时候应该切分行。通常:
在一个逗号或者空格之后进行断开;
在一个操作符之后断开;
在表达式开始前的地方重新开始新的一行;
示例:
totalSum = a +b +c +…
d+e;
function (param1,param2,…
param3)
setText(['Long line split'…
'into two parts.']);
c, 基本缩排应该是3或者4个空格
好的缩排或许是唯一的一个展现程序结构的好方法。
1个空格是缩排太小而不能够强调出代码的逻辑分层;2个空格的缩排在为了减少因为嵌套循环超过80列而切分行的断裂的时候被建议采用,而MATLAB通常没有太多太深的循环嵌套。大于4个空格的缩排使得因为行切分的机会增大而使得代码的可读性变差。4个空格的缩排是MATLAB编辑器的缺省设置,在以前的一些版本,缺省缩排是3个空格。
d, 应该与MATLAB编辑器的缩排一致
MATLAB编辑器提供了使得代码结构清晰的缩排,并且与C++与Java推荐使用的缩排方式相一致。
e, 通常情况下,一行代码应该只包含一个可执行语句
f, 短的单个if,for 或者while语句可以写在一行。
if(condition),statement;end
while(condition),statement;end
for iTest = 1:nTest,statement;end
g, 空白空格
在 =,&,与| 前后加上空格
在指定的字符前后加上空格可以增强其可视化的分割提示,明显地将语句左右两部分分开。在二值逻辑操作符前后加上空格可以使得复杂的表达式清晰。
示例:
simpleSum = firstTerm+secondTerm;
h, 常规的操作符两边可以加上空格
这种方式是有争议的。部分人认为它可以增强其可读性。
示例:
simpleAverage= (firstTerm + secondTerm) / two;
1 : nIterations
i, 逗号后面可以加上空格
这些空格可以增强可读性。有些程序员为了避免切分行而不采用这种方式。
示例: foo(alpha, beta, gamma),也可以foo(alpha,beta,gama)
j, 分号或者同一行多条指令的逗号之后应该加上一个空格字符
空格加强可读性。
示例:if (pi>1),disp( 'Yes' ), end
k, 关键字后面应该加上空格
这种方式有助于区分关键字与函数。
l, 一个块(block)内部的一个逻辑组语句应该通过一个空白行将其分隔开
在块的逻辑单元之间加入空白行可以增强代码的可读性。
m, 块(blocks)之间应该用多行空白行分隔
一种方式是采用3 隔空白行。采用大的间隔来与块内分隔相区别,使得在文件中,
块看起来非常明显。另外一种方式是采用注释符号后面跟多个诸如*或者-。
n, 通过排列成行列整齐的方式来加强可读性
代码排列成行列整齐的形式可以使得切分表达式容易阅读与理解。这种排版也有助于
揭示错误。
示例: weithedPopulation = (doctorWeight *nDoctors) + …
(layerWeight* nLawyers) + …
(chiefWeight* nChiefs);
(2) 注释
注释的目的是为代码增加信息。注释的典型应用是解释用法、提供参考信息、证明结果、阐述需要的改进等。经验表明,在写代码的同时就加上注释比后来再补充注释要好。
a, 注释不能够改变写得很糟糕的代码效果
注释不能够弥补因为代码命名不当、没有清晰的逻辑结构等造成的缺陷。存在这样缺陷的代码应该重写。
b, 注释文字应该简洁易读
一个糟糕的或者是无用的注释反而会影响读者的正常理解。N.Schryer提到:“如果代码与注释不一致,那么或许两者都是错误的。”一个通常更重要的是注释应该讲的是“为什么”(Why)和“怎么做”(how),而不是“是什么”(what)。
c, 函数的注释写法(尽量使用英文)
如下例子:
%================================================================
% 功能: 求圆孔的夫琅禾费衍射光强分布
% 参数: CircleHoleFD为圆孔结构体,包含圆孔衍射相关信息;
% theta为衍射场的次波方向,可以为向量,求取各方向的光强
% 返回值: I为衍射光强分布
% 主要思路:使用夫琅禾费单缝衍射公式计算
% 备注: 入射角只考虑一个维度的
% 调用方法:见CalcCircleHoleFD_Test文件
% 日期: 2011/7/12 20:37
%================================================================
function I =CalcCircleHoleFD(CircleHoleFD, theta)
。。。(具体编程开始)
(3) 文档
a, 文档规范化
作为有用的文档应该包含一个对如下内容的可读性的描述:代码打算干什么(要求),
它是如何工作的(设计),它依赖于什其他什么函数以及怎么被其他代码调用(接口),以
及它是如何测试的等。对于额外的考虑,文档可以包含解决方案的选择性的讨论以及扩展
与维护的建议。
b, 首先考虑书写文档
一些程序员相信的方法是:“代码第一,回答问题是以后的事情。”而通过经验,我们
绝大多数人知道先开发设计然后再实现可以导致更加满意的结果。如果将测试与文档留在最后,那么开发项目几乎不能够按期完成的。首先书写文档可
以确保其按时完成甚至可能减少开发时间。
c, 修改
一个专业的对代码修改进行管理和写文档的方法是采用源程序控制工具。对于很简单
的工程,在函数文件的注释中加入修改历史比什么都不做要好。
参考文献:
Anonymous,Good Matlab Programming Practices for the Non-Programmer
Richard Johnson,MATLAB Programming Style Guidelines
Fayssal El Moufatich,MATLAB Programming Tips & Tricks:Part I Functional Programming
Genial 译,MATLAB 编程风格指南
了凡春秋:http://blog.sina.com.cn/s/blog_6163bdeb0102dqse.html
Programming Style Guidelines.pdf
Archiver|手机版|科学网 ( 京ICP备07017567号-12 )
GMT+8, 2024-11-20 09:48
Powered by ScienceNet.cn
Copyright © 2007- 中国科学报社