Kent Beck 教你编程模式与代码重构

《Test-Driven development By Example》阅读(一) SQ3R阅读法:   一、Survey(阅读前的调查)       1、书名:《Test-Driven development By Example》,中文译名《测试驱动开发实例》。     2、作者:Kent Beck(肯特·贝克),美国著名软件工程师与作家,在软件工程方面有很大的贡献。他是Smalltalk软件的开发者,设计模式的先驱,测试驱动开发的支持者,也是极限编程的创始者之一。 阅读详情

Kent Beck 是最早研究软件开发的模式和重构的人之一,是敏捷开发的开创者之一。一起跟大佬学习提高写代码的姿势吧。

关于 Kent Beck 与《实现模式》这本书

  • 作者简介


    Kent Beck,软件开发方法学的泰山北斗,是最早研究软件开发的模式和重构的人之一,是敏捷开发的开创者之一,更是极限编程和测试驱动开发的创始人。

  • 《实现模式》


    这本书是 Kent Beck 的杰作,目标是帮助你通过代码表达自己的意图,从更高的层次理解代码的结构与模式。

  • 章节概览

模式

举个栗子???? 编程中,我们想写一个函数,需要给它命名。那么映入我们脑海的是:

  1. 模式让你感觉到束手束脚,但可以帮你节省时间和精力,提高效率。

  2. 模式的种类繁多,众多模式构成了一种编程风格

一种编程理论

价值观

原则

小结

上面提到了个关键词,分别是:模式、原则、价值观。

模式是编码时的一些约束(force),众多的模式共同构筑了一种编程风格。

价值观是编程过程中统一支配性主题,影响了我们在编程中所作的每个决策。

原则是模式和价值观之间搭建的桥梁,在遇到没有现有模式可以解决的问题的时候,原则往往可以让我们“无中生有”的创造一些东西,而这些东西往往都是很不错的。

摘录书中的一句总结:模式描述了要做什么,价值观提供了动机,原则把动机转化成了实际行动。

动机

由上面的讨论可以知道,价值观为模式的形成提供了动机。那么主要的动机之一是软件设计应该致力于减少整体成本。

经过统计,人们发现,维护成本远远高于初始成本。也就是说维护的代价很大。因为理解现有代码需要耗费很多时间,而且容易出错,改动之后还需要重新测试和部署。

通过合理的模式的使用,可以降低经济成本。

类

关于类,书中讲解了很多细小的点。有的比较有意思,值得一说。

通读本章后,进行了梳理整合,做如下总结。

  1. 类的命名

    类的名字应该是简明扼要,简短而有表现力。一个好的命名可以大大增加理解代码的容易度。

  2. 针对接口编程,不针对现实编程

    对操作进行抽象,由子类实现各自的具体逻辑。


    interface(接口)对扩展开放,对修改关闭。比如想给一个interface增加一个函数,不能直接添加,  要重新写个interface继承它。如果直接在原interface增加函数,就要导致所有实现了本接口的地方都要修改,这个代价是非常大的。

  3. 当我们从其他地方复制了一大段代码

    如果有两个地方的代码非常相似甚至相同,那就要考虑是否可以抽取到公共父类或者工具类中。直接拷贝一份的弊端很明显,维护起来很困难,比如其中一个地方需要修改,那么另外一个地方是不是也要修改呢。而且增加了代码的阅读难度,这明显和模式的原则不符。

  4. 内部类和匿名内部类

    内部类当被实例化之后,会获得创建它的外部类对象的引用,所以可以直接访问后者的数据而不用建立额外的连接。


    但是这种对象持有操作有内存泄漏的风险。比如在手Q中ThreadManager.post中就有特殊的操作来避免内存泄漏。

  5. 逻辑委派和可插拔的选择器

    把相同的逻辑统一处理,然后把不同的逻辑发放给不同的模块去处理。在手Q中,不同的回报消息在统一处理之后发放给不同的回调逻辑,也是一种实际应用。

    可插拔的选择器和逻辑委派很相似,比如有一个打印类的函数列表的工具方法,传给它不同的类名,就打印不同的类的函数信息。

  6. 类库

    把一些公共的方法放到一个公共的类中,声明为static,当成工具来调用。可以简化代码,看起来更清晰。

