从其它平台迁移而来


前言

接触编程已十年有余,使用Delphi谋生也已五年有余,不敢说阅码无数,实实在在看过的代码也是有几箩筐的,但见过的写得好的、写得漂亮的、写得优美的代码,少之又少。

由于pascal语言简单易学的优点,以及DelphiIDE快速开发的方便,致使随便来个阿猫阿狗搞几下就能搞出来个马马虎虎的东西,于是众多程序猿便借势野蛮生长,个个都长得很有个性,产出的代码也自然是个性十足。事实上,其它语言的这种现象也不少。

我无意发起圣战,毕竟每只都有自己的追求,而我,不过是长成了一只有点洁癖的。以下是我的洁癖,也是我的追求,算是总结,也算是对自己的警醒。

正文

排版

良好的排版能使代码看起来清晰愉悦,统一的排版能使团队合作愉快,也更能显出版本控制优势。

简单来说,cnPack提供的排版功能就不错。我喜欢在默认的基础上做如下调整:

  • 关键字小写。因为小写比大写更易阅读。

  • begin 位于下一行。因为能突出代码块的起始位置。

  • 当超过90列时自动换行于80列。因为我的屏幕有点小,而且我个人也比较懒,再加上一点点历史原因。

  • 字符串拼接等不希望cnPack自动排版的地方,可在末尾加//单行注释进行妨碍。写过长SQL语句的都知道我在说什么。

注释

注释很重要,但注释也可以很美妙。比如:interface区主要使用xml风格的注释,implementation区主要使用默认风格的注释,具体如下:

  • 函数、过程、类方法、类属性、结构体方法的声明使用xml风格的注释,注释在上,声明在下。当你把鼠标放上去的时候你就知道我是对的。

  • 枚举成员、类字段、结构体字段使用//单行注释,注释在右,且同一代码块尽量缩进对齐。无他,我有洁癖。

xml风格的注释,我喜欢的格式如下,至于怎么设置,我想这不是问题。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{func}
/// <summary>|</summary>
/// <param name="n1"></param>
/// <param name="n2"></param>
/// <returns></returns>

{param}
/// <param name="|"></param>

{remarks}
/// <remarks>|</remarks>

{returns}
/// <returns>|</returns>

{seealso}
/// <seealso>|</seealso>

{summary}
/// <summary>|</summary>

{value}
/// <value>|</value>

命名

什么拼音首字母,什么1 2 3 4 5,我是极其痛恨的!

  • 禁止使用汉字拼音拼音首字母前缀+数字命名。

  • 要使用有意义的单词或短语命名。

  • 可以使用缩写,但不能产生歧义,若没有更合适的命名但又容易产生歧义则必须加注释详细说明。

  • 主要使用Pascal命名法,特殊情况可加前缀,且前缀一般要小写。

  • 全局常量尽量全部大写,且单词间用下划线_分隔。

  • 普通命名尽量少用下划线_

  • 组件须加前缀,前缀统一使用cnPack生成,同类组件要使用相同的前缀。

  • 工程组,组名加前缀g,工程名不加前缀。

  • 窗体单元,单元名加前缀FM_,窗体名加前缀frm

  • 数据模块单元,单元名加前缀DM_,数据模块名加前缀dm

  • 框架单元,单元名加前缀FA_,框架名加前缀fra

  • 自定义组件单元,单元名加前缀c,我个人喜欢加前缀J

  • 普通单元,单元名加前缀u

  • 在类中,属性字段加前缀F,非属性字段加前缀m

  • 句柄类变量可选择加前缀h

  • 函数/过程的形参一般加前缀A

  • 在函数/过程内部临时使用的变量可加前缀tmp

  • 数据库中,表名加前缀T_,视图名加前缀V_,存储过程名加前缀SP_

函数/过程

  • 形参最好保持在4个以内,最多不要超过10个,实在不行就传结构体

我曾用过一家公司的API,一个函数传了54个参数,当时我就炸毛了,你这是要打扑克吗?

  • 一个函数/过程最好只做一件事,也就是所谓的KISS原则

我曾接手过一个项目,核心业务就在一个过程里,知道这个过程有多少行吗?1W+!每次改到这里心中总有千万头羊驼奔过……

日期时间

  • Delphi日期时间转换函数默认是会受操作系统日期时间格式影响的,程序初始化时最好先进行格式设置。

  • Delphi日期时间的零点与其它的是不同的,尤其是数据库里,最好格式化成字符串再入库。

面向对象

讲真,我也是从小白过来的,知道要跃过这道坎不是那么容易,但是,必须要知道:

  • 面向对象是一种思想,并不是你弄出个类来,就是在面向对象了!

  • 不管你是面向对象还是别的什么东西,KISS原则总是对的!

  • 多用组合,少用继承。Golang倒是把这点发挥到了极致。

  • 别不放窗体就不会写代码了!

其它

  • 字符编码尽可能使用UTF-8无BOM

  • 要做到编译0 Error 0 Warning

  • 禁止使用try ... except Application.Run; end;try ... except ; end;,无论如何都不能用!

  • 不要滥用Timer,除非你想把自己玩死!

  • 建议Debug模式下总是开启内存泄漏报告,否则当你遇到AV报错的时候你就自己去爽吧!

  • Debug模式下善用OutputDebugString,相信你会开心得笑出猪哼的。

  • 创建/释放打开/关闭要对称,而且要在正确的位置。

  • 坚持谁创建,就由谁负责释放的原则,不要干自动释放的蠢事,除非你清楚自己在做什么,但通常情况下没人会知道别人会怎么调用它。

  • 使用对象前最好先判断下对象是否存在,除非能确保对象肯定存在。

  • 动态创建的对象,释放时要使用FreeAndNil();

  • 动态创建组件对象时,Create传入参数要慎重,某些情况下传入nil不会报错但就是运行不正常,比如某些数据库组件,此时建议传入Application

  • 写线程时,不要使用FreeOnTerminate := True;,若坚持了以上原则的话,几乎没有可能会用到它。

  • 不要调用Terminate;,若坚持了以上原则的话,没有可能会用到它。

  • 不要使用相对路径,即使外部配置为相对路径,读取配置后也要转换为绝对路径,否则当你的程序被三方程序调用运行的时候,你就会爽歪歪的。