架构师训练营 - 第二周学习总结
编程语言的实质
编程的目的是:用计算机来解决现实世界的问题。
编程的过程是:在计算机所能理解的“模型”(解空间)和现实世界(问题空间)之间,建立一种关系。
编程语言是一种“抽象”的机制。
面向对象编程的三要素(特征)
封装性
继承性
多态性
面向对象编程与面向对象分析
面向对象编程不是使用面向对象的编程语言进行编辑,而是利用多态特性进行编辑。
面向对象分析是将客观世界,即编程的业务领域进行对象分析。
充血模型与贫血模型
领域驱动设计DDD
面向对象设计的目的和原则
面向对象设计的目的:强内聚,低耦合,从而使系统:
易扩展——易于增加新的功能
更强壮——不容易被粗心的程序员破坏
可移植——能够在多样的环境下运行
更简单——容易理解、容易维护
面向对象设计的原则:
开闭原则:面向扩展开放,面向修改关闭
依赖倒置原则:实现尽量依赖抽象,不依赖具体实现
里氏替换原则:父类存在的地方,子类可以替换
单一职责原则:每个类应该专注于一件事情
接口隔离原则:应当为每个客户端提供尽可能小的单独的接口,而不是提供大的总的接口
迪米特法则:一个软件实体应当尽可能少的与其他实体类发生相互作用
组合/聚合复用原则:尽量使用组合/聚合达到复用,尽量少用继承
设计模式
设计模式是用于解决某一种问题的通用的解决方案。设计模式贯彻了设计原则。
框架
框架是用来实现某一类应用的结构性的程序,是对某一类架构方案可复用的设计与实现。
框架vs工具
框架调用应用程序代码;应用程序代码调用工具。
架构师用框架保证架构落地;架构师用工具提高开发效率。
软件设计的“臭味”
僵硬——不易改变(很难对系统进行改动,因为每个改动都会迫使许多对系统其他部分的改动)
脆弱——只想改变A,结果B被意外破坏(对系统的改动会导致系统中和改动的地方无关的许多地方出现问题)
牢固性(不可移植)——不能适应环境的变化(很难解开系统的纠结,使之成为一些可在其他系统中重用的组件)
粘滞性(导致误用的陷阱)——做错误的事比做正确的事更容易,引诱程序员破坏原有的设计(面临一个改动的时候,开发人员常常会发现会有多种改动的方法。有的方法会保持系统原来的设计,而另外一些则会破坏设计,当那些可以保持系统设计的方法比那些破坏设计的方法更难应用时,就表明设计具有高的粘滞性,做错误的事情就很容易)
晦涩——代码难以理解(很难阅读、理解,没有很好地表现出意图)
不必要的复杂性(过渡设计)——设计中包含有不具任何直接好处的基础结构
不必要的重复(copy-paste代码)——设计中包含有重复的结构,而该重复的结构本可以使用单一的抽象进行统一
OOD原则一:开闭原则(OCP)
对于扩展是开放的
对于更改是封闭的
简言之:不需要修改软件实体(类、模块、函数等),就应该能实现功能的扩展
开闭原则的关键是抽象。
OOD原则二:依赖倒置原则(DIP)
高层模块不能依赖低层模块,而是大家都依赖于抽象;
抽象不能依赖实现,而是实现依赖抽象。
DIP倒置了什么:
模块或包的依赖关系
开发顺序和职责
软件的层次化
高层决定低层
高层被重用
依赖倒置原则的要点:高层模块定义一个接口供低层模块实现,而不是低层模块实现之后抽象出接口。在依赖倒置里面抽象是属于高层模块,由高层模块决定低层模块的开发。
依赖倒置原则也是框架设计的原则。
框架的核心:好莱坞原则(倒转了层次依赖关系:有框架来调用我们的业务代码,而不是我们去调用框架)
好莱坞原则:Don't call me, I'll call you.好莱坞原则是用在系统的高层组件与底层组件之间,高层组件不应该直接调用底层组件,而是从容器获取。
OOD原则三:里氏替换原则(LSP)
里氏替换原则是用来解决继承的问题。
通俗的说法:在一个程序中,使用父类的场景都可以使用子类替换,这个继承就是合理的。里氏替换原则不仅仅是要求父类和子类满足IS-A的关系,同时在应用场景中需要子类可以替换父类,父类的行为能够完全适配子类。
从契约的角度看待LSP
LSP要求,凡是使用基类的地方,一定也适用于其子类。
从语法的角度看:
子类一定得拥有基类的整个接口。
子类的访问控制不能比基类更严格。
从更广泛的意义来看,子类的“契约”不能比基类更“严格”
如何解决LSP问题
最简单的办法:提取共性到基类
使用组合代替继承
建议优先使用组合
OOD原则四:单一职责原则(SRP)
一个类,只能有一个引起它的变化的原因。
什么是职责?一个职责是一个变化的原因。
OOD原则五:接口隔离原则(ISP)
不应该是强迫客户程序依赖它们不需要的方法。主要实现手段是多继承。
ISP 和 SRP 的关系:
ISP 和 SRP 是相关的,都和“内聚性”有关。
SRP 指出应该如何设计一个类——只能有一种原因才能促使类发生改变。
ISP 指出应该如何设计一个接口——从客户的需要出发,强调不要让客户看到他们不需要的方法。
总结
编程史、编程方法的演进史使自己了解到编程的本质是抽象,由此产生了面向对象。为了遵循面向对象设计的目的和原则,设计模式诞生。为了针对某一类应用的场景,提供这一类应用的解决方案,简化开发者的工作,框架应运而生。
清楚知道了框架和工具的区别,在开发中需要明确这两个之间的差异。
原先对于面向对象的设计原则有一些知道,不能够很好的区分。老师详细讲了面向对象的设计原则,并且结合案例,打开了我的思维,虽然有些地方还不能很好的体会,在以后的工作中需要更加深入的思考。
判断一个设计好不好需要在软件开发的上下文环境中去判断。软件开发的上下文环境就是不定的需求变更。
版权声明: 本文为 InfoQ 作者【陈琪霖】的原创文章。
原文链接:【http://xie.infoq.cn/article/5ebe34c7f047135bd3dda45bd】。文章转载请联系作者。
评论