Pulpcode

捕获,搅碎,拼接,吞咽

0%

2014年终技术总结之代码洁癖

本文算是两部分,一部分是对《编写可读代码的艺术》一书的总结,一部分算是自己这一年来对代码书写的心得体会。

虽然项目的整体构架和设计模式很重要,但程序员日常工作的大部分时间,还是会花在一些“基本”的事上,所以写的一手“好代码”,也十分重要。

这些代码洁癖包括:

命名,注释以及审美-可以用于代码库每一行的小提示。
简化循环和逻辑。
在程序中定义循环,逻辑和变量,从而使得代码更容易理解。
重新组织你的代码。
在更高层次上组织大的代码块以及在功能层次上解决问题的方法。

而代码洁癖,本身就是为了使代码更容易理解,你会发现,如果一个人的代码写的很干净,那么他的编程思路也绝对是清晰的。相反代码写的乱的人,他们的编程思路,甚至做事态度都是含糊不清的。

关键思想: 代码的写法应当使别人理解它所需的时间最小化。

表面层次的改进

命名

关键是要把信息装入名字中,这其中包括:

选择专业的词汇
避免泛泛的名字
用具体的名字代替抽象的名字
使用前缀或后缀来给名字附带更多信息
决定名字的长度
利用名字的格式来表达含义

使用比较专业的词

不要使用Get,Size,Tmp这样的命名,因为它们非常含糊,比如有一个函数要获取一个页面,使用getPage就不够好,而使用FetchPage,DownloadPage就好很多。

而相比于Size,Height(),NumberNodes(),MemoryBytes()这样的专业词汇就要好很多。

还有类似Kill,Pause,Resume这样的动词,也要比Stop要好很多。

书中对专业词汇进行了总结:

单词    更多选择
send   deliver, dispatch, announce, distribute, route
find   search, extract, locate, recover
start  launch, create, begin, open
make   create, set up, build, generate, compose, add, new

不要使用很随便很泛泛的名字

永远不要使用tmp,it,retval,这样的命名,更不用说,foo,aa,bb了。

在交换两个值的代码中常常会用到tmp这个变量名,因为tmp这个名字只应用于短期存在且临时性为其主要存在因素的变量。

关于临时变量

关于临时变量,之前写过一篇博客:临时变量应该叫啥?

值得一提的是,最近使用的语言基本就是c#,python,所以再也没有使用过all_imagesall-images这样的下划线命名方式了。

还有我认为尽量使用全拼,不要使用简写和缩写来命名变量。

开闭区间

《编写可读代码的艺术》书中提到,如果要操作[1,2,3,4,5]这样的闭区间,使用firstlast来命名。
而如果是操作[1,2,3,4,5)这样的半开半闭区间,则使用beginend这样的关键字。

注释

人们常常会说,好的代码是不需要注释的。

如果你的逻辑,你的类,你的函数命名,都是“可读的”,那么真是没有必要再去写一些“浪费精力”的注释了。

也就是说: 好代码 > 坏代码 + 好注释

而且注释也不仅仅是解释代码而已,还可以写一些记录你思想的注释,比如这样:

// TODO 此处代码会有取消后的bug,应该在保存的那一刻,才生成新的对象。
// TODO 是直接绑定到一个对象上,还是从表单获取数据?在后台再去创建这些对象。

有几种标记在程序员中很流行:

TODO:  我还没有处理的事情
FIXME: 已知的无法运行的代码
HACK:  对一个问题不得不采用比较粗糙的解决方案
XXX:   危险,这里有重要的问题

排版审美

好的代码绝对给人很清爽的感觉,就算是从IDE中粘贴出到普通的文本编辑器,没有高亮,代码依旧会显得很整齐。

这里有三条原则:

  1. 使用一致的布局
  2. 让相似的代码看上去相似
  3. 把相关的代码行分组形成代码块

再比如每行代码不要超过80个字符,也是必须要遵守的排版风格。(在我的编辑器中如果代码超过80行,会对此行代码进行高亮)

对于一系列的赋值语句,将=进行对齐,也是个排版的好习惯,而且单词与操作符之间要保留一个空格的距离。

坏排版:

apple =5
orange =9
banana =19
pear =2

好排版:

apple  = 5
orange = 9
banana = 19
pear   = 2

逻辑与循环

逻辑判断

关于逻辑代码应该如何书写,我之前写过一篇博客,关于if的几种写法

for和while

现在基本能使用函数式编程和Linq的地方,我是不会再去写for语句了。其实在大学的时候,我就开始区分forwhile,那些口口声声说什么forwhile可以相互替代的根本什么都不懂。

其实for语句就是常用于遍历一个容器,python的for和c#的foreach,应该算是操作迭代器的语法糖。而while才算是重复执行某些动作。在c语言中,我们常常使用for语句来操作数组。

for循环使用心得

代码风格

特别要注意一点的是,一致的风格比正确的风格更重要。

如果你积累了一定的代码量,就需要不断的总结自己的编码风格。

这其中不仅仅是代码风格,还包括自己掌握的编程范式,包括可读性和健壮性。比如这里应该用try..catch,这里应该将创建的对象释放。

熟练之后,你都不用去想,就能马上写下这个问题应该如何去解决。

比如现在,我会在一段代码的开头,就检验要操作的对象是否为空。而且为了简化代码,我还会使用短路求值,而不是一个一个的判断。

1
2
3
4
5
6
if(employee != null && employee.Department != null)
{
xxxxxx;
xxxxxx;
xxxxxx;
}

或者一开始就将它们return

1
2
3
4
5
6
7
if(employee == null || employee.Department == null)
{
return;
}
xxxxxx;
xxxxxx;
xxxxxx;

永不停息

慢慢的去做

一个人的钱包里是怎样的,那么他的房间就是怎样的。

而且如果不是每天花一点时间去整理,而是长时间后的突击式整理,变乱又是早晚的事。

所以一开始就急着去将学到的东西全部用出是不可能的,这需要你将这些技能,方法和技巧慢慢的融入到自己的coding中。

边际效益

其实我还是想说,如果你的程序构架不够好,设计模式做的不够好,那么代码本身写的再好,也不会有更大的突破,你只在在勤奋的走弯路,本身还是要抓清主次。与其过于抠编程细节,不如学学构架设计。