状态

  1. 直接访问与间接访问

    在类中有很多变量,每一个变量都会存在很多状态,比如boolean有true和false两种状态,一般类的范围内进行直接访问,对外部的访问一般强制间接访问,也就是通过public的函数访问。


    比如下面这种方式一般是类内访问。

    door.isOpen = true
    

    而下面这种方式一般用在类外访问。

    public boolean isOpen() {
        return this.isOpen;
    
    }
    

    其实就是合理使用Java中的private、protected、public修饰。

  2. 变量的分块

    在一个类中有很多变量,比如private成员变量、static静态变量、public公共变量,除了变量名命名要规范外,还要分区分块。比如static类型的应该放到最上面,并且与其他类型的变量隔开。

  3. 参数

    一个变量想传递到其他地方有很多方法。比如可以设置成public+static,让别人直接访问。但是这种方式耦合程度太高,比如改一个变量名,所有引用的地方都要修改。可以使用参数,直接把一个状态传递到另外一个地方,而不涉及二者之间的耦合。

  4. 变量的初始化:及早初始化和延迟初始化

    初始化就是给变量一个默认的状态。


    对于对性能影响较低的初始化可以及早初始化,可以保证变量在后续的使用过程中是已经初始化了的。并且变量的初始化要尽量放到一起,这样逻辑更清晰,也更美观。比如Android中的findViewById()在初始化时就要尽量放到一起。

    延迟初始化是考虑到了性能问题,如果初始化成本很高,就可以考虑通过延迟初始化来实现快速启动。

行为

  1. 主体流

    虽然Java是面向对象编程,但是在一个函数中,也是由上到下依次执行。主体流中包含了一些异常判断和卫述句(guard clause)。

  2. 卫述句

    卫述句是异常检查的一种方式。在程序的主体流中,需要判断某些不适用主体流的情况。

    void init() {
        if (isInited) {
    
            return;
    
        }
    
        ....
    
    }
    

    我们习惯了if-then-else这种约束,当看到if的时候,很容易就想到需要else语句。卫述句则不需要else子句,它是表达的另一种情形,只是一次主体流中的异常判断。

  3. 异常传播

    当程序发生异常,不能直接将日志信息输出,这样被有心之人抓取到了会产生安全隐患。同样也不能置之不理,这样后面排查问题就很困难。正确的做法是调用异常处理工具,比如写入日志文件等等。

方法

把大块的逻辑分成许多块,每一块都是一个方法,每个方法起一个顾名思义的名称。这样的代码理解起来更容易,更易于维护和重用。

  1. 安全复制

    如果在一个类中有一个List,存放着若干个类Demo的对象实例,比如

    List<Demo> list = new ArrayList<Demo>();
    

    如果外界想访问这个列表呢,通常的做法是这样的

    public List<Demo> getDemoList() {
        return this.list;
    
    }
    

    这样的话会有安全隐患,我们必须要考虑,外界的逻辑是否会对我们的数据产生影响

    getDemoList().clear(); // 数据被莫名修改,会发生一些问题。
    

    考虑更高的安全性,我们可以这么做

    public List<Demo> getDemoList() {
        List<Demo> copyList = new ArrayList<Demo>();
    
        copyList.addAll(this.list);
    
        return copyList;
    
    }
    

    当然,安全复制不可滥用,如果数据很大,这种复制会占用耗费的内存和性能,所以更好的做法是综合考虑安全性和性能的平衡。

  2. 方法注释

    对于沟通良好的代码来说,很多注释完全是多余的。在强调命名的沟通性和表达性的时候,注释显得处在一个很别扭的层次上。注释不是越多越好,在必要的时候添加适当的注释是合理的。当然,在后期的代码修改的时候,记得及时更新代码注释,否则注释不正确反倒对阅读人造成了误解。

容器

  1. 使用容器应该关心的一个问题

    在将容器暴露给外界使用的时候,需要考虑外界是否可以对容器进行修改。比如Iterable无法保证容器中的数据不被修改,外界可以直接调用它的remove方法进行修改,而不通知容器所有者,这样会出现问题。解决办法之一就是返回一个安全拷贝。

  2. 不可变的容器

    当只想把容器暴露给外界而不希望被修改时,除了安全拷贝外,还可以创建不可修改的容器,当容器的元素被外界修改时,程序会throw exception。

    3. 容器的继承和委派

有时候我们可能需要继承一个容器类。比如新建一个书籍列表的类Library,我们的目的是给他提供类似集合一样的增删改查操作。一个很直接的想法是让它继承ArrayList。

public class Library extends ArrayList{
    ....
}

