《代码整洁之道》——读书笔记(持续更新)
细节之中自由天地,整洁成就卓越代码
前言
软件质量,依赖于架构,项目管理和代码质量。代码质量与整洁度成正比。软件80%以上的工作都是在维护,其实就是修修补补。
全员生产维护(Total Productive Maintenance,TPM)的质量保证手段,主要支柱5S原则。
1.整理(seiri),或组织,搞清楚事物所在。代码里的命名。
2.整顿(seiton),或整齐,物皆有其位,而后物尽归其位。代码也有其位,不在其位就要重构。
3.清除(Seiso),或清洁,清理工作。无效代码,遗弃注释也要清楚掉
4.清洁(Seiketsu),或标准化,保持清洁共识。代码也要保持一贯的风格和实践手段。
5.身美(Shitsuke),或纪律/自律。实践中执行,并乐于改进。
不断清理缓慢陈腐代码,减少重构自己后期。全心倾注于细节,屡见于追求卓越的行为之中。视代码为设计——作为过程而非终点的设计。
第一章 整洁代码
1.1要有代码
代码永远不会消失,因为代码呈现了需求的细节。代码是程序员将需求明确到机器可以执行的程度。较高层次上用特点语言撰写的规约也将是代码,也要符合严谨、精确、规范、详细的特点。悖论在于,客户的很多需求就是模糊的感觉,最终还是需要精确性的需求规约描述——这就是代码。
1.2糟糕的代码
糟糕的代码真的能毁坏产品,最终毁坏一家公司,这是有显示按理的。糟糕的代码就像沼泽。
1.3混乱的代价
糟糕的代码,随着代码的修改,混乱会被放大,会让团队的生产力持续下降,趋向于零。管理层面对这种情况,首先是增加更多人手到项目中。但新人很难搞清楚原代码的设计意图,又背负生产力的压力,只会制造更多的混乱,致使生产力继续降低。最后管理层只能同意新团队重新设计。这是会出现聪明和优秀的人开发新系统,其余人维护旧系统。新系统的挑战是要实现旧系统的所有功能,同时要跟上旧系统的持续改动,在新系统功能足以抗衡旧系统之前,管理层不会更换旧系统。这个情况如果持续时间过长,新团队的老成员可能都不知去向,而现有成员则要求再重新设计一套新系统。如此恶性循环。
1.3.2态度
原本小功能,却花费很长时间,修改很多代码的代价。我们不能抱怨。1.需求背离了初期设计。2.进度太紧张。3.愚蠢的经理。4.渴求的客户。实际是我们太不专业了。经理和营销人员指望从我们这里得到专业的信息,才能做出承诺和保证。用户指望我们把需求功能都实现。项目经理指望我们遵守进度。大多经理需要实情,他们关心进度,程序员专业和质量。
1.3.3谜题
制造混乱只会错过期限,唯一做得快的方法是适中保持代码整洁
1.3.4整洁代码的艺术
编写整洁代码的程序员就像是艺术家,他能用一系列变换把一块白板变作由优雅代码构成的系统。
1.3.5什么是整洁代码
优雅,高效。逻辑直接了当,缺陷难以隐藏。减少依赖,便于维护。分层战略完善的错误处理代码。性能最优。只做一件事。优雅是“外表或举止上令人愉悦的优美和雅观;令人愉悦的精致和简单。”——Bjarne Stroustrup,C++语言发明者
简单直接,如同优美的散文。有单元测试和验收测试。干净利落的抽闲和直截了当的控制语句。——Grady Booch《面向对象分析与设计》
由使用框架的程序员阅读和增补。有意义的命名。只做一件事,少依赖。明确定义,清晰的少的API。代码自身表达清晰。——Dave Thomas Eclipse战略教父,OTI公司创始人。
能通过所有测试。没有重复代码。体现系统重全部设计理念。较少的类、方法、函数等。消除重复,提高表达力,提早构建简单抽象。——Ron Jeffries 《极限编程实施》
代码让你深合己意,专为解决那个问题而存在,就是漂亮代码。——Ward Cunninghan,Wiki发明者,extreme programming 极限编程的创始人之一,SmallTalk语言和面向对象的思想领袖。
1.5我们是作者
读代码所消耗的时间是写代码时间的10倍。要让读代码变得轻松,即便这会让写代码过程更难。
1.6童子军军规
让营地比你来时更干净
第二章 有意义的命名
2.2名副其实
取个好名字花费的时间,远远比烂名字浪费的时间多。一旦发现好名字,立即更换。这样读代码的人会很开心。名字不应该还需要注释补充。
//典型需要注释的变量
int d; //消逝的时间,以日计
//改进后不需要注释的变量
int elapsedTimeInDays;
int daysSinceCreation;
int daysSinceModification;
int fileAgeInDays;
//选择体现本意的名称能让人更容易理解和修改代码
//原始代码
public List<int[]> GetThem() {
List<int[]> list1 = new ArrayList<int[]>();
for(int [] x : theList)
if(x[0] == 4)
List1.add(x);
return list1;
}
//命名更有意义的名称,代码的易读性得到一定的提升
public List<int[]> GetFlaggedCells() {
List<int[]> flaggedCells= new ArrayList<int[]>();
for(int [] cell : gameBoard)
if(cell[STATUS_VALUE] == FLAGGED)
flaggedCells.add(cell);
return flaggedCells;
}
//int 数组更换为类,得到进一步提升
public List<Cell> GetFlaggedCells() {
List<Cell> flaggedCells= new ArrayList<int[]>();
for(Cell cell : gameBoard)
if(cell.isFlagged())
flaggedCells.add(cell);
return flaggedCells;
}
2.3避免误导
1.程序员必须避免留下掩藏代码本意的错误线索。应当避免使用与本意相悖的词。如hp,aix,sco都不该用做变量名。使用accountList就不如使用accountGroup或bunchOfAccounts表示一组账户贴切。
2.使用不同之处较小的名称如:XYZControllerForEfficientHandlingOfStrings和XYZControllerForEfficientStorageOfStrings
3.不要使用字符“l”和“o”做为变量名
2.4做有意义的区分
如果仅仅为了编译器或解释器的需要来变更代码,就会制造麻烦。如:
1.仅更改统一名称的字母顺序,故意错误拼写
2.给变量添加数字,用于区分
public static void copyChars(char a1[], char a2[]) {
for( int i=0; i < a1.length; i++){
a2[i] = a1[i];
}
}
3.废话也是没意义的区分。如类ProductInfo和类ProductData。Variable永不不出现在变量中,Table一次永远不出现在表名中。比如NameString中的“String”,CustomerObject中的“Object”都是废话。
2.5使用读得出来的名称
1.反面示例如“pee ess zee kyew, genymdhms”
//难以理解
class DtaRcrd102{
private Date genymdhms;
private Date modyymdhms;
private final String pszqint = "102";
};
//容易拼读
class Customer{
private Date geneartionTimeStamp;
private Date modificationTimeStamp;
private final String recordID = "102";
};
2.6使用可搜索的名字
单字母名称和数字常量,很难再一大篇文字中找出来。作用域越小,名称可以越小。如单字母“i”,“e”,常量数组“7”,非常不友好。
2.7避免使用编码
2.7.1匈牙利语标记法
更多推荐

所有评论(0)