话在我们这个行业是很幽默的。我们总说编程就是CV,黑客写的程序大部分都是靠复制粘贴。其实很多资深或者资深的程序员写代码,就是CV:从别的项目copy一段代码,稍微改动一下,跑起来没问题。但这种做法是在给后代挖坑!通常只要这些CV代码中有一点逻辑需要修改,就意味着所有的CV都要修改。所以,很多人在实际开发的时候,发现明明很简单的小需求,你要改很多地方。需要很长时间和测试来解释如何测量它们。你搞的PMO和领导对你做人效率很不满意。!只要你少做一个改动,就等于留下一个潜在的bug,等你发布生产的时候,发现各种小问题,继续连夜回滚和hotfix,最后重新发布版本。你找到CV的致命点了吗?这种方式是最容易产生重复代码的地方,所以DoNotCV!正确姿势:提取方法fun,在需要的地方调用fun方法。CV的重复代码比较好找,但是有的代码结构类似,也是重复代码!然而,有些人却对这种难闻的气味视而不见。事实上,创建重复代码的恶意动机还是很多的:在后续开发中实现,或者发现但不容易直接引用改进:为了稳定性及时重构不合理的地方,坚持照搬老逻辑。不熟悉业务&&不相信自己的代码能力,不敢重构改进:通过微重构,多次迭代小改进,慢慢优化互联网敏捷开发,“快”的坏事不能做确定由于时间限制或能力问题代码。改进:提高结构重复能力某系统需要向翻译引擎发送工作相关信息:sendBook发送工作信息至sendChapter发送章节至startTranslation开始翻译。这些业务都是后台执行的,所以加上方法签名。任务注解,表示是任务调度入口。实际的代码执行放在对应的服务业务方法中。是不是够简洁,但是这段代码的结构是重复的,注意catch语句。之所以要catch,是为了防止系统出错而不被人察觉。捕捉到异常后,通过IM将错误信息发送给相关负责人。注意,逻辑是后来加的,所以这段代码的作者不厌其烦地到处修改代码。这三个函数调用的业务代码虽然不同,但是结构是一样的,基本流程可以概括如下:可以提取结构。从OOP的角度来说,就是抽取一个接口:使用函数式编程来简化代码:如果有一些通用的结构调整,比如在任务执行前后添加一些日志信息,这样的改动可以放在executeTask方法中而不是改变!很容易错过!所以这种题其实并不复杂,关键是找到结构重复。与直接CV相比,结构重复极具欺骗性。人们很难对他们所做的三件事做出反应,但它们也是重复的代码。一般参数是名词,而方法调用是动词。动词不同,不代表没有重码!知道这一点,就更容易找到相似的结构。比如案例中:发作品信息、发章节、开始翻译好像是三个不同的东西,只是因为动词不一样,但是除了动词,其他部分都是一样的!因此,它们属于结构重复。做出真正的选择来编辑章节内容。有一个业务逻辑。章节审核通过后,才能进行后续的处理,比如章节的翻译。所以这里editChapter方法的最后一个参数表示是否审核通过。在这段代码中,当前的处理逻辑:如果本章是作者编辑的,那么本章需要审核。如果这一章是editor编辑的,那么审稿直接pass,因为editor本身也是Whatexactlydidthereviewerchooseif?感觉if选择的一定是两个不同的业务流程。但是仔细观察后发现if和else这两段代码几乎是一样的,只是最后一个参数不同而已。是的,这也是一种重复代码。只是这种重复的代码是你新写的,不是CV。因为写的时候只想到if判断之后要做什么,而没有想过if语句判断的是什么。客观上容易造成重复。写代码一定要有表现力,准确表达意图,这是优秀代码的基本要求。而且这里的if判断区分的是参数,不是动作。这段代码可以微调:这里我将user.isEditor()的判断结果赋值给approvedboolean变量,而不是直接作为参数传给editChapter。这波操作只是为了提高代码的可读性。因为editChapter最后一个参数表示该章节是否审核通过,引入approved变量,可以清楚的看出一个章节是否审核通过的判断条件是“用户是否是编辑者”,这样代码就更清晰了!如果以后通过审批的条件发生了改变,改变的点只在审批的变量赋值上!如果你正在寻找一种更具表现力的方法,你可以提取一个方法并将所有的变化放在这个方法中:在实际项目中,你经常可以看到if语句没有有效地选择对象,有的是参数列表特殊的,有的有if代码块中的多个语句。所以,只要看到出现if语句,而且if和else的代码块看起来很相似,很可能就是出现了这种badsmell。不想玩“找茬”,给自己以后的发展留个坑,赶快重构吧!Don'tRepeatYourself(DRY,不要重复自己)在一个系统中,每一条知识都必须有一个单一的、清晰的、权威的表达。每一条知识都必须在系统中有一个单一的、明确的、权威的表示。写代码要做到DRY,一个关键点就是要能找到duplication。发现重复:在沼泽中挣扎后,被动地发现并提高自己的识别能力,主动发现并复制这种主动识别能力,其实背后是对软件设计,尤其是关注点分离的更好理解。本文转载自微信公众号「JavaEdge」,可通过以下二维码关注。转载本文请联系JavaEdge公众号。