这种操作实现了Library的add、remove、迭代以及其他容器操作,但是这种方式会带来一些问题。比如一般我们不需要ArrayList的toArray操作,但是如何避免用户调用呢,总不能把所有不需要的方法都加以实现并抛出UnsupportedOperationException来取消继承。

这里可以使用委派来实现这种操作。

public class Library{
    Collection<Book> books = new ArrayList<Book>();
}

使用这种方式可以只暴露一些需要的方法。我在头像墙widget中就是这样做的。

public class AvatarWallViewPager{
    protected RollViewPager mViewPager;
}

改进框架

  1. 更新框架时的向前兼容性

    在更新框架的时候,一个非常重要的点就是向后兼容。更新框架的功能不能影响到现有代码的逻辑。在设计框架的时候,保持代码尽可能简单的同时,也要尽可能提高代码的适用范围,考虑后续框架的更新是否容易。

  2. 兼容性更新--增量式更新

    包(package)为框架代码的增量式更新提供了一条途径,可以在新的包下创建相同类名的新类。比如把更新后的org.junit.Assert放到org.junit.improved.Assert这个类中,这样的话客户代码只需要更新imports语句就可以实现更新。修改import更加简单,影响更小。

  3. 抽象--接口和抽象类

    多使用接口和抽象类可以提高框架的灵活度。只将必要的逻辑暴露给外部使用,内部逻辑是private的。当修改框架代码时,只要接口和抽象类的抽象方法不变,其他的逻辑可以灵活修改,外部调用者不会受到任何影响。

附录 A

这部分主要是介绍了一个度量操作性能的框架。介绍了设计框架时要注意的一些事情。

设计操作度量框架要注意以下几个要点:

  1. 将操作执行多次,取平均值,克服精度问题。

  2. 在测量时要考虑Java的自动优化机制会不会影响操作执行的时间。

总结

这本书主要是着力于编程时的思维层面上的考虑。开发者大脑中要时刻铭记沟通、简单、灵活的价值观,遵循实现模式,并学会在遇到前所未有的问题时,能在价值观的指导下,利用现有原则找到更为恰当的解决方案。

据说很多靓仔都点了“在看”!

实现模式 [(美) Kent Beck著] 学习如何编写高质量代码,如何提高代码的可读性,提升编程能力 立即下载

相关推荐

重头开始学ROS(8)---LVI-SAM复现与实机部署Ubuntu20.04以及如何适配6轴imu

本文详细记录了在Ubuntu20.04环境下复现LVI-SLAM系统的过程,主要包含四个部分:源码编译、问题解决、数据录制和6轴IMU适配。在编译过程中遇到GTSAM、PCL版本、OpenCV路径等典型问题并给出解决方案;详细说明了ROS bag包的录制规范;针对6轴IMU硬件限制,提供了核心代码修改方案。文章为LVI-SLAM系统在非标准环境下的部署提供了实用参考,特别适合需要适配不同硬件配置的研究者。

qq_73991479的博客 1558

你必须知道的Java开发大牛

1、James Gosling   在他12岁的时候,他已能设计电子游戏机,帮忙邻居修理收割机。大学时期在天文系担任程式开发工读生,1977年获得了加拿大卡尔加里大学计算机科学学士学位,1983年获得了美国卡内基梅隆大学计算机科学博士学位,博士论文的题目是:"The Algebraic Manipulation of Constraints"。

1424

