第一章 整洁代码
1.编程要做什么
代码呈现了需求的细节,在某些层面上,这些细节无法被忽略或抽象,必须明确。而将需求明确到机器可以执行的细节程度,就是编程要做的事。
2.项目过程中经常遇到这样的问题:
(1)初期进度很快,后来进度特别迟缓,每次修改代码就要修改其他几处代码
(2)团队合作时代码容易混乱,每个人的代码风格和规范都不一样,别人修改后代码更加混乱

(3)自己写的代码回过头去看时要看很久才知道这段代码的意图
3.代码混乱的代价
发布周期长,缺陷难以修复,装载时间久,崩溃几率大

码一旦混乱,团队生产力就容易持续下降,想要增加人手来提高生产力并不可取。第一,新人不熟悉系统的设计;第二,大家都有着提高生产力的压力,更容易制造
混乱的代码。开发团队就想做全新的设计,那就只能分成两队,旧团队负责维护现有系统,新团队不仅要实现旧系统的所有功能,还要跟上对旧系统的持续改进。在
新系统功能不足以抗衡旧系统之前,新系统是不会发布的。可是有两点需要注意:新系统要花多久才能上线,时间久的话会面临开发团队人员变动的问题。
当你发现自己的代码很混乱时,你是会因为各种原因,如进度紧张,修改难度大等而置之不理,还是回过头来修改呢?记得一句话,later equals never。
4.好的代码的要求
(1)有意义的命名,能在字面上表达其含义,代码要在字面上表达其含义,字面编程
(2)力求集中,每个函数、类、模块都专注于做一件事,且这些函数、类、方法、实体等尽可能少
(3)消除重复
(4)有单元测试并能通过测试
如果每个例程都让你感到深合己意,那就是整洁代码,如果代码让编程语言看上去像是专为解决那个问题而存在,就可以称之为漂亮的代码。
 
第二章 有意义的命名
1.项目中有很多需要命名的对象
变量、函数、参数、类、包、源代码及源代码所在目录、jar文件、war文件、ear文件等
通过命名可以告诉别人它为什么存在,做什么事,应该怎么用
每段代码都有其实际应用的场景,一段代码如果难以理解,很多时候并不是因为代码复杂,而是代码的模糊度较高,难以明确代码的意图。

2.如何正确命名

(1)不要以数字系列命名,尤其是在某个方法的参数列表上,且参数最好概念明确
(2)相似的类要加以区分,请问Product类、ProductInfo类、ProductData、ProductObject类的区别
(3)使用读的出来的名称,可以使用谐音,如2,4
(4)使用可搜索的名称,找MAX_SIZE_PER_PAGE容易还是100容易,变量名不可过短,也不要过于普遍,要方便查找
(5)方法名最好是动词或动词短语
(6)为每个抽象概念选一个词作为一贯使用的命名方式,如get,fetch,retrive
(7)添加有意义的语境,如firstName,lastName,state好呢,还是addrFirstName好呢,实际上添加了前缀之后,读者会明白这 些变量属于一个更大的语境,还可以有更好的做法,创建一个名为address的类
 
第三章 函数
1.基本要求

(1)第一规则是短小,第二规则还是短小。函数多少行才算短小呢?

Bob说,20行左右的代码为佳

(2)每个函数都只做一件事,做好这一件事

如果一个函数做了多个事就代表有多个原因可以导致函数被修改

但是,怎么确定,那么多行代码,就只做了这么一件事呢?

public static string RenderPageWithSetupAndTeardowns

(PageData pageData,Boolean isSuite) throw Exception

{

if(isTestPage(pageData))

{

includeSetupAndTeardownPages(pageData,isSuite);

}

return pageData.getHtml();

}

看起来像是做了三件事:判断是否为测试页面;如果是,则包含设置和分析步骤;返回Html。

Bob 提供了”To”(要)原则,也就是以To起头段落来描述这个函数。

要(To) RenderPageWithSetupAndTeardowns,检查页面是否为测试页,如果是测试页,就包含设置和分析步骤,无论是不是测试页,都返回HTML。

