我读<代码整洁之道>--读书笔记整理
第一章 整洁代码
"我可以列出我留意到的整洁代码的所有特点,但其中有一条是根本性的,整洁的代码总是看起来像是某位特别在意他的人写的.几乎没有改进的余地,代码作者设么都想到了,如果你企图改进它,总会回到原点,赞叹某人留给你的代码" ---Michael Feathers
"整洁的代码只做好一件事" ---Bjarne Stroustrup
第二章 有意义的命名
1 变量名要名副其实
即顾名思义,变量.函数或者类的名称应该能告诉你,它为什么会存在,他做什么事,应该怎么用,名称应该尽量不需要注释补充亦能表示其含义.
类名和对象应该是名词或者名词短语,方法名应该是动词或者动词短语.
2 避免误导
//不好的命名
public boolean stateMachine(int smStatus) {
//...
}
public boolean doAction() {
//...
}
//好的命名
public boolean moveStateMachineToStatus(int smStatus) {
//...
}
public boolean doNextStepInProviderTechnique() {
//...
}
3 做有意义的区分
4 使用能读得出来的名称
名字中不要有冗余,定义一个List类型变量,xxxList不如xxx的复数形式简洁,List字眼就属于冗余字段.
5 命名布尔变量
使用常见的布尔含义的命名: 如done;error;found;success;
可以添加前缀is,has来转换布尔,但是isSuccess不如success可读性好
避免使用负向变量命名:如notFound,设想if(!notFound)是不是觉得别扭.负向条件比正向条件更加难于理解,应该尽量避免.
第三章 函数
1 短小
这里是指一个函数的代码量,不是指函数名称要短小.函数应该是在做一件从语义上无法再次拆解的事情.
2 一个函数只做一件事
函数应该做一件事,做好这一件事,而且只做这一件事.
写多长的函数比较合适?
约定:不超过一屏幕,长度并不是问题,关键在于函数名称和函数体之前的语义距离,函数应该很短,也可以较长.只要保证函数只做这一件事.
拆分函数的技巧?
寻找注释,如果函数中某部分代码前面有一行注释,一般可以把这段代码替换成一个函数.此外,当感觉需要注释来说明一些什么的时候,就要考虑把要说明的这些东西封装成一个独立的函数.
3 每个函数一个抽象层级
这一点需要多一些说明,要确保函数只做一件事,函数的语句要在同一个抽象层级上.
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String fileId = request.getParameter("FILEID");
if (fileId == null) {
throw new ServletException("Invalid FileId"); }
String partNum = request.getParameter("PART"); int part = 1;
if (partNum != null) {
part = Integer.valueOf(partNum).intValue(); }
boolean isLast = "Y".equals(request.getParameter("LAST"));
boolean getName="Y".equals(request.getParameter("GETNAME"));
String fileName =
MitoDownloadCache.INSTANCE.getFileName(fileId, part);
if (fileName== null) {
throw new ServletException("Invalid FileName"); }
MitoConfig mitoCfg = new MitoConfig();
File file = new File(mitoCfg.getPrintClientDataPath()+"/"+fileName);
if (!file.exists()) {
throw new ServletException("File " + file.getAbsolutePath() + " not found");
}
if (getName) {
doDownloadFilename(request, response, file.getName());
} else {
if (isLast) {
MitoDownloadCache.INSTANCE.removeFileList(fileId); }
doDownload(request, response, file); file.delete();
}
上面这个方法是我copy来的,不用研究这个函数的内容,只看一下结构,这个函数中既有比较高抽象层次的函数doDownloadFilename,doDownload,还有getFileName这种位于中间抽象层次的函数,更有很多像equals等较低抽象层次的概念.混杂了不同抽象层次,读起来就比较吃力,现在来改造一下:
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
File file = fileToDownLoad(request);
if (downloadByName(request)) {
doDownloadFilename(request, response, file.getName());
} else {
removeFromCacheIfLast(request);
doDownload(request, response, fileToDownLoad(request));
file.delete();
} }
将功能拆分成红能更小更细的函数,封装成私有方法,起一个见名知义的函数名,使整个方法能够位于同一个抽象层次,然后在每个函数内部都跟着下一级抽象层次的函数,这样能给阅读带来极大的便利.(上面函数中私有方法这里不再展示)
4 使用描述性名称
函数越小,功能越集中,就越容易取一个合适的名字.另外不要害怕长名称,描述性很好的长名称比含糊不清的短名称要好.不要害怕花时间给函数起名字,起一个合适的名字本身就是编程的一部分.
5 函数输入参数
最理想的函数参数是0个(无参函数),其次是一个,二个,应该尽量避免三个以上的参数.
尽量避免标示参数,即用一个boolean类型作为入参,比如下面这个函数,eat(true);这样读起来就有些摸不着头脑,可能读者需要去查看eat方法eat(boolean isHuntry)才能比较理解这个函数.
如果函数必须要三个或三个以上的参数,就说明其中一些参数需要封装成类,如果很难封装成类,就说明这个函数的设计有问题.
6 函数输出参数
面向对象语言的方法应该尽量避免使用输出参数,当然那些util类型的工具类除外.this也有输出函数的意味,如果函数必须要修改某种状态,就修改所属对象的状态吧.
7 抽离try/catch代码块
try/catch代码块比较丑陋,搞乱了代码结构,最好把try/catch代码块的主体部分抽离出来,另外形成函数.
函数应该只做一件事,错误处理就是一件事,因此,如果处理错误(带try/catch)的函数应该只处理错误,该函数只有try/catch不应该再包含其他内容.
8 使用更少的代码
//实例1:不好的代码格式
public int size() {
if (root == null) {
return 0;
}else {
return root.numSiblings();
}
}
//实例1:好的代码风格
public int size() {
return root != null ?root.numSiblings() : 0;
}
//实例2 不好的代码
List<Integer> list = Arrays.asList(1, 2, 3));
list = Collections.unmodifieableList(list);
return list;
//实例2 好的代码
import static java.util.Arrays.*;
import static java.util.Collections.*;
... return unmodifiableList(asList(1, 2, 3))
实例2中给出的例子有些函数式编程的味道,这里只是提供一种思路,但大多数情况我们一般写出来的都是上面的格式.
第四章 注释
不写无意义的注释,什么是无意义的注释,如下:
//当我写这段代码的时候,只有老天和我自己知道我在做什么
//现在,只剩老天知道了
...
//我不对以下代码负责
//使他们逼我写的,是违背我意愿的
注释尽量做到简洁
最好不写注释
代码结合命名应该良好的描述功能,写注释说明表达意图的失败以及对代码功能的不自信,糟糕的代码是注释存在的动机之一.
什么是必须要写的注释
警告他人 版权协议 公共API
第五章 格式
1 格式的目的
代码格式很重要,代码格式关乎沟通,而沟通是开发者的头等大事.
2 垂直格式
阅读代码都是从上往下,从左往右读的.在一个类中,在封包声明,导入声明,和每个函数之前都应该使用一个空白行来隔开.这可以给阅读带来愉悦的感受.
空白行隔开了概念,每个空白行都是一条线索,标示出一个新的独立的概念,阅读代码的时候,我们的目光总是容易停留在空白行的前一行或后一行.
变量声明 :变量声明应该尽量靠近其使用位置.类变量应该声明在类的顶部,
相关函数:某函数A调用了函数B,应该尽量把他们放到一起,让A位于B的上方.
概念相关:概念相关的代码应该放到一起,相关性越强,他们之间的距离就应该越短.
避免过度缩进(代码梯子):
//不好的代码风格
public void startCharging() {
if (customer.hasFunds()) {
if (!station.isCharging()) {
if (!station.currentlyBooked()) {
reallyStartCharging();
return;
}
}
}
throw new UnableToStartException();
}
//好的代码风格
public void startCharging() {
if (!customer.hasFunds()) throw new UnableToStartException
if (station.isCharging()) throw new UnableToStartException
if (station.currentlyBooked()) throw newUnableToStartException
reallyStartCharging();
}
3 横向格式
一行代码应该多宽?
应当遵循无需拖动滚动条到右边的原则,每行代码控制在100个字符以内是良好的风格.
第六章 对象和数据结构
数据抽象
当我们构建一个实体类时,会为变量设置为private,再为变量提供set/get方法,想一想为什么要这么做?实际上,即使变量都是私有,我们通过变量的set/get方法操作变量时,实现仍然被曝光了,那为何不直接将变量设置为public,然后直接操作变量呢?
隐藏实现并非只是在变量之间放上一个函数层那么简单,更大的意义在于抽象,类并不是简单的用set/get方法将变量推向外间,而是暴露抽象接口,使得用户无需了解数据的实现就能够操作数据本体.
德墨忒尔定律(The Law of Demeter)
得墨特定律认为,模块不应该了解它所操作的对象的内部情况.对象隐藏数据,曝光操作.
类C的方法f只应该调用以下对象的方法
- C
- 由f创建的对象
- 作为参数传递给f的对象
- 由C的实体变量持有的对象
方法不应该调用任何由任何函数返回的对象的方法,一个很经典的比喻就是:不要和陌生人说话,只和朋友说话,还有一个比喻就是,人可以命令狗走路,但人不能直接命令狗的腿去走路,而应该由狗来控制自己的腿去走路.
如果代码中充斥着"."构成的链式编程风格的代码.意味着该定律被被违反了.当然如果调用者是数据结构,没有行为只有数据,就可以忽略.
...未完
我读<代码整洁之道>--读书笔记整理的更多相关文章
- 代码整洁之道读书笔记(Ch4-Ch7)
这几章从注释.程序格式.对象与数据结构的规范以及错误处理四个方面介绍了如何使代码变得简洁易懂.不同于上次摘抄的方法,这一次我会结合第一次个人作业的代码进行分析. 第四章 注释 这一章告诉我们,好的注 ...
- 读<<代码整洁之道>>的感想
花去了近一周的时间浏览一下这本书.总体感觉这本书写得不错. 我发现自己以前写的代码时多么的糟糕.有很多改进之处... 同时我也发现写出优秀的代码不易.优秀的代码不仅仅易读,并且易修改,易维护,程序易维 ...
- <读书笔记> 代码整洁之道
概述 1.本文档的内容主要来源于书籍<代码整洁之道>作者Robert C.Martin,属于读书笔记. 2.软件质量,不仅依赖于架构和项目管理,而且与代码质量紧密相关,本书提出一 ...
- 《代码整洁之道》ch5~ch9读书笔记 PB16110698(~3.15) 第二周
<代码整洁之道>ch5~ch9读书笔记 本周我阅读了本书的第5~9章节,进一步了解整洁代码需要注意的几个方面:格式.对象与数据结构.错误处理.边界测试.单元测试和类的规范.以下我将分别记录 ...
- 《代码整洁之道》ch1~ch4读书笔记 PB16110698 (~3.8 第一周)
<代码整洁之道>ch1~ch4读书笔记 <clean code>正如其书名所言,是一本关于整洁代码规范的“教科书”.作者在书中通过实例阐述了整洁代码带来的种种利处以及混乱代码 ...
- <代码整洁之道>、<java与模式>、<head first设计模式>读书笔记集合
一.前言 几个月前的看书笔记 ...
- 如何写出如散文般的代码――《代码整洁之道》读书笔记(Ch1-Ch3)
不知道有多少人像我一样,程序出现问题时添加函数添加变量解决,变量名用a,b,c等"简单"的字母来表示.不知道有多少人像我一样,看完自己的代码,心里暗骂"什么玩意儿!&qu ...
- 《代码整洁之道》(Clean Code)- 读书笔记
一.关于Bob大叔的Clean Code <代码整洁之道>主要讲述了一系列行之有效的整洁代码操作实践.软件质量,不但依赖于架构及项目管理,而且与代码质量紧密相关.这一点,无论是敏捷开发流派 ...
- 读《Clean Code 代码整洁之道》之感悟
盲目自信,自认为已经敲了几年代码,还看什么整洁之道啊.我那可爱的书架读懂了我的心思,很明事理的保护起来这本小可爱,未曾让它与我牵手 最近项目中的 bug 有点多,改动代码十分吃力,每看一行代码都带一句 ...
随机推荐
- SpringMvc支持跨域访问,Spring跨域访问,SpringMvc @CrossOrigin 跨域
SpringMvc支持跨域访问,Spring跨域访问,SpringMvc @CrossOrigin 跨域 >>>>>>>>>>>> ...
- .NET平台的ORM分析工具
众所周知,“ORM”和“性能问题”常常一起出现.ORM通过对开发人员隐藏SQL细节可以大大的提高生产力.然而,它们很容易产生一些未被发现的荒谬查询.通常情况下,数据库管理员可以通过交叉引用有问题的存储 ...
- JavaScript中判断鼠标按键(event.button)
<div id="test"></div> <script> document.oncontextmenu=function(){ return ...
- dotpeek的导出
在开始写之前先说明下,搜了很久的度娘,就是没找到dotpeek的导出功能,····,看来用的人不多, ------------------------------------------------- ...
- jenkins - MultiJob使用
我们如果使用jenkins需要由串行,并行,传递参数和等待执行的功能的话,那我们会用到jenkins里面的两个东西:MultiJob和pipeline 这里我介绍下MultiJob的使用 实例任务的拓 ...
- Java-认识变量、注释并能及时发现错误
package com;//变量的演示public class VarDemo { public static void main(String[] args) { /* * 1)题目不用抄 2)注释 ...
- (转)mysql水平分表和垂直分表和数据库分区
坚信数据库的物理设计在对高级数据库的性能影响上远比其他因素重要.给大家说一下经过专家对Oracle的研究,他们解释了为什么拙劣的物理设计是数据库停机(无论是有计划的还是没计划的)背后的主要原因.但在这 ...
- 如何把我的Java程序变成exe文件?
JAVA是一种“跨平台”的语言,拥有“一次编写,处处运行”的特点,让它成为当今IT行业,必不可少的一门编程语言.每一个软件开发完成之后,应该大家都需要打包程序并发送给客户,常见的方式:java程序打成 ...
- Docker Registry
前言 上一篇文章讲了Docker Machine实现多主机Docker节点的管理.本文讲解如何实现Docker Registry,其实这个在第一篇Docker入门一文中已经简单介绍,本文仅是对一些细节 ...
- 微信小程序movable-view移动图片和双指缩放
先从movable-view开始说起吧. movable-view是小程序自定义的组件.其描述为:"可移动的视图容器,在页面中可以拖拽滑动". 官方文档地址:https://mp. ...