命名约定
命名往往是令人纠结的事情,即使一些大佬也曾发出过类似的感叹。
There are only two hard things in Computer Science: cache invalidation and naming things.
– Phil Karlton
通过规范化的命名可以提高代码的可读性,有效降低debug的工作量。
变量命名
-
变量名应使用小驼峰命名法,即第一个单词的首字母小写,后续单词首字母大写。
例如:
velocity, angularAcceleration.
-
作用域大的变量应该用有意义的名称。
作用域较小的变量可以用短名称。
例如:
x, y, z
-
前缀 n 应用于表示对象数量的变量。
例如:
nFiles, nCars, nLines
-
复数形式的约定
例如:
point, pointArray
-
代表单个实体编号的变量可以以编号No为后缀。
例如:
tableNo, employeeNo
-
迭代器变量应以 i、j、k 等命名或前缀。
iFiles, jColumns
-
对于嵌套循环,迭代器应按字母顺序排列,并提供有用的名称。
for iFiles = 1:nFiles
for jPositions = 1:nPositions
...
end
end
-
避免使用否定的布尔变量名
例如使用
isFound
而非isNotFound
-
首字母缩略词即使通常为大写,也应混合或小写。
html, isUsaSpecific
-
避免使用关键字或特殊值名称。
常量
-
命名常量应全部大写,并使用下划线分隔单词。
MAX_ITERATIONS, COLOR_RED
-
常量可以使用通用类型名称作为前缀。
COLOR_RED, COLOR_GREEN, COLOR_BLUE
结构体
-
结构体名称应使用大驼峰命名法,即每个单词的首字母都大写。
例如:
Car, DumpTruck
-
请勿在字段名称中包含结构体名称。
即使用
Segment.length
而不是Segment.segmentLength
函数
-
函数的名称应记录其用法,名称应该用小写或混合大小写。
width(), computeTotalWidth()
-
函数应该使用有意义的名称,例如使用
computeTotalWidth
而非compwid
-
具有单一输出的函数可以根据输出来命名
例如:
shearStress(), standardError()
-
没有输出参数或仅返回句柄的函数应根据其功能来命名。
例如:
plotfft()
-
为访问对象或属性保留前缀get/set。
例如:
getobj(), setappdata()
-
为计算某些内容的方法保留前缀compute。
例如:
computeSumOfResiduals(), computeSpread()
-
为查找内容的方法保留前缀find。
例如:
findOldestRecord()
-
保留前缀initialize用于实例化对象或概念。
例如:
initializeProblemState()
-
为布尔函数保留前缀is。
例如:
isCrazy, isNuts, isOffHisRocker
-
当为彼此密切相关的概念或操作创建有意义的名称时,最好使用强相关的名称。当其中一个操作与另一个操作相反或互补时尤其如此。
例如:
get/set, add/remove, create/destroy, start/stop, insert/delete, increment/decrement, old/new, begin/end, first/last, up/down, min/max, next/previous, open/close, show/hide,suspend/resume
等 -
需要注意函数名同名问题,可使用which -all 或exist 来检查是否存在函数名遮蔽。
文件
M文件
- 将代码模块化,使用片段来组成整体。
- 编写易于测试的函数。
- 明确交互。使用输入和输出而不是全局变量。用结构代替长长的参数列表。
- 分区。所有子函数和大多数函数都应很好地完成一件事。
- 尽可能使用现有函数,而不是自定义编码函数。
- 将多个 m 文件中使用的代码块移至函数中。
- 当一个函数只被一个其他函数调用时,使用子函数。
- 为每个函数编写测试脚本。
声明
变量和常量
-
除非内存限制要求,否则不应重复使用变量。
-
同一类型的相关变量可以在共同语句中声明。不相关的变量不应在同一语句中声明。
persistent x, y, z
-
在文件开头附近的注释中记录重要变量。用行末注释记录常量。
THRESHOLD = 10; % Max noise level
全局变量
尽量减少全局变量和常量的使用。考虑使用函数替代全局常量。
循环
- 循环中使用的变量应在循环之前立即初始化。
result = zeros(nDays,1);
for iDay = 1:nDays
result(iDay) = foo(iDay);
end
-
尽量减少在循环中使用break 和 continue 。
-
嵌套循环中的结束行可以用注释来阐明代码块。
for index=1:2
if index==1
dosomething(index); ...
end % End if
end % End for
条件式
- 避免复杂的条件表达式,改用临时逻辑变量。
isValid = (v >= lowerLimit) & (v <= upperLimit);
isNew = ismember(v, valueArray);
-
避免使用条件表达式
if 0
。 -
if-else
序列应包含else
条件。通常情况应放在
if
部分,例外情况应放在if-else
语句的else
部分。 -
switch
语句应包含otherwise
条件。 -
如果变量是字符串,请使用
switch
序列。 -
尽可能使用
switch
语句代替多重if-elseif-else
语句。
布局、注释和文档
布局
-
内容应保留在前 80 列内。
-
应在逗号、空格和运算符之后分割行。
-
续行与上一行表达式的开头对齐
例如:
totalSum = a + b + c ...
d + e;
-
基本缩进应为 4 个空格。
-
一般来说,一行代码应该只包含一个可执行语句。
-
短的单语句 if、for 或 while 语句可以写在一行上。
if (condition), statement; end
空格
- 在 = 、& 和 | 前后插入空格。
- 逗号后跟一个空格。
- 关键字后面应该跟一个空格。
- 代码块应由三个空行或分节符分隔。
- 在任何可以增强可读性的地方使用对齐代码。
注释
-
注释应该与代码一致,但不能重复代码。
-
注释应与引用的语句具有相同的缩进。
-
传统的函数头注释应支持 help 和 lookfor,在matlab中使用help + 函数名会打印该函数的第一个连续的注释块。
-
使用lookfor+函数命令的方式,查看某一函数的介绍。在命令行窗口输入lookfor plot,此时将出现所有与plot函数有关的M文件。
-
函数头注释应该讨论输入/输出参数的任何特殊要求,并描述函数的任何副作用。在函数头注释中使用正确的大小写编写函数名称。
function runEverything % runEverything runs all mfiles in its folder
-
将任何版权行和更改历史记录放在函数标题之后,中间空一行。
-
所有注释均应使用英文。
文档
-
使用文本标记编写页眉注释,提供用户文档。包含与帮助页面相对应的部分:语法、描述、示例和另见。考虑先编写文档,以便更好地定义输入、输出和功能。
-
考虑使用 SVN 或 GIT 等源代码控制工具。如果不使用源控制工具,可在函数标题后或脚本顶部附近添加更改历史注释,以记录更改。
参考文献
- Johnson, Richard. “MATLAB Programming Style Guidelines.” Version 1.5. Datatool. 2002-Oct. Accessed 2014-Jan-15. http://goo.gl/uyGVM5 Johnson, Richard.
- “The Elements of MATLAB Style. Cambridge University Press, 2010-Dec-31. http://goo.gl/cUA7Gr Johnson, Richard.
- “Updates to The Elements of MATLAB Style.” 2012-May-07. Accessed 2014-Jan-29. http://goo.gl/GwHqNp