架构师训练营 1 期 - 第二周总结(vaik)
本周概要
本周的重点是面向对象编程的本质和原则,首先从编程历史演进分析,编程的方式是如何一步步演化到今天的面向对象编程大行其道的,接着分析了那些糟糕代码的特点和坏处,然后就逐步讲解了面向对象编程的四个最重要也最基本的原则:开放封闭、依赖倒置、里氏替换、单一职责接口隔离。最后通过智慧老师自己的案例反应式编程框架 Flower,讲述了如何应用面向对象的基本原则和设计模式实现开发框架。
面向对象编程的本质和未来
我的思考:编程语言的发展:从解决领域问题出发,从简单到复杂,从粗犷到精细,高层基于底层抽象,越来越科学,用更优化的工具解决越来越复杂、越来越抽象领域问题。
编程语言的实质
编程的目的:用计算机解决现实世界的问题
编程的过程即:在计算机所能理解的“模型”(解空间)和现实世界(问题空间)之间,建立一种联系。
编程语言是一种“抽象”的机制,问题是对“谁”来抽象:
我的理解:
领域问题---》 某个问题,Boss 的一个 idea,一个故事,一个 PPT...
模型---》产品经理的迭代需求+架构师的架构设计
软件系统--》 项目经理+开发+测试+运维一起整出来的东东
抽象的种类
机器代码和汇编语言:对基础机器进行抽象
非结构化的高级语言(如 Basic,Fortan 等):对计算处理逻辑抽象
结构化的程序设计:开始对问题领域进行一定程序的抽象
面向对象的程序设计:直接表达问题空间的元素
编程方法的演进
汇编语言-》高级语言-》结构化程序-》面向对象程序-》问题领域
编程的核心要素
人(劳动者)
计算机(劳动工具)
客观业务领域(劳动对象)
什么是面向对象编程
万物皆为对象
程序是对象的集合,它通过发送消息告诉彼此所要做的
每个对象都有自己的由其他对象所构成的存储
每个对象都拥有其类型
某一特定类型的所有对象都可以接收同样的消息
以上是第一个成功的面向对象语言 Smalltalk 的描述,C++和 Java 等后期面向对象语言,都在此基础上定义
什么是对象
状态:表明每个对象可以有自己的数据
行为:表明每个对象可以产生行为
标识:表明每个对象都区别于其它的对象(唯一的地址)
面向对象编程的三要素
封装性(Encapsulation)
隐藏实现细节(访问控制)
定义接口
继承性(Inheritance)
IS-A 关系
HAS-A 关系
接口重用
多态性(Polymorphism)
后期绑定(虚函数)
向上转形(UP Casting)
对象互换
子类实现父类或接口的抽象方法,程序使用抽象父类或接口编程,运行期注入不同的子类,程序就表现出不同的形态,是为多态。
面向对象编程和面向对象分析
面向对象编程不是使用使用对象的语言进行编程,而是利用多态特性进行编程。
面向对象分析是将客观世界,即编程的业务领域进行对象分析。
充血模型和贫血模型
领域驱动设计 DDD
面向对象设计目的原则
面向对象设计目的
强内聚、低耦合,从而使用系统
易扩展
更强壮
可移植
更简单
面向对象设计原则
为了达到上述设计目标,有人总结出了多种指导原则
“原则”是独立于编程语言的,甚至可以用于非面向对象的编程语言中
设计模式
设计模式是解决某一类问题的能用解决方案。是语言中立,贯彻了面向对象设计的原则
23 种基本设计模
创建模式
行为模式
结构模式
更细分领域总结多种设计模式
并发编程模式
JavaEE 模式
etc.
框架(framework)
框架是用来实现某一类应用的结构性程序,是对某一类架构方案的可复用的设计与实现
框架结构定义程序的边界和范围以及规范
简化应用开发者的工作
实现多种设计模式,使得开发者轻松设计出结构良好的程序
不同领域的框架
windows 编程的 MFC 框架
Java 为它的 GUI(图形用户界面)开发了 AWT 框架
各种开源框架:MyBatis,Spring 等
Web 服务器也是框架:Tomcat
框架 VS 工具
框架调用应用程序代码
应用程序代码调用工具
架构师用框架保证架构落地
架构师用工具提高开发效率
我的思考:
面向对象编程的目标是实现高内聚、低耦合的,易扩展、健壮的可复用程序,这样的描述当然没什么问题,但什么样是高内聚,低耦合、易扩展、健壮,这几个概念其实挺抽象笼统的。理解起来挺模糊的。
高内聚:方法到类到模块到子系统的功能职责单一清晰,没有多余,只做好一件事
低耦合:方法到类到模块到子系统对外部的依赖越少耦合就越低
易扩展:能方便简单添加新的功能,应对需求变化,而不影响原有代码的功能
可复用:通过单一职责原则,接口隔离原则,以及继承来实现功能的可复用
什么是坏代码
我理解的坏代码特点
方法或类的组织混乱没有条理,多种功能纠缠在一起
命名随意不规范,易容引起岐义
注释随意,没有讲清楚关键点
到外是相同复制粘贴的代码,没有统一提出公共的功能方法
晦涩 - 代码难以理解
我理解的好代码特点
他人阅读代码的感觉是愉悦的、易懂的
简单清晰有条理的
注释恰到好处
方法、类、模块功能职责单一,没有多余不必要的
开放封闭原则(OCP)
开放封闭原则:对功能扩展开放,对修改关闭,是面向对象设计最重要的原则。
我的理解:修改这个词应该是相对的,但代码出现 Bug,或者需求有大的变化时,修改修复是难以避免的。这里的修改是指通过设计能够避免直接修改,或者通过扩展可以实现的功能就不要修改原来的代码,这要求对未来的需求变化有前瞻性的预判,需要有很强的编程能力和丰富的开发经验,初学者比较难以理解透彻这个原则的。
依赖倒置原则(DIP)
DIP-Dependency Inversion Principle
高层模块不依赖于低层模块,大家都依赖于抽象
抽象不依赖实现,而实现依赖抽象
DIP 倒置了什么
模块或包的依赖关系
开发顺序和职责
系统的层次化
高层决定低层
高层被重用
我的理解:
依赖倒置原则是框架设计最核心的原则。这里有另外两个概念不得不提,一个是控制反转,一个依赖注入。我们需要清晰依赖倒置、控制反转、依赖注入这三者的联系和区别。
控制反转:即依赖方不需要关心被依赖对象的创建,只需要使用传进来的被依赖对象即可。IoC 结合面向接口编程,可以使得编写的程序扩展性更强。它是一种设计模式,它遵循了依赖倒置的原则。
依赖注入:是实现控制反转一种手段,在 Spring 中通过配置文件 xml,annotation-based 或 java-based 的方式来实现。
里氏替换原则(LSP)
OCP 的关键在于抽象,而抽象的威力在于多态和继承,一个正确的继承要符合什么要求呢?答案是 Liskov 替换原则。
若每个类型 T1 的实例对旬 o1,都存在一个类型 T2 的对象 o2,使得在所有针对 T2 编写的程序 P 中,用 o1 替换 o2 后,程序 P 的行为功能不变,则 T1 是 T2 的子类型。
简言之:子类型(subtype)必须能够替换掉它们的基类型(base type)。
我的理解:LSP 是对行为的一种抽象规范,它实现了灵活的扩展,功能的可复用,也是实现 OCP 原则的方式。
单一职责接口隔离(SRP)
又称为“内聚性原则(cohesion)”,即:一个模块的组成元素之间的功能相关性。
一个类,只能有一个引起它的变化的原因。
什么是职责?
单纯谈论职责,每个人都会得出不同的结论。
一个职责是一个变化的原因。
我的问题和思考:
问题:在实际项目中如何判断“引起一个变化的原因”来划分规范好方法和类的功能,来遵循单一职责原则?
思考:类的功能都体现在方法函数上,方法是粒度最小的功能体现,我觉得首先要规范类的功能,然后再确定每个功能的方法,然后再审视,每个方法的必要性和合理,每个方法的参数输入和返回的合理性。
案例讲解:反应式编程框架 Flower
框架介绍
Flower 是一个构建在 Akka 上的反应式微服务框架,开发者只需要针对每一个细粒度的业务功能开发一个 Service 服务,并将这些 Service 按照业务流程进行可视化编排,即可得到一个反应式系统
框架设计目标
开发工程师无需学习函数式编程即可开发反应式系统
纯消息驱动,可以实现更灵活的扩展(事件溯源、分布式事务,限流)
更好的性能意味着用更少的机器就可以满足系统的并发压力
消息驱动天然限流特性使系统在过高并发和部分组件失效的情况下保障系统不会崩溃
Flower Web 开发兼容 Spring
框架是如何设计实现
Flower 通过 Akka 的 Actor 实现异步:
核心模块设计:
Flower 的分布式异步微服务解决方案
版权声明: 本文为 InfoQ 作者【行之】的原创文章。
原文链接:【http://xie.infoq.cn/article/2375c995af077d769ec9e0944】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论