课程笔记:极客时间—设计模式之美
设计模式学习导读
为什么要学习设计模式?
- 应对面试中的设计模式相关问题
- 告别写被别人吐槽的烂代码
- 提高复杂代码的设计和开发能力
- 让读源码、学框架事半功倍
- 为你的职场发展做铺垫
有些能力,要早点锻炼;有些东西,要早点知道;有些书,要早点读。这样在你后面的生活、工作、学习中,才能一直发挥作用。不要等到好多年后,看到了,才恍然大悟,后悔没有早点去学、去看。
设计模式作为一门与编程、开发有着直接关系的基础知识,是你现在就要开始学习的。早点去学习,以后的项目就都可以拿来锻炼,每写一行代码都是对内功的利用和加深,是可以受益一整个职业生涯的事情。
从哪些维度评判代码质量的好坏?
写出好代码的前提:能够辨别代码写得”好“还是”烂“。
评价代码质量好坏的认知:
- 需要综合各种因素来进行评价。
- 不同的评价维度也并不是完全独立的,有些是具有包含关系、重叠关系或者可以互相影响的。
- 各种评价维度也并不是非黑即白的。
- 对一段代码的质量评价,常常有很强的主观性。
7个最常用的代码评价标准
可维护性(Maintainability)
什么是代码的可维护性?
“维护”主要包括修改bug、修改老的代码、添加新的代码之类的工作。
“代码易维护”是指:在不破坏原有代码设计、不引入新的bug的情况下,能够快速地修改或者添加代码。
“代码不易维护”是指:修改或者添加代码需要冒着极大的引入新bug的风险,并且需要花费很长的时间才能完成。
可维护性的重要性:对于一个项目来说,维护代码的时间远远大于编写代码的时间。工程师大部分的时间可能都是花在修修bug、改改老的功能逻辑、添加一些新的功能逻辑之类的工作上。
如何量化可维护性?
代码可维护性的好坏是一个比较主观的评价标准,如:
- 代码的可读性好、简洁、可扩展性好,就会使得代码易维护;
- 更细化地讲,如果代码分层清晰、模块化好、高内聚低耦合、遵从基于接口而非实现编程的设计原则等等,那就意味着代码易维护;
- 代码的易维护性还跟项目代码量的多少、业务的复杂程度、技术复杂程度、文档是否全面、团队成员的开发水平等诸多因素有关;
可读性(Readability)
代码的可读性应该是评价代码质量最重要的指标之一。
如何评价一段代码的可读性?
- 代码是否符合编程规范
- 命名是否达意
- 注释是否详尽
- 函数是否长短合适
- 模块划分是否清晰
- 是否符合高内聚低耦合
- ……
一个主观的评价手段:code review。如果你的同事可以轻松地读懂你写的代码,那说明你的代码可读性很好;如果同事在读你写的代码时,有很多疑问,那就说明你的代码可读性有待提高了。
可扩展性(Extensibility)
代码的可扩展性也是一个评价代码质量非常重要的标准。
它表示我们的代码应对未来需求变化的能力。
代码的可扩展性是指:我们在不修改或少量修改原有代码的情况下,通过扩展的方式添加新的功能代码。
灵活性(Flexibility)
如何理解灵活性?
灵活性是一个挺抽象的评价标准,要给它下个定义很难。我们可以通过下面的几个场景来思考什么是灵活性。
- 场景1:当我们添加一个新的功能代码的时候,原有代码已经预留好了扩展点,我们不需要修改原有的代码,只要在扩展点上添加新的代码即可。(易扩展、灵活)
- 场景2:当我们要实现一个功能的时候,发现原有代码中,已经抽象出了很多底层可以复用的模块、类等代码,我们可以拿来直接使用。(易复用、灵活)
- 场景3:当我们使用某组接口的时候,如果这组接口可以应对各种使用场景,满足各种不同的需求。(易用、灵活)
简洁性(Simplicity)
KISS原则:”Keep It Simple, Stupid”
代码简洁、逻辑清晰,也就意味着易读、易维护。
一个偏见:认为简单的代码没有技术含量。实际上,思从深而行从简,真正的高手能云淡风轻地用最简单的方法解决最复杂的问题。这也是一个编程老手跟编程新手的本质区别之一。
可复用性(Reusability)
代码的可复用性可以简单地理解为,尽量减少重复代码的编写,复用已有的代码。
如何提高代码的可复用性?
- 使用继承、多态
- 使用单一职责原则
- 解耦、高内聚、模块化
- 应用DRY设计原则
可测试性(Testability)
代码可测试性的好坏,能从侧面上非常准确地反映代码质量的好坏。
代码的可测试性差,比较难写单元测试,那基本上就能说明代码设计得有问题。
如何才能写出高质量的代码?
如何写出高质量的代码,也就等同于,如何写出易维护、易读、易扩展、灵活、简洁、可复用、可测试的代码。
要写出满足这些评价标准的高质量代码,我们需要掌握一些更加细化、更加能落地的编程方法论。包括:
- 面向对象设计思想
- 设计原则
- 设计模式
- 编程规范
- 重构技巧
编程方法论
面向对象
面向对象因为其具有丰富的特性(封装、抽象、继承、多态),可以实现很多复杂的设计思路,是很多设计原则、设计模式编码实现的基础。
面向对象编程的相关知识点:
- 面向对象四大特性:封装、抽象、继承、多态
- 面向对象编程与面向过程编程的区别和联系
- 面向对象分析、面向对象设计、面向对象编程
- 接口与抽象类的区别以及各自的应用场景
- 多用组合少用继承的设计思想
- 面向过程的贫血模型和面向对象的充血模型
设计原则
设计原则是指导我们代码设计的一些经验总结。
对于每一种设计原则,我们需要掌握它的设计初衷、能解决哪些编程问题,有哪些应用场景。
几个常用的设计原则:
- SOLID原则——SRP单一职责原则
- SOLID原则——OCP开闭原则
- SOLID原则——LSP里氏替换原则
- SOLID原则——ISP接口隔离原则
- SOLID原则——DIP依赖倒置原则
- DRY原则、KISS原则、YAGNI原则、LOD原则
设计模式
设计模式是针对软件开发中经常遇到的一些设计问题,总结出来的一套解决方案或者设计思路。
设计模式相对于设计原则来说,没那么抽象,而且大部分都不难理解,代码实现也并不复杂。这一块的学习难点是了解它们都能解决哪些问题,掌握典型的应用场景,并且懂得不过度应用。
23中经典的设计模式:
创建型模式
常用的有:单例模式、工厂模式(工厂方法模式、抽象工厂模式)、建造者模式
不常用的有:原型模式
结构型模式
常用的有:代理模式、桥接模式、装饰器模式、适配器模式
不常用的有:门面模式、组合模式、享元模式
行为型模式
常用的有:观察者模式、模板模式、策略模式、职责链模式、迭代器模式、状态模式。
不常用的有:访问者模式、备忘录模式、命令模式、解释器模式、中介模式。
对于常用的设计模式,我们要多花点时间理解掌握。对于不常用的设计模式,我们只需要稍微了解即可。
编程规范
编程规范主要解决的是代码的可读性问题。
编程规范相对于设计原则、设计模式,更加具体、更加偏重代码细节。
可直接看经典书籍:《重构》、《代码整洁之道》
代码重构
软件开发是一个不停迭代的过程,因此没有一劳永逸的设计。随着需求的变化,代码的不停堆砌,原有的设计必定会存在这样或那样的问题。
重构是软件开发中非常重要的一个环节。持续重构是保持代码质量不下降的有效手段,能有效避免代码腐化到无可救药的地步。
重构的工具包括:
- 设计思想
- 设计原则
- 设计模式
- 编程规范
重构相关的知识点
- 重构的目的、对象、时机、方法
- 保证重构不出错的技术手段:单元测试和代码的可测试性
- 两种不同规模的重构:大重构(大规模高层次)和小重构(小规模低层次)
学习重构,不仅仅要掌握一些重构技巧、套路,更重要的是建立持续重构的意识,把重构当作开发的一部分,融入到日常的开发中。
五者之间的联系
- 面向对象编程因为其具有丰富的特性,可以实现很多复杂的设计思路,是很多设计原则、设计模式等编码实现的基础。
- 设计原则是指导我们代码设计的一些经验总结,对于某些场景下,是否应该应用某种设计模式,具有指导意义。
- 设计模式是针对软件开发中经常遇到的一些设计问题,总结出来的一套解决方案或者设计思路。应用设计模式的主要目的是提高代码的可扩展性。从抽象程度来说,设计原则比设计模式更抽象,设计模式更加具体、更加可执行。
- 编程规范主要解决的是代码的可读性问题。编程规范相较于设计原则、设计模式,更加具体、更加偏重代码细节、更加能落地。持续的小重构依赖的理论基础主要就是编程规范。
- 重构作为保持代码质量不下降的有效手段,利用的就是面向对象、设计原则、设计模式、编码规范这些理论。