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 教你编程模式与代码重构相关推荐

  1. java编程代码大全_掌握Java编程技巧,代码重构

    代码重构在不改变软件系统外部行为的前提下,改善它的内部结构,通过调整程序代码改善软件的质量.性能,使其程序的设计模式和架构更趋合理,提高软件的扩展性和维护性. 代码重构目标 持续纠偏和改进软件设计 随 ...

  2. 22种代码味道(Martin Fowler与Kent Beck)

    Martin Fowler在Refactoring: Improving the Design of Existing Code(中译名:<重构--改善既有代码的设计>)一书中与Kent ...

  3. 模型描述的关系模式_你的项目该用哪种编程模式?

    哎,一个1970年的问题,争论了快50年了,还有那么多引战的. 客观一点讲,对于玩过不少语言.大体上几种模式都上过项目的我来讲,几种编程模式的本质问题都是管理问题. 01 面向过程,本质是" ...

  4. 推荐:5款可以教你编程的游戏

    推荐:5款可以教你编程的游戏 2015-10-12 11:03 编辑: suiling 分类:游戏开发 来源:sixrevisions 0 3349 编程HTML5游戏 招聘信息: iOS开发工程师 ...

  5. 如何通过 Scratch 教小朋友编程思维?

    寒假的时候,我带着自己的小孩学 Scratch,希望通过这种图形化的语言来训练他的编程思维.开学之后,很多事情需要处理,所以拖到现在才写总结.希望对大家有所启发. 在介绍如何做这件事情之前,先介绍一个 ...

  6. C#异步编程模式IAsyncResult概述

    C#异步编程模式IAsyncResult概述 IAsyncResult 异步设计模式通过名为 BeginOperationName 和 EndOperationName 的两个方法来实现原同步方法的异 ...

  7. 智能合约的核心思想、语法重点、编程模式、示例、规范及架构

    目录 智能合约简介 智能合约例子 合约编程模式COP 合约语法 重难点 限制和规范 合约架构 什么是智能合约 一个智能合约是一套以数字形式定义的承诺(promises) ,包括合约参与方可以在上面执行 ...

  8. Java多线程编程模式实战指南(三):Two-phase Termination模式--转载

    本文由本人首次发布在infoq中文站上:http://www.infoq.com/cn/articles/java-multithreaded-programming-mode-two-phase-t ...

  9. 老手是这样教新手编程的

    周末, 轻松一下. 酷壳: http://collshell.cn/ 本文来自: http://coolshell.cn/?p=2420 comp.lang.c全球最大的C语言新闻组,其Google的 ...

  10. 一些实用的编程模式 | Options模式

    今天开个新系列,讲一些实用的编程模式,每个编程模式学完后,都能马上在实战中应用起来,让我们写出更富表达力.易维护.好扩展.优雅亿点点的代码. 这些编程模式的示例我会用Go来演示,但其实这些模式大多与语 ...

最新文章

  1. 白鹭引擎开发飞机大战详尽教程(四控制飞机移动)
  2. vue.js2.0 新手开发_VueJs2.0建议学习路线
  3. IDEA Java Web 推送Tomcat
  4. 多源计算机培训,多源数据汇聚的多流形学习算法研究
  5. leetcode344. 反转字符串 史上最简单力扣题
  6. ps -ef |grep
  7. [唐诗]正月十五日夜-苏味道
  8. python机器学习库xgboost使用调参
  9. 10大漏洞评估和渗透测试工具
  10. c++缺省值 缺省参数
  11. PC解决电子签名的方法
  12. 绿色数据中心基础设施建维服务认证
  13. mysql neq_neq、eq的用法,thinkphp框架下的
  14. dCas9-ROS1——靶向去甲基化的捷径
  15. eclipse 使用maven打包 包含非java文件时报错
  16. SQL 给时间字段增加一固定时间
  17. 搭建DEM企业管理器
  18. 介绍国产的PHP MVC框架:FleaPHP
  19. 清华大学计算机音乐,清华大学2018年毕业歌《告别之前》发布!每个告别都等得到再见...
  20. 工程伦理(2021春)课后习题全部答案

热门文章

  1. 关于Unity中unitypackage文件的图标显示及打开方式异常问题的解决
  2. 计算机专业班级网站,班级网站毕业论文.doc
  3. 解决Layui表格头部工具栏事件绑定失效,上传文件按钮失效问题
  4. google浏览器缓存文件在哪里
  5. 举个栗子~Tableau 技巧(220):使用「集」实现不同分析维度图表的数据联动
  6. 高考数学九大知识模块的易错考点【修正版】【知识体系辅导】
  7. 翟菜花:从风流到下流,杜蕾斯新文案为何被人口诛笔伐?
  8. 《英语语法新思维初级教程》学习笔记(五)形容词
  9. 排序算法之python实现(上)
  10. php判断是否submit,submit什么意思 php提交表单时判断 if$_POST[submit]与 ifisset$_POST[submit] 的区别...