mirror of
https://github.com/cheetahlou/CategoryResourceRepost.git
synced 2025-11-16 22:23:45 +08:00
mod
This commit is contained in:
53
极客时间专栏/设计模式之美/开源与项目实战:总结课/100 | 如何将设计思想、原则、模式等理论知识应用到项目中?.md
Normal file
53
极客时间专栏/设计模式之美/开源与项目实战:总结课/100 | 如何将设计思想、原则、模式等理论知识应用到项目中?.md
Normal file
@@ -0,0 +1,53 @@
|
||||
<audio id="audio" title="100 | 如何将设计思想、原则、模式等理论知识应用到项目中?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/a4/b1/a4da50a6de2554f82cd8c4f78691acb1.mp3"></audio>
|
||||
|
||||
上一节课,我们对整个专栏的理论知识点做了串讲复习,不知道你掌握得如何?对于上节课总结的重点内容,我希望你能多花点时间搞透彻,对于一些不那么重要的内容,我建议你把专栏当作工具资料,用到的时候随手查阅,再深入学习研究。
|
||||
|
||||
实际上,很多小伙伴反应,虽然理论掌握得差不多,专栏也很贴近实战,每个知识点的讲解都有结合实际的代码案例,并且最后还有集中的项目实战,但落实到自己写代码的时候,还是无法将学到的理论知识很好地应用到其中。今天,我们就再聊一聊,如何将设计思想、原则、模式等理论知识应用到实际的项目开发中。
|
||||
|
||||
话不多说,让我们正式开始今天的学习吧!
|
||||
|
||||
## 吃透理论、先把书读厚再把书读薄
|
||||
|
||||
把理论知识灵活地应用到实践的前提是,对理论有透彻、无盲点的理解。如果我们对理论知识掌握得似懂非懂,在实际软件开发中,遇到跟专栏中讲过的问题类似,我们可以照葫芦画瓢去解决,但是,如果问题背景稍有改变,我们就会比较难联想到对应的理论知识,更难灵活地应用理论去解决。
|
||||
|
||||
要想透彻理解专栏中的每个知识点,一个是要多看几遍,二是要有死磕精神。虽然这两个方法可能已经是老生常谈了,听起来也没有什么高大上的,但从我自身的学习经验来讲,它们确实很有用。
|
||||
|
||||
**书读百遍其义自见。**有的时候,对某个知识点,如果看一遍看不懂,你就硬着头皮多看几遍,或者隔几天再回过头来看一遍,你会发现原来很多看不懂的地方,自然而然就懂了。
|
||||
|
||||
**慢就是快,快就是慢。**专栏涉及的内容很多,但我们花一年把所有的知识点学透彻,实际上是件一劳永逸的事情。这个过程虽然看似漫长,但收益却很多。对比而言,如果你只是为了追求结课速度,花一两个月、甚至一两个礼拜,把课程学完。这看似很快,但实际上收获会很少。
|
||||
|
||||
**先把书读厚,再把书读薄。**反复地学、持续地看。先把书读厚,等到你把所有的知识点都理解透彻,并且在脑子里建立起清晰的知识体系之后,你会发现,实际上专栏的内容也就那么点东西,并不难记忆。前提是你先要花时间把书读厚,然后才能做到把书读薄。
|
||||
|
||||
虽然这里我们讲到书读百遍其义自见,也讲到死磕精神,但是,我必须强调一下,有的时候,对于某个知识点,我们看了很多遍、死磕了很长时间,如果还是没法透彻理解,我们也不要过于钻牛角尖,非得“现在立刻马上就要”把它拿下。我们可以先把这个知识点放一放,先看看后面的内容,隔一段时间,让知识沉淀、消化一下,再回过头来看也是可以的。
|
||||
|
||||
## 在实战中反复学习、模仿和借鉴
|
||||
|
||||
很多人说,理论的知识学了就忘,忘了是不是就等于白学了呢?实际上不是的,起码对于我们这个专栏的内容来说,并非如此。在专栏中,几乎每个知识点,我都结合具体的案例和代码来讲解,目的就是为了让你在实战中学习。所以,你学习的重点不是理论知识,而是跟随我的思维逻辑,学习如何分析代码问题,解决代码问题。通过专栏,经过上百个代码案例的剖析学习,即便理论知识你有可能会忘记,但这种潜移默化的能力锻炼,是不会丢掉的。
|
||||
|
||||
对于新手来说,最好的学习方法之一就是“模仿”。我之前在《数据结构和算法之美》专栏中,也曾经讲过,如果你是一名算法或者编程初学者,自己编写代码实现各种数据结构和算法,可能会比较困难。在这种情况下,你就可以先从“照抄”开始,把所有的代码都抄一遍或者抄几遍,然后再慢慢地过渡到自己去默写。
|
||||
|
||||
对于我们这个专栏来说,如果你项目经验不多,要想把理论一下子就灵活地应用到项目中,实际上这个要求也有点过高了。同样,你也可以先从模仿开始,对于项目中遇到的跟专栏中相似的开发场景,你可以借鉴专栏中的设计思路、代码实现。实际上,除了专栏中的案例之外,我们还有很多借鉴的来源,比如我们前面剖析过的经典开源项目(Spring、MyBatis),还有项目中大牛同事写的代码等等。
|
||||
|
||||
有人为了刷LeetCode、刷算法题,会积累一些算法模板,对于相似的问题,套用算法模板来快速解决。同样的,我们也可以积累设计模板、代码模板,对于相似的功能需求,我们可以套路设计模板、代码模板来解决。比如,在前面讲到的限流框架、灰度组件中,加载配置文件这样一个常用功能的设计和实现,我们就可以抽象成模板。对于其他项目中类似的功能需求,直接套用就可以,不用从零开始设计和实现了。
|
||||
|
||||
## 刻意思考、刻意训练、追求极致
|
||||
|
||||
要想把理论知识应用到项目中,并且做到润物细无声、融会贯通、无招胜有招,我们需要经过漫长的刻意思考和刻意训练。
|
||||
|
||||
拿到一个功能需求的时候,我们先去思考一下如何设计,而不是上来就写代码。写代码时,我们也要时刻思考代码是否遵循了经典的设计思想、设计原则,比如是否足够可扩展、是否满足SOLID原则、可读性如何等等。
|
||||
|
||||
写完代码之后,我们再思考一下,代码是否有进一步优化的空间。做Code Review的时候,看到别人的优秀的代码,我们就去思考一下,有哪些值得借鉴的地方。
|
||||
|
||||
总之,在平时的开发中,我们要刻意的去做这种跟代码质量、代码设计相关的思考训练。时间长了,这种思考就能成为习惯和本能反应,慢慢地,你的代码能力也就不自觉地提高了。
|
||||
|
||||
刻意训练的过程在前期会比较痛苦。为了尽可能写出高质量的代码,为了刻意训练在代码中应用理论知识,原本半天就能写好的代码,可能需要好几天才能完成。在最开始的时候,我建议你把专栏中讲到的经典的设计思想、原则、模式,打印出来贴在电脑旁,每次写代码的时候,对照着每个知识点,一个一个去审视代码。
|
||||
|
||||
跟前面讲到的花很多时间把理论知识搞透彻的道理一样,刻意训练虽然在前期需要投入更多的时间和精力,但也是一件一劳永逸的事情。等到训练到一定程度之后,你就会发现,在不依赖这个知识点列表的情况下,你开始不自主地考虑代码质量问题、设计问题,不经意写出的代码,就完全符合高质量代码的要求了,而且,写出好的代码并不会花费更多的时间了。相反,如果不愿意为刻意训练付出时间和精力,每次写代码都马马虎虎,代码质量永远都提高不了,也永远都达不到灵活应用理论知识到项目中。
|
||||
|
||||
我经常说,多花点心思和时间把一段代码写好、优化到极致,比写十段凑活能用的代码,对提高代码能力更有效。实际上,这就好比刷LeetCode算法题,对于一些经典算法的经典题目,我们一定要刻意地多花点时间搞清楚,死磕一下。虽然死磕的过程很痛苦,可能会花掉你很多时间,但一旦搞明白之后,其他类似的题目都可以很快解决。相反,如果看到不会的问题,连思考都不思考,就去看答案,那做十道题,也还是没有太多长进,看到题目不看答案还是写不出来。
|
||||
|
||||
## 课堂讨论
|
||||
|
||||
关于如何将设计思想、原则、模式等理论知识应用到项目中,除了我分享的这些经验之外,你还有哪些经验可以分享给大家呢?另外,经过这么长的学习和训练,在自己参与的项目中,你是否开始关注代码质量问题,代码能力是否有提升了呢?
|
||||
|
||||
欢迎留言和我分享你的想法,如果有收获,也欢迎你把这篇文章分享给你的朋友。
|
||||
73
极客时间专栏/设计模式之美/开源与项目实战:总结课/99 | 总结回顾:在实际软件开发中常用的设计思想、原则和模式.md
Normal file
73
极客时间专栏/设计模式之美/开源与项目实战:总结课/99 | 总结回顾:在实际软件开发中常用的设计思想、原则和模式.md
Normal file
@@ -0,0 +1,73 @@
|
||||
<audio id="audio" title="99 | 总结回顾:在实际软件开发中常用的设计思想、原则和模式" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/7d/9f/7d6c2c5408e8885c314510f7cdeffa9f.mp3"></audio>
|
||||
|
||||
到今天为止,理论部分和实战部分都已经讲完了,整个专栏也接近尾声了。我这里用两节课的时间,带你一块复习一下前面学到的知识点。跟前面的讲解相对应,这两节课分别是针对理论部分和实战部分进行回顾总结。
|
||||
|
||||
今天,我先来带你回顾一下整个专栏的知识体系。我们整个专栏围绕着编写高质量代码展开,涵盖了代码设计的方方面面,主要包括面向对象、设计原则、编码规范、重构技巧、设计模式这五个部分。我们就从这五个方面,带你一块把之前学过的知识点串一遍。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/f3/d3/f3262ef8152517d3b11bfc3f2d2b12d3.png" alt="">
|
||||
|
||||
话不多说,让我们正式开始今天的学习吧!
|
||||
|
||||
## 面向对象
|
||||
|
||||
相对于面向过程、函数式编程,面向对象是现在最主流的编程范式。纯面向过程的编程方法,现在已经不多见了,而新的函数式编程,因为它的应用场景比较局限,所以大多作为面向对象编程的一种补充,用在科学计算、大数据处理等特殊领域。
|
||||
|
||||
它提供了丰富的特性,比如封装、抽象、继承、多态,有助于实现复杂的设计思路,是很多设计原则、设计模式等编程实现的基础。
|
||||
|
||||
在面向对象这一部分,我们要重点掌握面向对象的四大特性:封装、抽象、继承、多态,以及面向对象编程与面向过程编程的区别。需要特别注意的是,在平时的面向对象编程开发中,我们要避免编写出面向过程风格的代码。
|
||||
|
||||
除此之外,我们还重点学习了面向对象分析(OOA)、设计(OOD)、编程(OOP)。其中,面向对象分析就是需求分析,面向对象设计是代码层面的设计,输出的设计结果是类。面向对象编程就是将设计的结果翻译成代码的过程。
|
||||
|
||||
在专栏中,我们重点讲解了面向对象设计这一部分。我们可以把面向对象设计分为四个环节:划分职责并识别出有哪些类、定义类及其属性和方法、定义类之间的交互关系、组装类并提供执行入口。我们通过几个项目案例,带你实战了一下设计过程,希望你能面对开发需求的时候,不会无从下手,做到有章可循,按照我们的给出的步骤,有条不紊地完成设计。
|
||||
|
||||
在面向对象这一部分,我们还额外讲到了两个设计思想:基于接口而非实现的设计思想、多用组合少用继承的设计思想。这两个设计思想虽然简单,但非常实用,应用它们能让代码更加灵活,更加容易扩展,所以,这两个设计思想几乎贯穿在我们整个专栏的代码实现中。
|
||||
|
||||
## 设计原则
|
||||
|
||||
在专栏的最开始,我们总结了一套评判代码质量的标准,比如可读性、可维护性、可扩展性、复用性等,这是从代码整体质量的角度来评判的。但是,落实到具体的细节,我们往往从是否符合设计原则,来对代码设计进行评判。比如,我们说这段代码的可扩展性比较差,主要原因是违背了开闭原则。这也就是说,相对于可读性、可维护性、可扩展性等代码整体质量的评判标准,设计原则更加具体,能够更加明确地指出代码存在的问题。
|
||||
|
||||
在专栏中,我们重点讲解了一些经典的设计原则,大部分都耳熟能详。它们分别是SOLID原则、DRY原则、KISS原则、YAGNI原则、LOD原则。这些原则的定义描述都很简单,看似都很好理解,但也都比较抽象,比较难落地指导具体的编程。所以,学习的重点是透彻理解它们的设计初衷,掌握它们能解决哪些编程问题,有哪些常用的应用场景。
|
||||
|
||||
SOLID原则并非一个原则。它包含:单一职责原则(SRP)、开闭原则(OCP)、里氏替换原则(LSP)、接口隔离原则(ISP)、依赖倒置原则(DIP)。其中,里氏替换和接口隔离这两个设计原则并不那么常用,稍微了解就可以了。我们重点学习了单一职责、开闭、依赖倒置这三个原则。
|
||||
|
||||
单一职责原则是类职责划分的重要参考依据,是保证代码”高内聚“的有效手段,是面向对象设计前两步(划分职责并识别出有哪些类、定义类及其属性和方法)的主要指导原则。单一职责原则的难点在于,对代码职责是否足够单一的判定。这要根据具体的场景来具体分析。同一个类的设计,在不同的场景下,对职责是否单一的判定,可能是不同的。
|
||||
|
||||
开闭原则是保证代码可扩展性的重要指导原则,是对代码扩展性的具体解读。很多设计模式诞生的初衷都是为了提高代码的扩展性,都是以满足开闭原则为设计目的的。实际上,尽管开闭原则描述为对扩展开放、对修改关闭,但也并不是说杜绝一切代码修改,正确的理解是以最小化修改代价来完成新功能的添加。实际上,在平时的开发中,我们要时刻思考,目前的设计在以后应对新功能扩展的时候,是否能做到不需要大的代码修改(比如调整代码结构)就能完成。
|
||||
|
||||
依赖倒置原则主要用来指导框架层面的设计。高层模块不依赖低层模块,它们共同依赖同一个抽象。深挖一下的话,我们要把它跟控制反转、依赖注入、依赖注入框架做区分。实际上,比依赖倒置原则更加常用的是依赖注入。它用来指导如何编写可测试性代码,换句话说,编写可测试代码的诀窍就是应用依赖注入。
|
||||
|
||||
KISS、YAGNI可以说是两个万金油原则,小到代码、大到架构、产品,很多场景都能套用这两条原则。其中,YAGNI原则表示暂时不需要的就不要做,KISS原则表示要做就要尽量保持简单。跟单一职责原则类似,掌握这两个原则的难点也是在于,对代码是否符合KISS、YAGNI原则的判定。这也需要根据具体的场景来具体分析,在某个时间点、某个场景下,某段代码符合KISS、YAGNI原则,换个时间点、换个场景,可能就不符合了。
|
||||
|
||||
DRY原则主要是提醒你不要写重复的代码,这个倒是不难掌握。LOD原则又叫最小知道原则,不该有直接依赖关系的类之间,不要有依赖;有依赖关系的类之间,尽量只依赖必要的接口。如果说单一职责原则是为了实现“高内聚”, 那这个原则就是为了实现“松耦合”。
|
||||
|
||||
## 编码规范
|
||||
|
||||
编码规范很重要,特别是对于初入职、开发经验不多的程序员,遵从好的编码规范,能让你写出来的代码至少不会太烂。而且,编码规范都比较具体,不像设计原则、模式、思想那样,比较抽象,需要融入很多个人的理解和思考,需要根据具体的场景具体分析,所以,它落地执行起来更加容易。
|
||||
|
||||
虽然我们讲了很多设计思想、原则、模式,但是,大部分代码都不需要用到这么复杂的设计,即便用到,可能也就只是用到极个别的知识点,而且用的也不会很频繁。但是,编码规范就不一样了。编码规范影响到你写的每个类、函数、变量。你编写每行代码的时候都要思考是否符合编码规范。
|
||||
|
||||
除此之外,编程规范主要解决代码的可读性问题。我个人觉得,在编写代码的时候,我们要把可读性放到首位。只有在代码可读性比较好的情况下,我们再去考虑代码的扩展性、灵活性等。一般来说,一个可读性比较好的代码,对它修改、扩展、重构都不是难事,因为这些工作的前提都是先读懂代码。
|
||||
|
||||
不过,专栏中只是总结了一些最常用的、最能明显改善代码质量的编码规范,更进一步的学习你可以参考《重构》《代码大全》《代码整洁之道》等书籍,或者参看你公司内部的编码规范。
|
||||
|
||||
## 重构技巧
|
||||
|
||||
重构作为保持代码质量不腐化的有效手段,利用的就是面向对象、设计原则、设计模式、编码规范这些理论。在重构的过程中,我们用代码质量评判标准来评判代码的整体质量,然后对照设计原则来发现代码存在的具体问题,最后用设计模式或者编码规范对存在的问题进行改善。
|
||||
|
||||
持续重构除了能保证代码质量不腐化之外,还能有效避免过度设计。有了持续重构意识,我们就不会因为担心设计不足而过度设计。我们先按照最简单的思路来设计,然后在后续的开发过程中逐步迭代重构。
|
||||
|
||||
在专栏中,我们还对重构进行了粗略的分类,分为大规模高层次的重构和小规模低层次的重构。不管哪种重构,保证重构不出错,除了熟悉代码之外,还有就是完善的单元测试。
|
||||
|
||||
## 设计模式
|
||||
|
||||
如果说设计原则相当于编程心法,那设计模式相当于具体的招式。设计模式是针对软件开发中经常遇到的一些设计问题,总结出来的一套解决方案或者设计思路。我们用设计原则来评判代码设计哪里有问题,然后再通过具体的设计模式来改善。相对于其他部分来讲,设计模式是最容易学习的,但也是最容易被滥用的,所以,我们在第75讲中还专门讲了如何避免过度设计。
|
||||
|
||||
经典的设计模式有23种,分三种类型:创建型、结构型和行为型。其中,创建型设计模式主要解决“对象的创建”问题,结构型设计模式主要解决“类或对象的组合”问题,行为型设计模式主要解决“类或对象之间的交互”问题。
|
||||
|
||||
虽然专栏中讲到的设计模式有很多种,但常用的并不多,主要有:单例、工厂、建造者、代理、装饰器、适配器、观察者、模板、策略、职责链、迭代器这11种,所以,你只要集中精力,把这11种搞明白就可以了,剩下的那12种稍微了解,混个眼熟,等到真正用到的时候,再深入地去研究学习就可以了。
|
||||
|
||||
## 课堂讨论
|
||||
|
||||
很多人反映学了就忘,对于上面的这些知识点,你记住了百分之多少呢?你是怎么克服学了就忘的问题的呢?
|
||||
|
||||
欢迎留言和我分享你的想法,如果有收获,也欢迎你把这篇文章分享给你的朋友。
|
||||
Reference in New Issue
Block a user