随笔分类 -  【6】代码重构

摘要:《小酌重构系列》是我在博客园的第一个系列文章,这个系列历时一个多月终于完成了。写这个系列的初衷是为了团队培训,为什么要做这个培训呢? 是因为在项目的开发过程中,我们遭遇了一些“代码的痛苦”。 写代码是程序员的基本工作,但写出好的代码不是一件容易的事情。 写不出好的代码,就可能产生痛苦。代码的痛苦包含哪些方面呢?一般来说,包括... 阅读全文
posted @ 2016-06-02 07:17 keepfool 阅读(1228) 评论(5) 推荐(18) 编辑
摘要:当方法返回类型或属性类型为集合时,有些开发者会千篇一律地使用IList<T>集合。然而IList<T>具有集合的所有操作,这意味着调用者不仅可以读取集合信息,还能够修改集合。业务需求本来只是为调用者提供一个可读的集合,例如数据的查询和展示,但当方法返回IList<T>时,无疑隐式地开放了集合可写的权限。此时,我们无法阻止调用者篡改集合元素。这种情况下,我们应该使用IEnumerable<T>来代替IList<T>。 阅读全文
posted @ 2016-06-01 07:13 keepfool 阅读(1514) 评论(7) 推荐(13) 编辑
摘要:当条件判断语句较为复杂时(有多个不同的检查项),会使得代码的可读性会大打折扣,也难以清晰地传达判断意图。再者,当判断逻辑变更时,我们不得不去修改if语句里面的判断代码。 我们可以根据检查项是否需要参数来封装条件,如果检查项不需要参数,则可以将其提取为属性;如果需要参数,则将其提取为方法。 本文要讲的重构策略“封装条件”是基于“提取方法”这个重构策略的。 阅读全文
posted @ 2016-05-31 22:16 keepfool 阅读(1350) 评论(2) 推荐(6) 编辑
摘要:在自然语言中,双重否定表示肯定。但是在程序中,双重否定会降低代码的可读性,使程序不易理解,容易产生错觉。 人通常是用“正向思维”去理解一件事情的,使用双重否定的判断,需要开发者以“逆向思维”的方式去理解它的含义。 另外,在写程序时,"!"符号很容易被疏忽和遗漏,一不小心则会编写出错误的代码,从而产生bug。 所以,在程序中,我们应当尽量避免使用双重否定。 阅读全文
posted @ 2016-05-30 22:10 keepfool 阅读(1513) 评论(3) 推荐(8) 编辑
摘要:异常处理的关键在于何时处理异常以及如何使用异常,有些开发者会觉得try catch的处理和使用难以把握,于是他们秉承着“您可错杀一千,不可放过一个”的想法,给所有的方法添加try catch。 从用户角度出发,用户确实难以察觉到什么,应用程序运行正常,使用的体验好像也没什么差别。 从程序角度出发,大量的try catch会降低代码的可读性,只有在异常触发时才会对程序的性能造成较大的影响... 阅读全文
posted @ 2016-05-21 05:44 keepfool 阅读(1469) 评论(8) 推荐(10) 编辑
摘要:if else, for, while等是程序中最常用的语句,这些语句有一个共同点——它们的逻辑都封装在一对“{}”包围的代码块中。在实现复杂的业务逻辑时,会较多地用到这些语句,可能会形成多层的代码嵌套。代码的嵌套层数越大,代码的缩进层次就越深,这将会降低代码的可读性。本文要讲的“分解大括号”策略正是为了避免这种问题,它也可以使我们的代码变得更加整洁。 阅读全文
posted @ 2016-05-20 22:59 keepfool 阅读(1404) 评论(2) 推荐(7) 编辑
摘要:在程序中创建对象,并设置对象的属性,是我们长干的事儿。当创建对象需要大量的重复代码时,代码看起来就不那么优雅了。从类的职责角度出发,业务类既要实现一定的逻辑,还要负责对象的创建,业务类干的事儿也忒多了点。对象创建也是“一件事”,我们可以将“这件事”从业务代码中提取出来,让专门的类去做“这件事”,这就是本文要讲的主题——提取工厂类。 阅读全文
posted @ 2016-05-19 23:49 keepfool 阅读(1013) 评论(3) 推荐(8) 编辑
摘要:试想这样一个场景,你提供了一些API给客户端调用,客户端传入了一些参数,然后根据这些参数执行了API逻辑,最终返回一个结果给客户端。 在这个场景中,有两个隐患,它们分别是: 客户端调用API时,传入的参数是否准确,参数是否满足API的执行前提 API逻辑执行完时,返回的结果是否准确,结果是否符合客户端的预期 阅读全文
posted @ 2016-05-19 07:15 keepfool 阅读(1497) 评论(2) 推荐(5) 编辑
摘要:在一些较为复杂的业务中,客户端需要依据条件,执行相应的行为或算法。在实现这些业务时,我们可能会使用较多的分支语句(switch case或if else语句)。使用分支语句,意味着“变化”和“重复”,每个分支条件都代表一个变化,每个分支逻辑都是相似行为或算法的重复。今天我将介绍一种新的处理“变化”和“重复”的策略——“使用策略模式代替分支"。 阅读全文
posted @ 2016-05-17 22:42 keepfool 阅读(2490) 评论(8) 推荐(18) 编辑
摘要:有时候你可能会在条件判断中,根据不同的对象类型(通常是基类的一系列子类,或接口的一系列实现),提供相应的逻辑和算法。 基于这种场景,我们可以考虑使用“多态”来代替冗长的条件判断,将if else(或switch)中的“变化点”封装到子类中。这样,就不需要使用if else(或switch)语句了,取而代之的是子类多态的实例,从而使得代码的可读性和可扩展性提高了——这就是本文要介绍的重构策略“使用多态代替条件判断”。 阅读全文
posted @ 2016-05-15 17:08 keepfool 阅读(3988) 评论(2) 推荐(9) 编辑
摘要:我们有时候在应用程序中可能编写了一些“幽灵”类,“幽灵”类也叫中间类。这些中间类可能什么事儿都没做,而只是简单地调用了其他的组件。这些中间类没有发挥实际的作用,它们增加了应用程序的层级(layer),并且增加了应用程序的复杂性。这时,我们应将这样的中间类删除,甚至删除中间类所处的“中间层”——这就是本文要讲的重构策略“移除中间类”。 阅读全文
posted @ 2016-05-15 10:32 keepfool 阅读(1018) 评论(0) 推荐(4) 编辑
摘要:为了方便大家阅读这个系列的文章,我弄了个目录汇总。主要包含4个部分:1. 方法、字段重构 2.类、接口重构 3.设计模式重构 4.一般性重构 阅读全文
posted @ 2016-05-14 15:32 keepfool 阅读(4378) 评论(2) 推荐(14) 编辑
摘要:单元测试是针对代码单元的“独立”测试,编写单元测试有助于改善代码的质量。在编写单元测试时,难免有一些功能是依赖于其他代码的。通常我们只想测试这些功能本身,而不想测试它所依赖的代码。“依赖的代码”是编写单元测试时的一个难题,我们可以通过2种方式来解决这个问题:Mock依赖的代码和分解依赖。然而Mock不是万能的,我们不能在单元测试中Mock静态类,但是通过“分解依赖”可以解决这个问题,本文将通过一个示例来演示这2种方式。 阅读全文
posted @ 2016-05-09 23:31 keepfool 阅读(1373) 评论(0) 推荐(7) 编辑
摘要:子类可以继承父类的字段、属性和方法,使用“继承”可以较大程度地复用代码。 在使用继承时,务必要确定代码中定义的“父类”和“子类”确实存在客观的“父子关系”,而不要去做“为了代码复用而使用继承”的事情,这是舍本逐末的做法,也是滥用继承的体现。 滥用继承会破坏类之间客观存在的关系,也会模糊代码所体现的语义。 阅读全文
posted @ 2016-05-07 09:32 keepfool 阅读(2593) 评论(9) 推荐(9) 编辑
摘要:当一个方法包含大量的布尔参数时,方法是很脆弱的,由此还可能会产生两个问题: 1. 方法不容易被理解 2. 给方法的使用者造成一定困扰,可能会产生一些预期之外的结果 本文要介绍的重构策略“为布尔方法命名”,可以有效地避开这两个问题。 阅读全文
posted @ 2016-05-03 22:55 keepfool 阅读(1956) 评论(5) 推荐(15) 编辑
摘要:本文要介绍的是4种重构策略,它们分别是提升方法、降低方法、提升字段和降低字段。在使用这4种重构策略之前,我觉得有必要先介绍一个重要的概念——语义。语义可以简单地看作是数据对应的现实世界中的事物所代表的概念和含义,以及这些含义直接的关系,是数据在某个领域上的解释和逻辑表示。语义具有领域特征,不属于任何领域的语义是不存在的。接下来,我将通过示例来描述这4种示例。 阅读全文
posted @ 2016-05-01 22:17 keepfool 阅读(1467) 评论(2) 推荐(7) 编辑
摘要:“艺术源于生活”——代码也源于生活,你在生活中的一些行为习惯,可能会恰如其分地体现在代码中。 当实现较为复杂的功能时,由于它包含一系列的逻辑,我们倾向于编写一个“大方法”来实现。 为了使项目便于维护,以及增强代码的可读性,我们有必要对“大方法”的逻辑进行整理,并提取出分散的“小方法”。 这就是本文要讲的两种重构策略:提取方法、提取方法对象。 阅读全文
posted @ 2016-04-26 00:33 keepfool 阅读(4036) 评论(18) 推荐(24) 编辑
摘要:有些开发者在编写方法时,可能较少地去思考一个问题:方法放在这个class中是否合适? 他们可能会觉得:这个方法已经实现xxx功能了,放在哪个class都一样的,class不就是一个装方法的容器嘛。 我赞同class是一个装东西的容器,且不仅限于方法。 但是,容器是有区别的。本文要讲的“移动方法”可以让方法放进合适的class的一种重构策略。 阅读全文
posted @ 2016-04-24 18:47 keepfool 阅读(5767) 评论(14) 推荐(24) 编辑
摘要:相信博客园的读者大多都是千万“码农”中的一员,每个人都写过很多代码,但并不是每一个人都能写出高质量的代码。 rome is not built in one day !——完成高质量的代码也不是一蹴而就的。为了写出高质量的代码,我们需要借助一些手段,“代码重构”基本上是最常用的手段,甚至是唯一的手段。 重构需要你花一些心思去琢磨自己的代码,这好比自己种的花花草草,看你怎么对待它们。你不给它们浇水、除虫、晒太阳,它们可能会长虫、生病。如果你用心地去对待它们,它们可能会枝繁叶茂,花开茂盛。但是,即使你已经很专心地去打理它们了,它们也不一定是“健康的”,毕竟每一种花草都有自己的习性,代码也是如此。 阅读全文
posted @ 2016-04-23 08:10 keepfool 阅读(9228) 评论(23) 推荐(60) 编辑

点击右上角即可分享
微信分享提示