Clean Code 中文版.doc_第1页
Clean Code 中文版.doc_第2页
Clean Code 中文版.doc_第3页
Clean Code 中文版.doc_第4页
全文预览已结束

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

什么是整洁代码如果代码很容易被团队的每个人读懂的话就称作整洁代码。伴随着可理解化发展了代码的可读性与可理解性,可变性,可扩展性和可维护性。在没有积累大量的技术债务情况下需要所有的东西来保持项目长时间的工作最佳响应特点刚性该软件是很难改变的。一个小小的改变,会导致后续变化级联反应。常规按照标准公约 编码,建筑,设计指南(检查工具)字段非定义状态+脆弱性由于一个单一的变化,会使得软件很多地方遭到破坏。保持简单,愚蠢简单的总是更好。尽可能地降低复杂性。F字段保存数据并不属于实例状态,但用于保存临时数据。使用局部变量或提取一类抽象执行的动作。可配置性高高固定性您不能重复使用代码在其他项目中,因为关系到风险和高精力。童子军规则离开营地比你发现它要清洁。 防止可配置性,因为没有人能决定它应该如何。否则,这将导致过于复杂不稳定的系统。响应变化根本原因分析 在一个源文件的多国语言版C#, Java, JavaScript, XML, HTML, XAML, English, German 微层不要在上面添加功能,但整体需要简化。实际 CoC变动成本(CoC)响应粘度的设计抄近路和引进技术债务更能够事半功倍。总是寻找一个问题的根本原因。否则,它将让你一遍又一遍。 依存性实体逻辑相依存单身/服务定位 使用依赖注入。单身隐藏的依赖关系。 +粘度环境高度增加复杂性该设计中包含的元素,目前没有用到。增加的复杂性,使代码更难理解。因此,扩大和改变代码结果需要投入较高的精力。构建,测试和其他任务需要很长的时间。因此,每个人都没能将这些活动正确执行技术债务引入。.环境项目建设只需要一步。退出只需然后建立一个单一的命令。I如果一个模块依赖于另一个,那应该是实体依赖,而不只是逻辑。不需要作出假设。+技术债务低最佳 CoC时间低执行测试只需要一步运行所有的单元测试,只需要一个单一的命令基类取决于它们的派生类 基类可以与任何派生类工作。不必要的重复源控制系统通常使用源代码控制系统信息过多减少接口耦合以致降到最低一个项目开始编写干净的代码是一个软件产品的整个生命周期中使变化成本保持尽可能恒定的一项投资。因此,当写干净的代码(灰线)时最初的变化成本比快速和肮脏的编程(黑线)稍高,但支付却相当快。尤其要记住的在软件维护过程中大部分费用需要支付。随着时间的推移,如果不重构干净的代码,不洁代码会导致技术债务增加。还有其他原因导致技术债务,如坏流程和缺少文件,但不洁的代码是一个主要驱动因素。造成结果的是,响应变化的能力在下降(红线)。代码中包含大量重复的代码:精确的代码重复或设计重复(以不同的方式做同样的事情)。重复一段代码更改更昂贵,更容易出错,因为变化在几个地方,需要面临一个地方没有相应改变的风险。持续集成保证完整性与持续集成特征排斥重写的安全装置依赖关系注入从运行系统中解耦构建在运行时完全解耦构建阶段,有助于简化运行时的行为。不要重写警告,错误,异常处理-他们会抓住你。.透明度 代码是很难理解的。由于不理解的副作用,因此,任何变化都需要花费额外的时间来重新设计代码,并更可能导致缺陷,。+类的方法应该是用在属于该类的类变量和函数中产生作用的,而不是作用于其他类别的变量和函数。当一个方法使用一些其他的对象来操作该对象内的数据的访问器和存取器时,那么它排斥其他对象类。它希望它里面的其他类以便可以直接访问变量操纵。人工耦合隐性时态耦合在整洁代码中,错误不能隐藏类的设计单一职责原则一个类应该有一个,且只有一个理由去改变。不依赖于对方不应该被人为地加上。例如,一些方法调用的顺序是非常重要的,然后确保他们不能被称为在次序错误+当改变现有的代码时,许多软件缺陷被引入。原因是开发商不能完全掌握改变代码时产生的影响。通过编写尽可能容易明白的代码,干净代码使引入缺陷的风险降至最低。设计较高水平的配置数据+开闭原则在不修改它的情况下,你能够有扩展一个类的行为。原则松散的耦合类,组件,模块中的至少有一个使用了其它的,则两个类,组件或模块将会耦合。这些项目了解对方之后,会实现宽松耦合。一个组件仅能够松散地耦合到它的环境,这样使得比强耦合的组件更为容易地改变或替换Liskov 替换原则+必须替代其基类的派生类I如果你有一个如拖欠或配置恒定的值,具有已知和抽象化预计的高水平,不要把它埋没在一个低级别的功能上。作为一个参数揭露它,从高层次的功能上调用低级别的功能。可传递导览 又名迪米特法则,写的关于害羞代码。 一个模块只需要知道它的直接依赖 不具随意性+依赖倒置原则依赖于抽象而不是结核。接口隔离原则使客户特定的细粒度的接口。拥有一个原因来构建你的代码,并拥有各原因来确保代码的结构是可传达。如果结构出现任意性,别人就会有权去改变它。命名选择描述性/正确的名称名称必须能够反映变量,字段,属性代表。名称必须是精确的。+精确性在你的代码中做出决策,确保你把它用得恰当。知道你为什么用它,你将如何处理任何例外。+选择适当的抽象级别名称 选择合适的名称,反映抽象化的类或方法进行工作高内聚+类应尽量小内聚(Cohesion)是一个模块内部各成分之间相关联程度的度量。在类中的一个组件、类的方法和字段应该应具有较高的内聚力。高内聚在类和组件中能生成较为简单,易理解的代码结构和设计。较小的类是比较容易把握的。类应小于约100行的代码。否则,它是很难发现类如何做它的工作,它可能不超过一个单一的作业。尊随公约结构按照约定的结构来执行设计决策。命名规范要求要好,但当他们处于劣势时会强制遵从。.功能抽象化后命名接口 一个接口的名称应该来自其使用的客户端,如 istream的。 局部变化+包装凝聚力发布重用等效原理重用的颗粒释放该颗粒。+偏向多态性if / else或Switch/Case +一个软件系统必须保持,延长和改变很长一段时间,局部改变降低了参与成本和风险。保持局部变化意味着有设计变化不交叉的边界。共同封闭原则一起改变的类被打包在一起。容易删除+共同重用原则使一起用的类被打包在一起。“一个switch”:对于一个给定类型的选择有可能是不超过一个switch语句。 switch语句的使用情况,必须在系统其余部分的地方创建关于switch语句的多态对象。.名称类别后,他们如何实现他们的接口 类的名称应该反映它是如何满足其接口(S)如MemoryStream的IStream的命名方法。 命名之后他们做些什么 方法的命名应该说明做了什么,而不是它是如何做。 +对称/类比 华丰对称设计(例如 Load Save)和遵循类比的设计(例如.NET框架中相同的设计)+我们构建软件通常通过添加,延长或改变功能。然而,移除元素很重要,这样可以保持整体设计尽可能的简单。当一个块变得太复杂,它可以移除并替换一个或多个简单的块。包装耦合无环依赖原则包的依赖关系图,必须没有周期。为长作用域使用长文件名 领域-参数-局部变量-循环变量-长-短+独立的多线程代码不要将代码混合使用来处理多线程方面其余的代码。将他们分为不同的类别。名称描述的效果 名称必须反映整个功能。 稳定依赖原则取决于稳定的方向误置职责一些代码放错了地方。在可能的情况下进行标准命名有一个标准的时候不要用你自己的语言 稳定抽象原则抽象稳定增加抽象错误级别的代码 功能处于抽象错误级别的,如一个PercentageFull物业中一个通用的ISTACK。编码名称 没有前缀,没有类型/范围信息整洁代码中文版(由K084 和K075翻译,不足之处,请参看原版:Clean-Code-V2.11!)可理解性一致性I如果你想以一种特定的方式来做某些事情,那么将这些事情的处理方式一致 相同的变量名称对应相同的概念,相应的概念对应相同的命名模式 ts.+条件语句条件式封装条件语句 if(this.ShouldBeDeleted(定时器)优选于if(& timer.HasExpired!timer.IsRecurrent)。+从遗留代码到干净的代码。 总是有一个正在运行的系统 1) 识别功能+如何了解干净的代码 结对编程 +在小步骤里更改系统,从一个运行状态到另一个运行状态。在您的代码里确定现有的功能,并根据有关它们未来的发展(变化的可能性和风险)再来优先考虑他们。 使用解释性变量使用区域变量来定义算法名称 +积极的条件语句 积极的条件比消极的条件语句容易阅读。 封装边界的条件 +相对于原始数据类型选择专用值对象 使用专用的基本类型取代像字符串,整数这样的原始类型,如,用绝对路径代替字符串。边界的条件是很难跟踪到的,将它们放在一个地方进行处理,如下一级=该级+1无用的东西死注释,代码 删除未使用的东西。您可以在版本控制系统中找到他们。 在一个单一的工作站两个开发人员一起解决问题。一个是驱动器,另一个是导航器。该驱动器是负责编写代码。导航器是负责按照编码准则来维持解决方案与架构,并着眼于下一步到去哪里(例如写下一步的测试)。既挑战他们的思路以及解决问题的方式2) 引入边界接口可测性 重构的界限,你的系统接口,以便可以模拟环境测试的双精度(假货,嘲笑,存根,模拟器)。 +提交评论开发人员与并同开发人员通过所有代码变更前的提交(或推动)到版本控制系统的变化。同行开发人员针对干净的代码的指引和设计对代码进行检查。 +杂乱不是死代码但不添加任何功能3) 写功能验收测试 覆盖功能验收测试,以建立一个安全网重构。 +不适当的信息 注释比不同的系统信息要好:产品积压,源代码控制。仅使用代码注释的技术说明编码道场 +差评模糊的意图 过于密集的算法会失去所用的表现形式。评论不添加任何值(冗余代码),格式不正确,不正确的语法和拼写。 4) 识别组件 在一个特征中,确定所使用的组件提供的功能。根据未来发展的相关性(可能性和风险的变化)的优先次序来排列组件。可维护性杀手 复制 消除重复。违反了“不要重复自己”(DRY)原则。 一组开发人员在编码道场走到一起,锻炼他们的技能。两个开发人员解决问题(形比赛)的结对编程。其余的人员一起观察。 10分钟后,该组旋转建立一个新的对。观察员可以批判当前的解决方案,但只有当所有的测试都是绿色的。 明显的行为方式不能执行 违反了“最小惊奇原则”,你所期望的就是你想得到的。 5) 重构组件之间的接口 重构(或引进)之间的接口组件,以便每个组件都可以在隔离的环境中测试。 +参考书目干净代号:由罗伯特马丁敏捷软件大师手册 + 幻数/字符串 当有意义的命名不能来自本身的价值时,将幻数和字符串替换命名常量,给他们一个有意义的名字。 隐藏的逻辑依赖 一个调用方法的正确与否取决于同一个类的其它东西,如调用删除,能删除返回真,否则失败。 6) 写组件的验收测试 覆盖功能由组件的功能与验收测试提供。枚举(持续或定义行为) 他们要坚持使用的参考代码,而不是枚举。他们定义的行为使用多态,而不是枚举7) 决定每个组件:重构,流程再造,保留 决定是否要重构,再造或保留它的每个组件。 +方法一种方法做一件事情循环,异常处理,.封装在子方法 +异常处理。捕捉特定的异常 你可以以有意义的方式反应捕捉的地方 8a) 重构组件 +内重新设计类组件和重构一步步骤(见重构的格局)。添加单元测试的每一个新设计的一类方法应该下降1个抽象级别 声明在同一个语句中的方法都应该写在同一个抽象层中,它应该是低于描述功能函数的名称。 .捕获异常要尽可能具体。捕获的异常,可以以一种有意义的方式反应。捕获异常时,你可以以一种有意义的方式反应。否则,让别人调用堆栈中的反应它。8b) 重新设计组件 8c) 保留组件 如果你预计未来只有少数的变化到一个组件,并且该组件在过去很少有缺陷,可以考虑保留它 使用ATDD和TDD(见清洁ATDD/ TDD小抄)的重新实现组件方法与参数太多 参数较少最好。功能可能被外包给含有字段信息的专用的类中 使用异常,而不是返回代码或空 故障快速切换OUT/ REF参数的方法 防止使用。返回复杂对象所持有的所有值,再分成几种方法。如果你的方法必须改变事物的状态时,它被称为改变对象的状态。 在特殊情况下,抛出一个异常时,你的方法不能完成其工作。不接受或返回null。不要返回错误代码。 异常应尽早抛出后检测一个特例。看着异常的堆栈跟踪,这有助于查明确切位置的问题 重构模式调解分歧统一类似的代码更改的代码逐级两条,直到它们是相同的。隔离变更+选择器/标志参数 迁移数据 全局整数符(布尔标志)分割成几个独立的方法,可以从客户端调用无标志的方法。 为控制流使用异常 控制流使用异常:有坏的表现,难理解,导致较难处理的真实异常。首先,隔离的代码从剩余部分进行重构。然后重构。最后,撤消隔离。移动从一个表示到另一个暂时性重复数据结构。不适当静态静态方法应该是一个实例方法 误吞的异常 异常可以被吞噬,只有在特殊情况下完全解决后离开catch块。否则,系统留在不一致的状态e.源代码结构垂直分离变量和方法应接被用来定义在他们关系密切的地方。局部变量应该声明略高于他们的第一次使用,并有一个小的垂直范围。 临时并行实现 +“重构”通过引入临时并行的算法实现。后一个调用者切换等。当不再需要时,删除旧的解决方案。 .非军事区的组件 +Legend:DODONT+嵌套命名空间功能的代码结构 保持所有属于相同的特性。不要使用命名空间通信层。一个特性可能会使用核心功能,如记录。嵌套代码应比非嵌套的代码更具体,或能够处理可能性较小的情况。介绍了内部组件边界和一切不必要的内部边界外推到组件接口和内部边界之间的非军事区。重构组件接口与内部边界相匹配并消除非军事区。 Urs Enzler June2013 V2.1自动检测的种类ATDD 验收测试驱动开发先指定一个特征测试,然后实现.+伪造 (存根, 伪装, 侦查, 模拟 )环境隔离使用伪装模仿被测试对象的所有依赖.不属于主机测试工具的测试+可以检测与测试工具中其他测试完全不同的测试对象的测试 .红色栏模式单步测试选择一个你最有信心的测试,你可以最大限度地提高学习效果(如:对设计的影响).+TDD 测试驱动开发红 绿 代码重构. 写一点代码,测试一点.伪装框架在不同测试场景中用来显示不同行为的伪装使用动态伪装框架(少量行为重复使用).过时的测试一个测试检查该系统不再要求的内容. 甚至可能妨碍清理的生产代码,因为它仍引用.部分测试扩展测试为更好匹配现实世界场景,扩展现有的测试.DDT 缺陷驱动测试POUTing 普通旧单元测试编写一个重生产缺陷的单元测试 修改代码 测试成功 缺陷永久修复.也被称为后测试.编写单元测试来检查已存在的代码. 你不可能想测试驱动的一切.使用 POUT 来增加健全.用于TDDing测试后添加额外的测试(比如:边界条件).手工编写伪装混合存根和期望公告隐藏测试功能测试功能隐藏在设置方法,基类或辅助功能类.只通过检查测试方法测试应该清楚别的有没有初始化或断言的地方编写一个测试,它不完全检查被所有要求的行为, 只是让你更进一步接近, 然后用下面的扩展测试.使用手工编写伪装当他们被用于多个测试时,同时他们只有几个行为变化在这些场景中(行为重用).确保你遵循AAA (arrange, act, assert)语法当使用模拟时.在同一代码块中,不要混合设置存根(可以是对象运行)具有这样的期望 (测试对象应该在的).臃肿的设置不清楚的错误原因拆分测试或使用断言消息.另一个测试如果想到新的测试,然后写进人物列表,不会失去当前测试聚焦.被测试对象调用的依赖和参数的结构使测试很难读懂.提取到帮助方法可以重复使用.可测试性的设计构造器 简单的对象必须可以容易塑造.否则, 不能实现容易、快速的测试+测试伪装取代测验对象Tests测试不检测测对象 但通过伪装返回值. 通常取决于极端伪装用法的量.学习测试编写针对外部元件的测试确保它们达到符合预期.条件测试的逻辑测试不应该有任何条件测试逻辑,因为其很难阅读.构造器 生命周期极端伪装用法通过依赖关系和配置/参数传入构造器,具有等同或长于被创造对象的生命周期.为其他值使用方法和属性.如果你的测试需要许多模拟或模拟设置, 然后考虑将测试对象分成几个类,或在你的测试对象和他的以来对象之间提供一个附加的抽象代码编写时的测试逻辑测试依赖于代码编写时的特殊逻辑.绿色栏模式假设 (直到成功)返回一个获得一一个测试运行的常数. 然后重构.+系统边界的抽象层+在系统边界(数据库, 文件系统, 网络服务, COM接口 .) 中使用抽象层,通过允许模拟来简化单元测试.单元测试原则快速为了经常执行单元测试不得不快速. 快速意味着远小于秒这级别.不稳定测试有时通过, 有时不通过并依赖于环境.三角化 驱动抽象化编写一个至少有两组简单数据的测试. 抽象的执行它们.+TDD 原则一个测试检查一个特征一个测试检查被测物体的一个特点.这意味着,它测试此功能中包括所有的东西,但不多.这可能包括多个呼叫被测物体.通过这种方式,测试作为被测物体的用法示例和文档.显著性性执+一对多 驱动收集操作首先,实施单个元素的操作,然后,逐步加到多个元素.结构安排 执行 断言通常通过AAA来对测试结构化. 切勿混淆这三个模块.独立的+可重复性不假设初始状态, 没有什么留下, 没有外在服务的依赖对象,可能导致不可获取(数据库, 文件系统 ).如果实现是显而易见的,那么只是落实一下,看看如果测试运行.如果没有,那么退后一步,只是试运行和重构.清除错误发生的地方. 测试集之间独立(随机顺序).测试程序集 (.Net)为每个产生的程序创造测试组件,并且以产生的程序名+ “.Test”为每个产生的程序命名.微小步伐做微小步骤操作.只有一点点测试代码之前编写所需的生产代码.然后重复.只添加一个断言每一步.+验收测试驱动开发使用验收测试驱动你的TDD测试用户功能测试自动的 ATDD组建验收测试+测试命名空间具有相关联测试对象的测试放在同一个命名空间.自我校正不需手动测试解释或干预. 不论红栏还是绿栏测试!保持测试简单每当一个测试变得复杂,检查是否可以被测物体分割成几类(单一职责原则)用验收测试检查所需功能,并指导你的TDD测试.验收测试是一个从顶到底的完整用户功能的测试并提供商业价值.使用自动化的验收测试驱动开发,回归测试和可执行的规范.为单个组件或子系统编写验收测试,因此这些部分可以去自由组合而部丢失覆盖率的.单元测试方法显示全部真相单元测试方法显示测试所需的所有部分. 不要使用设置方法或基类来执行测试对象或者依赖对象的操作.及时性测试被及时写出 (TDD, DDT, POUTing)偏向状态校正而不是行为校正 如果没有状态校正则使用行为校正.只对基础构造设置/清除只对单元测试需要的基础构造进行设置/清除.不要在进行其他任何的测试时使用它.单元测试缺陷测试并不检测所有通过测试第一眼看上去有效但没有测试测试对象.测试领域专业语言使用 DSLs 简化阅读测试: 辅助方法, 类.测试方法命名名字反应什么被测试, 例如:FeatureWhenScenarioThenBehaviour.测试需要极端测试一个测试需要数十行代码来设置环境. 这些噪声使我们很难发现什么被测试.TDD 过程缺陷使用代码覆盖率作为目标使用代码覆盖率查找缺失测试,但不把它当做驱动工具.否则,结果可能是测试的代码覆盖率,但不是确定性.单方案中的每个测试一个测试检测一个方案.太大的测试 / 多个方案的断言仿真系统边界资源文件测试和资源一致: FooTest.cs, FooTest.resx一个有效的测试太大了. 原因是这个测试检测不止一个功能或者测试对象不止一个 (违反单一职责原则).最后没有绿色栏10 分钟使用较小的步骤获得快速和频繁的反馈.命名命名被测系统测试变量结果值的命名匿名变量内部检查+一个测试直接访问测试对象内部(私有/受保护成员) (反射). 只是代码重构杀手.测试编写要在代码产生之前只有测试失败, 新的代码才需要. 另外, 如果测试结果令人惊讶但不是失败,要确保测试正确.仿真系统边界,如用户界面,数据库,文件系统和外部服务,加快验收测试并能检查异常情况 (例如,一个完整硬盘). 使用系统测试检查边界.验收测试狂潮对拥有正在测试的系统的变量使用相同的名字 (例如:testee or sut). 清楚识别被测系统,反重构的强健性.对拥有测试方法结果的变量通常使用同样的名字(例如: result).通常,对拥有被测方法无兴趣参数的变量使用相同的名字(例如: anonymousText).测试只在开发人员的机器上运行一个测试依赖于测试环境的改变和其他地方的错误 . 尽快使用连续不断的集成环境来获取他们.重构时间不足重构是一种对未来的投资. 可读性,可变性和可扩展性都会回报回来.不要编写处理每一种可能性的验收测试. 只为几个这是场景编写验收测试. 特殊的和理论性事例可以用更容易的单元测试覆盖.超过必要的测试一个测试检测比他目标更多. 测试出错当检测不必要的东西发生改变. 尤其是包含伪装或有序检测项在无序集合中.跳过容易测试的部分无需假设, 检查. 如果很容易, 那测试就更容易.跳过很难测试部分使它更简单, 不然 bugs会隐藏在那并影响可维护性.不相关的信息测试包含不相关理解的信息不要假设理解算法只是理解能工作不够, 确保理解为什么能工作.+重复测试测试使用文本填满控制台 可能曾使用国手动检测.围绕方法组织测试, 而不是行为边界的错误行为经常测试边界. 不要对行为假设.吞吐异常测试测试捕获异常并且通过测试.这些测试很脆弱且是重构杀手. 测试完全迷你使用这样的事例,它反应现实世界里特征如何运行.不要孤立的测试setters和getters, 测试使用它们场景.持续整合预提交检查后提交检查对每一个向在持续集成上的版本控制系统提交的测试运行所有的单元和可接受测试.ATDD, TDD周期+探索设计为用户填写验收准则这个团队都为用户填写验收准则.定义示例整个团队定义用于显示代码项目验收标准的示例.编写验收测试框架在验收测试框架中把示例映射到映射到一个空的规范 / 测试(Gherkin, MSpec 类 和它的声明 )在提交到代码资源库之前,运行覆盖当前运行在代码上的所有单元和可接受测试.面向团队的沟通失败的整合当一个阶段的持续整合服务失败, 通知整个团队尽快解决阻塞情况.需要构建知识来执行验收测试.初步设计有足够

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论