同事推荐《代码整洁之道》这本书很不错,这几天仔细地阅读了一翻,感受颇深。在这里聊以记录,跟大家分享一下。
第一章 整洁代码
什么是整洁的代码,以下是各种经验丰富程序员的见解。
1. 我喜欢优雅和高效的代码。代码逻辑应该直接了当,叫缺陷难以隐藏;尽量减少依赖关系,使之便于维护;依据某种分层战略完善错误处理代码;性能调至最优,省得引诱别人做没规矩的优化,搞出一堆混乱来。整洁的代码只做好一件事。 --C++语言发明者
2. 整洁的代码简单直接,简洁的代码如同优美的散文。整洁的代码从不隐藏设计者的意图,充满了干净利落的抽象和直接了当的控制语句。--《面向对象分析与设计》作者
3. 简洁的代码总是看起来像是某位特别在意它的人写的。几乎没有改进的余地。代码作者什么都想到了,如果你企图改进它,总是会回到原点。--《修改代码艺术》作者
4. 如果每一个例程都让你感到深合已意,那就是简洁的代码。如果代码让编程语言看起来像是专门为解决那个问题而存在,就可以称之为漂亮的代码。--《极限编程》创始人之一
第二章 有意义的命名
1. 要名副其实,比如:int d; // 消逝的时间,以日计。 改为 int elapsedTimeInDays;
2. 做有意义的区分,比如你有一个Product类,还有一个ProductInfo类。这两个类看不出有什么区别,应该避免。
3. 类名应该是名词或者名词短语,比如Customer,WikiPage。避免使用Processor,Manager这样的类名。
4. 方法名应该是动词或者动词短语,比如save,deletePage。
5. 每个概念对应一个词,并且一以贯之。例如使用fetch,retrieve和get来给多个类的同种方法命名是不对的。我们要调用某一个类的获取方法的时候,不知道该调fetch方法,retrieve方法还是get方法。
第三章 函数
如何写好函数
1. 函数的第一规则是要短小,第二规则是还要更短小。
建议if,else,while语句其中的代码只有一行,函数的缩进层次不应该多于一层或两层。
2. 函数应该做一件事。做好这件事。只做这件事。如果函数只是做了该函数名下同一抽象层次上的步骤,则函数还是只做了一件事。编写函数是把大一些的概念拆分为另一抽象层次上的一系列步骤。
3. 每个函数一个抽象层级,也就是逐个函数细化程序逻辑时,每一个函数做的多个事情的细化程度应该在一个层次上。
4. 函数参数不要超过3个
5. 输出参数不要使用,比如public void appendTitle(StringBuffer report);内部改变了report。
6. 分隔指令与询问分开,比如:public boolean set(String attribute,String value) 该函数设置某个指定属性的值,如果成功返回true,如果不存在该属性返回false。其实应该改成
if(attributeExists(attribute)) {
setAttribute(attribute,value);
.......
}
7. 抽离try/catch块
public void delete(Page page) { try { } catch (Exception e) { logError(e); } } private void deletePageAndAllReferences(Page page) throws Excepiton { deletePage(page); registry.deleteReference(page.name); configKeys.deleteKey(page.name.makeKey()); } private void logError(Exception e) { logger.log(e.getMessage()); }
8. 不要重复自己
第六章 对象和数据结构
1. 得墨忒耳律:模块不应了解它所操作对象的内部情形。这意味着对象不应通过存取器暴露其内部结构(比如get/set方法)比如:
String outPutDir = ctxt.getAbsolutePath(); String outFile = outputDir + "/" + className.replace('.','/') + ".class"; FileOutputStream fout = new FileOutputStream(outFile); BufferedOutputStream bos = new BufferedOutputStream(fout);
我们发现ctxt通过get方法暴露了绝对路径属性,我们进一步发现暴露该属性是为了创建指定名称的临时文件。那么我们为何不让ctxt来创建临时文件呢,将它的绝度路径属性隐藏起来,改成:
BufferedOutputStream bos = cxtx.createFileStream(classFileName);
ctxt需要创建一个createFileStream方法。