这三件事情都处于一个抽象层次上,所以RenderPageWithSetupAndTeardowns做了一件事。

判断函数只做了一件事还有另一个方法:看能否再拆出一个函数

(3)每个函数都依序把你带到下一个函数。

调用的方法在前面,被调用的方法在后面。这样就能保证代码是从上往下看的了

2.函数参数

最理想的参数数量是零,其次是一,再次是二,尽量避免三。参数少也方便测试。

参数多时容易出现以下问题:
(1)参数的排列顺序,每个参数的实际意义,如assertEquals(expected,actual)
(2)传参时千万不要穿boolean,这样函数肯定不止做一件事,true的时候一件事,false的时候又是一件事。
(3)参数多的时候想要测试覆盖所有可能值的组合就会很困难

(4)如果一个函数需要三个或三个以上的参数,那么就要考虑其中的一些参数是否可以封装成类或者这些参数本就属于某个类。很多时候的一些参数,只是某个类的某个概念的一部分。

3.函数编写细则

(1)
函数和参数应当形成一种良好的动词/名词对形式,比如write(name)和writeField(name),assertEqual()和
assertExpectedEqualsActual(expected,actual),可以将参数的名称加入到函数名中

(2)函数要么“做什么事”,要么“回答什么事”,即将指令和询问分隔开来

(3)避免副作用。函数尽量只做一件事,否则会导致时序性耦合和顺序依赖

(4)抽离try/catch代码块,它们容易搞乱代码结构,应该另外形成函数,且该函数中只处理错误

第四章 注释

1.注释的恰当用法是弥补我们在用代码表达意图时遭遇的失败。

需要写注释并不是一件值得庆贺的事,注释写的好并不会提高你的代码质量。

2.注释有以下几个缺点

(1)代码在变动、演化,而我们不总会去维护注释,所以注释就难以精确。
(2)最真实最精确的还是代码,代码还能反映一些细节。
(3)注释是不能美化糟糕的代码的。
3.注释的几个使用场合
(1)公司代码规范要求编写与法律有关的注释,比如版权和著作声明
(2)提供一些基本信息,如解释某个抽象方法的返回值

//Return an instance of the Responder being tested

protected abstract Responder responderInstance();

(3)警示。警告其他程序员会出现某种后果
(4)TODO注释有时,有理由用//TODO形式在源码中放置要做的工作列表,无论TODO的目的如何,都不是在系统中留下糟糕代码的借口,一定要定期查看,删除不再需要的。(5)编写公共API中的JavaDoc
 
第五章 格式
1.良好的代码格式,会使得我们阅读更容易,一套共同的格式会让我们查找理解更快速。每个团队都应该遵循一套固定的代码格式规范,整个软件系统的统风格统一,而不是各自为政各成一体。

2.垂直方向

变量声明在函数顶部,实体变量声明在类的顶部

相关函数放在一起,被调用的函数放在调用函数的下面

3.水平方向

注意使用空格

一行代码的宽度:120字符之内,最好不要拖动横向滚动条。

缩进,尤其是在有循环语句、判断语句的时候

第六章 对象和数据结构

1.对象和数据结构的区别

(1)数据结构中的对象只是数据,面向对象中的对象包括了数据和行为。

(2)数据结构暴露其数据,没有提供有意义的函数;对象把数据隐藏于抽象之后,暴露操作数据的函数。

(3)数据结构难以添加新的的数据类型,因为需要改动所有函数,面向对象的代码则难以添加新的函数,因为需要修改所有的类。

在任何一个复杂的系统都会同时存在数据结构和对象,我们需要判断的是要添加的是新的数据类型还是新的行为函数。

2.迪米特法则:模块不应了解它所操作对象的内部情形。

类C的方法f只应调用以下对象的方法:

(1)C;

(2)由f创建的对象;

(3)作为参数传递给f的对象;

(4)由C的实体变量持有的对象;

方法不应调用由任何函数返回的对象的方法,换句话说,只和朋友说话,不和陌生人说话。以下就是违反该法则的一段代码:

final String outputDir=ctxt.getOptions().getScratchDir().getAbsolutePath();