自适应粒子群优化(Adaptive Particle Swarm Optimization,APSO

下面是一个关于自适应粒子群优化(Adaptive Particle Swarm Optimization,APSO)的博客,希望可以帮助您。提示:以下是本篇文章正文内容,下面案例可供参考在上面的代码中,表示粒子的数量,表示解空间的维度,表示迭代次数,表示优化的目标函数。在__init__方法中,我们初始化了粒子群的位置和速度,并将每个粒子的位置作为其最优解,将其适应度值初始化为正无穷。我们还初始化了学习因子和惯性权重的参数。在run方法中,我们迭代了次,计算每个粒子的适应度值和最优解。

weixin_52026057的博客 9916

跟极限编程创始人Kent Beck学编程

转载于:http://www.youkuaiyun.com/article/2012-09-27/2810441-Programming-Like-Kent-Beck   我、Stig、Krzysztof、Jakub和Kent Beck在2012年的Iterate Code Camp花了一个星期时间一起做了个项目,进行最佳实践性的编程学习。我们想和大家分享一下我们在这个过程中学习到的宝贵经验及教训,以使我

zgmzyr的专栏 1761

时序定江山,功耗写风骨——解读时序库lib文件的奥义【芯片设计 lib文件】

lib库,全称liberty library format file:它是Liberty时序文件的简称,使用 Liberty 语法来编写。它可以通过library compiler/dc转换成.db文件(database),供synopsis家的DC和PT使用,也可以通过spyglass的library compiler来生成sglib文件,供spyglass使用。他们是等价的,但db文件是二进制格式,人类不可读。

LogicYarn的博客 2602

30. 如何使用 SEGW 的 redefine 功能对 SAP 标准 OData 服务进行扩展

SAP 发布了很多标准的 Fiori 应用,可以通过笔者的文章里提到的进行浏览。比如 My Opportunities 就是 SAP CRM 领域的一个 Fiori 应用:下图是 Opportunity 明细页面的 Info 标签页:假设我们想在这些标准字段的末尾增添一个新字段 Created By,用来维护当前 Opportunity 的创建者。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1172

Kent Beck简单设计四条规则

学习Kent Beck简单设计四条规则 运行所有测试 不可重复 表达程序员的意图 尽可能减少方法的数量 首先我们设计开发出来的系统应该是包含测试,只有通过了所有的测试,系统才可以被发布。这就要求我们的测试,是覆盖全面的。全面的测试,必然我们的测试数量是很多的,那么我们在设计程序时,就要做到程序是可测试的,所以说,测试可以引致更好的设计。 不可重复,我们的系统不应该包含...

SuperCastellan的博客 2096

26. 如何给 SAP BTP Cloud Foundry 环境分配运行时内存

摘要:本文解答了SAP BTP Cloud Foundry环境中Space可用内存为0MB的问题。指出Space内存配额取决于Org配额分配,其计算方式为Org总配额减去所有运行中应用实例的内存预留总和。详细解释了SAP BTP的资源分配层级(Global account→Subaccount→Environment→Org→Space),并说明如何通过Global account的Entity Assignments查看Memory Plan配额分配(以GB为单位)。最后建议遇到问题的用户检查Subacc

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1264

Kent Beck:敏捷和极限编程是关于Be Yourself

童年根据发展心理学,童年经历会塑造一个人未来的表现。敏捷宣言发起者大多数在这样的家庭中长大:父亲是自由职业者; 母亲通常是家庭主妇,爱好阅读,有其他艺术或文化相关的嗜好。...

weixin_40768973的博客 581

华为OD新系统机试真题 4.26 -最大化游戏试玩资格分发

华为OD机试新系统真题【最大化游戏试玩资格分发】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD新系统机试 4月26号真题【最大化游戏试玩资格分发】。

qq_45776114的博客 826

[24] cuda 应用之 nppi 实现图像颜色通道变换

[24] cuda 应用之 nppi 实现图像颜色通道变换

yohnyang的博客 343

敏捷史话(十三):我被 Facebook 解雇了——Kent Beck

本文转自敏捷开发。 2011年,Kent Beck 加入了 Facebook 。那时候的他已年过半百,几十年的经验让他自认为非常了解软件行业。在 Facebook 的新手训练营期间,Kent 开始意识到,Facebook 与他所见过的任何公司都不一样。 Facebook 确实在做真正的敏捷,不仅非常灵活,而且时刻在为改变做准备。在 Facebook 训练营结束后,Kent 开始探索 Facebook 的代码库和文化。他发现,Facebook 用于构建和扩展产品的方法,彻底重塑了他对软件工程的信念。 Ken

minjiekaifa的博客 250

山东大学机试试题合集

山东大学机试试题合集

qq_63349644的博客 2622

实现模式-Kent Beck

最近在学习熊节老师的TDD实战营,大师特意推荐的一本提升编程技能的书。10年前的著作,今天读来还是感同身受,可见本书所传承的价值观、原则和77种实现模式,对于今日的开发人员,仍然具有指导作用。 序言中通过对什么是好的代码下了一个定义。所谓好的代码,除了其他所有要求之外,比如可以工作的、性能良好的、没有Bug的代码,还应该清晰准确地传达写作者的想法。 Martin Fowler在《重构:改善既有代码...

总结、分享、交流 2101

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

一起跟大佬提高写代码的姿势!教你编程模式与代码重构 !

Kent Beck 是最早研究软件开发的模式和重构的人之一,是敏捷开发的开创者之一。一起跟大佬学习提高写代码的姿势吧。关于 Kent Beck 与《实现模式》这本书作者简介Kent Be...

程序IT圈 391

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Influential-cs-books项目中的测试驱动开发与重构书籍:构建高质量代码的实践指南

在软件开发领域,编写高质量代码是每个程序员的追求。Influential-cs-books项目作为汇集计算机科学领域最具影响力书籍的资源库,收录了众多关于测试驱动开发(TDD)与重构的经典著作。这些书籍不仅提供了构建可靠软件的方法论,更为开发者提供了提升代码质量的实用指南。 ## 为什么测试驱动开发与重构是程序员必备技能? 测试驱动开发和重构是现代软件开发中确保代码质量的两大核心实践。测试驱动

gitblog_00662的博客 1011

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

什么是重构,什么不是重构

有时候,会有程序员跑到我这里说他们不喜欢某个东西的设计,“我们需要给它来个全面的重构”,来纠正里面的错误。哦,哦。这听起来可不是个好主意。而且这听起来也不是重构…重构(Refactoring)这个词最初由Martin Fowler 和 Kent Beck给下的定义,它是一种修改,使软件的内部结构更容易理解,在不改变软件的可见行为方式前提下使软件更容易变更…它是一种有节制的整理代码、使bug产生几率

曹胜欢 4229

重构改善既有代码的设计《二》重构原则

2.1 何谓重构 1,定义 名词形式:对软件内部结构的一种调整,目的是在不改变软件可观察的行为前提下,提高其可理解性,降低其修改的成本 动词形式:使用一系列重构的手法,在不改变软件可观察行为的前提下,调整其结构 2,目的 使软件更容易被理解和修改。你可以在软件内部做很多修改,但必须对软件的可观察的外部行为只造成很小的变化,或者没有变化,与之相对比的是性能优化,性能优化通常不会改变组件的行为(除了...

qq_42511550的博客 203

重构第二章

​🦖重构(名词):对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。这个定义适用于我在前面的例子中提到的那些有名字的重构,例如提炼函数和以多态取代条件表达式。​ 🦕重构(动词):使用一系列重构手法,在不改变软件可观察行为的前提下,调整其结构。​ 可观测行为是什么?它的意思是,整体而言,经过重构之后的代码所做的事应该与重构之前大致一样。重构之后的代码不一定与重构前行为完全一致。比如说,提炼函数会改变函数调用栈,因此程序的性能就会有所改变;改变函数声明和搬移函数..

豫州码农的博客 163

程序员必须养成良好的代码习惯

<br />养成良好的代码习惯,就是将代码写的漂亮,执行效率也自然就得到了提升。软件开发中包含太多东西了,需求的、设计的、测试的、管理的、文化的、心里的、沟通的,需要大家自己去琢磨。<br />前天在AgileChina2009上听了Fred George的演讲,他说他以前拿自己的代码给Kent Beck看,结果Kent说这代码很垃圾,你去看看我写的Smalltalk best practice patterns吧。然后Fred George就看了这本书并且完全按照书上的要求去做,5年后当他再给Kent看自

wing的专栏 675

肯特纳交易系统_像肯特·贝克一样编程

肯特纳交易系统 我们三个人,即Stig,Krzysztof和Jakub,很高兴在2012年Iterate Code Camp中与Kent Beck一起度过了一周的时间,共同致力于一个项目并学习编程最佳实践。 我们想分享我们学到的宝贵经验,使我们成为更好的程序员(或者至少我们想思考)。 编程风格背后的价值观 我们学到的大多数东西都来自三个基本价值:沟通,简单和灵活性(按重要性顺序)。 我们...

danpu0978的博客 532

什么是重构,什么不是

有时候,一个程序员会来找我,并解释说他们不喜欢某些东西的设计,并且“我们将需要进行大量的重构”才能使其正确。 喔喔 这听起来不好。 而且听起来也不像是重构……。 最初由Martin Fowler和Kent Beck定义的重构是 对软件的内部结构进行了更改,使其更易于理解,并且在不更改其可观察到的行为的情况下进行了更便宜的修改……这是一种清理代码的规范方法,可最大程度地减少引入错误的机会...

danpu0978的博客 234

像工匠一样进行重构--《Refactoring WorkBook》

liangqilang的专栏 107
上一篇: 检索匹配的利器:正则表达式
下一篇: 画一个姑娘陪着你 | 情人节特辑
肖小的人儿
博客等级 码龄12年 29粉丝 56原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值