当然,迪米特法则的前提是对象,如果是数据结构,没有什么行为,则他们自然会暴露其内部数据结构,迪米特法则也失效了。

如果数据结构只简单的拥有公共变量而没有函数,对象拥有私有变量和公共函数,这个问题就不会混淆。


第七章 错误处理

1.错误处理很重要,但是如果它搞乱了代码逻辑,就是错误的做法。

2.要注意的几点

(1)先写try-catch-finally语句

异常的奇妙之一在于,它在程序中界定了一个范围,在执行try部分的代码时,表明了可以随时取消执行,并在catch语句中继续。

在编写可能抛出的异常时,先写出try-catch-finally语句,能够帮你明确代码的目的是什么,无论在try中的代码出什么错都是一样的

(2)使用不可控异常

如果你在方法中抛出可控异常,而catch语句在三个层级之上,你就得在catch语句和抛出异常处的每个方法签名中声明该异常。

每个调用该函数的函数都要修改,捕获新异常,或者在其签名中添加合适的throw子句,封装被打破,因为在抛出路径中的每个函数都要去了解下一层级的异常细节。

(3)给出异常发生的环境说明

应该创建信息充分的错误消息,并和异常一起传递出去,消息中应该错误类型和失败操作,如果有日志系统,就应该传递足够的信息给catch块,并记录下来。这样可以方便的判断错误的来源和住所。

(4)别返回null值

在方法中返回null值,不如抛出异常或返回特例对象

注意一下,这个emptyList不支持add操作,也不支持get操作。

第八章 边界

1.优雅的使用第三方库

大多数人是通过花好几天阅读文档,再决定怎么使用,然后编写。最后不免陷入漫长的调试找代码中的缺陷中。因为学习第三方库代码很难,整合第三方代码也很难。

2.学习性测试

(1)找到最基础的文档(用来给第一次使用的人看的),开始阅读文档。每读完几个的api,便开始整合完成你想要的某一个功能,写一个类的一个函数将其封装起来。

(2)完成你初步罗列出来的功能便可以开始测试,如果不需要深入理解他人的代码的话,完成所需功能即可。如果想要开发超过百行的有关代码,还是把最基础文档的api全部测试一遍好。

(3)测试:对函数分别调用,从中弄懂参数和返回值的真正意义,并以此弄清当前函数整合的所有api干了什么。

(4)测试完成后,便应该只用自己封装起来的函数来写自己旳程序。当需要调用新的api,如果这个api属于之前的某个功能,就写进那个功能对应的函数,如果是新的功能,则应该考虑写新的类、新的的函数。

Clean Code读书笔记的更多相关文章

  1. “Clean Code” 读书笔记序

    最近开始研读 Robert C.Martin 的 “Clean Code”,为了巩固学习,会把每一章的笔记整理到博客中.而这篇博文作为一个索引和总结,会陆续加入各章的笔记链接,以及全部读完后的心得体会 ...

  2. 如何优雅地进行错误处理(clean code阅读笔记之六)

    错误处理是十分必要的,但是如果对错误处理使用不当则会让代码变得十分臃肿,让阅读者看不清代码的逻辑,更严重的是,这也会让程序变得十分脆弱.本文中将列出一些使用错误处理的技巧,帮助你写出既简洁又健壮的代码 ...

  3. 《代码整洁之道》(Clean Code)- 读书笔记

    一.关于Bob大叔的Clean Code <代码整洁之道>主要讲述了一系列行之有效的整洁代码操作实践.软件质量,不但依赖于架构及项目管理,而且与代码质量紧密相关.这一点,无论是敏捷开发流派 ...

  4. Code Clean读书笔记

    代码整洁之道读书笔记 by fangpc 序言部分 "神在细节之中" - 建筑师路德维希 5S哲学(精益) 整理(Seiri):搞清楚事物之所在--通过恰当地命名之类的手段--至关 ...

  5. 《Clean Code》读书笔记——第二周

    本周我阅读了<Clean Code>. “神在细节中!”,建筑家范德罗如是说.他当然专注于基于宏伟构架之上的永恒建筑形式,他也同样为自己设计的建筑挑选门把手.同样软件开发也是这样,小处见大 ...

  6. 读书笔记:《梦断代码Dreaming in Code》

    读书笔记:<梦断代码Dreaming in Code> 拿到<梦断代码>书后,一口气翻了一遍,然后又用了3天时间仔细读了一遍,也不禁掩卷长叹一声,做软件难.虽难,仍要继续走下去 ...

  7. 【笔记】Clean Code(持续更新)

    这个暑假出来实习,第一次体会到在一个团队中开发的体验,与网上的网站看到的大为不同,以前看网上说什么程序员写了屎山代码,写了一堆模糊的注释或者说垃圾代码不写注释. 但在我的实习体验中,代码虽然看起来很多 ...

  8. Clean Code 笔记 之 第二章

    你是否真正的会命名 前言 这是我第二次看这本书了(Clean Code)的时候,第一次看的时候是,看到某世界五百强在他们的代码中我竟然看不到一句注释,现在我还记得当时的情景,当我Download 下第 ...

  9. 代码整洁之道Clean Code笔记

    @ 目录 第 1 章 Clean Code 整洁代码(3星) ?为什么要整洁的代码 ?什么叫做整洁代码 第 2 章 Meaningful Names 有意义的命名(3星) 第 3 章 Function ...

随机推荐

  1. 解决treeview的同一节点单击多次的执行问题

    在使用treeview的AfterSelect函数的时候,单击同一节点多次无响应. 解决方法: 将首次单击的节点信息保存到selectTreeNode: 然后使用click函数,判断单击的节点是否和s ...

  2. POJ 1699 Best Sequence dfs

    题目: http://poj.org/problem?id=1699 无意间A了..超时一次,加了一句 if(len > ans)return; 然后就A了,dfs题,没有太多好说的,代码写的效 ...

  3. 国内物联网平台初探(八):移动云OneNET

    国内物联网平台初探(八)——移动云OneNET 平台架构 数据模型 使用场景示意图 服务 IOT Paas 基础服务 为IoT开发者提供智能设备自助开发工具.后台技术支持服务,为您提供物联网专网.短彩 ...

  4. but has failed to stop it. This is very likely to create a memory leak(c3p0在Spring管理中,连接未关闭导致的内存溢出)

    以下是错误日志信息: 严重: The web application [/news] registered the JDBC driver [com.mysql.jdbc.Driver] but fa ...

  5. 【高德地图API】如何解决坐标转换,坐标偏移?

    http://bbs.amap.com/thread-18617-1-1.html#rd?sukey=cbbc36a2500a2e6c2b0b19115118ace519002ff3a52731f13 ...

  6. Ecmall系统自带的分页功能

    在Ecmall的二次开发中,分页是必不可少的.这个系统已经自带了分页功能,下面来看看如何使用这个分页. 下面是一个自定义的类,用于查看订单的详细情况.关键在于get_order_data()这个方法, ...

  7. 2016 Web 开发资源工具大搜罗

    原文链接: 100+ Awesome Web Development Tools and Resources Web的迅猛发展对于开发者来说既是一件好事也是一件坏事.不断紧跟潮流学习新的技术.编程语言 ...

  8. 如何在win下编译thunderbird

    最近突然想研究一下thunderbird的实现,于是在WIN2K3下对其进行了系列的编译,特将编译的一些心得与大家共享.其实编译过程已经非常简单了,本文以VC8 ( VISUAL STUDIO 200 ...

  9. 【Xamarin挖墙脚系列:典型的业务程序的结构搭建】

    原文:[Xamarin挖墙脚系列:典型的业务程序的结构搭建] 其实app就是客户端.在现代的程序中,都是典型的C/S结构.当然,一些离线的小游戏,功能性应用除外,如:电话本,通信录,短信查看等等 这个 ...

  10. FishEye简介

    前言     在项目开发过程中,随着开发的进行,将有大量的代码编写提交到代码仓库,如何能全面准确的了解源代码的变化,提交的频率,代码量的趋势,发现代码的缺陷,将是控制源代码质量的重要指标,这个时候一个 ...