写点什么

架构师训练营第 1 期 -Week2 - 框架设计学习总结

用户头像
鲁小鲁
关注
发布于: 2020 年 09 月 27 日

这周的学习收获很多,以前不明白的几个面向对象设计原则,在老师的讲解下豁然开朗。很佩服老师的学习方法,对知识掌握的深度。


上周讲了什么

上周主要讲了架构师的职责,必备能力,架构方法,4+1 视图(逻辑视图、开发视图、物理视图、过程视图、场景视图)以及实现 4+1 视图的主要攻击 UML(统一建模语言)。UML 视图中的部署图、组件图、组件时序图、用例图、状态图、活动图(类似流程图)、合作图、类图、对象图、包图等 10 种图。

这周讲了什么?

这周讲的是设计原则(开闭原则,里氏替换原则、依赖倒置原则、单一职责原则、接口隔离原则,迪米特原则(这个没说))

第一节:编程语言的历史(面向机器编程、面向劳动者编程、面向领域问题编程),面向对象语言能更好的映射现实世界的领域问题,更好的反应事物之间的交互规律。面向对象的目标:高内聚、低耦合(高内聚,低耦合的系统易于扩展、更强壮、可移植、更简单)。面向对象的 3 个重要特点:继承,封装,多态,其中多态是最核心的特点。基于这个目标的设计原则(六个设计原则)、设计模式(面向对象设计模式分 3 大类,共 23 种,其他并发编程有其他设计模式,设计模式是永久解决某一问题的通用解决方案),以及基于这些设计原则和设计模式构建出框架(框架是实现某一类应用的结构性程序,是对某一类框架方案可复用的设计与实现)。框架完成了真个系统骨干或程序运行的最基础的运行流程,关键构建了整个系统的整体结构。框架与工具的区别(框架调用应用程序,应用程序调用工具,框架保证架构落地,保证整体的程序运行流程和整体结构,工具提高开发效率)


第二节:软件设计的臭味:僵硬、脆弱、不可移植、导致无用的陷阱、晦涩、过渡设计(僵化性、脆弱性、牢固性、粘滞性、不必要的复杂性、不必要的重复性)。程序首先要先给人看,在给机器执行


第三节:开闭原则(OCP-Open/closed principle)对扩展是开发的,对更改是关闭的,不需要修改软件实体(类、函数、模块),就应该实现功能的扩展。实现开闭原则的关键在于抽象软件工程的上下文是需求是在不断变化的,软件设计要能适应不断变化的需求。适配器模式、策略模式、观察者模式、装饰器模式都能很好的体现 开闭原则。

第四章:依赖倒置原则(DIP - Dependency Inversion Principle)高层模块不应该依赖低层模块,而是大家都依赖抽象,抽象不能依赖实现,而是实现依赖抽象。DIP 倒置了依赖的层次,改变了开发的先后顺序。DIP 是框架设计的指导原则,核心设计技巧。Don't call me, I'll call you.

第五节:里氏替换原则(LSP - Liskov Principle)子类必须能够替换掉他们的基类,LSP 是动态的看继承关系是否合理,在应用场景中看子类能不能替换父类,这样的分析更加坚定直接,也更符合继承的期望。静态的分析(is-a)未必是合理的。对象的核心特征在于其行为,LSP 从对象的行为上判断继承是否合理,更加合理。从契约角度看 LSP,从 Java 的语法看 LSP。解决不合理继承的两种方法:提取共性生成一个新父类和继承改为组合(减少不必要的继承,优先改为组合),继承的优点和缺点。可能违反 LSP 的征兆。里氏替换原则是一个关键继承的设计原则

第六节:单一职责原则(SRP - )又被称为“内聚性原则”,一个模块的组成元素直接的功能相关性,将它与引起一个模块改变的作用力相连。一个类(模块,函数),只能有一个引起它变化的原因单一职责原则是类设计指导原则。什么是职责(一个职责是一个变化的原因),内聚性的原则,相同的功能聚合在一起,相同的职责聚合在一起,这个职责应该单一。违反 SRP 原则,程序会变得脆弱、不可移植。改进的方案是拆解类。接口隔离原则(ISP -  Interface Segregation Principle)不应该强迫客户程序依赖他们不需要的方法。ISP 是接口设计的指导原则,ISP 和 SRP 的关系(都和内聚性相关),接口隔离实现手段时多继承。适配器在接口隔离中经常使用。胖接口的两种改进方法:适配器或多继承。《敏捷软件开发原则、模式与实践) 罗伯特森马丁:对于一个软件开发而言,要想实现敏捷的软件开发,并不在于敏捷的软件过程保证,当然过程保证也重要,重要的是在用设计本身是敏捷的。

第七节:反应式编程要解决的是线程被阻塞,导致的现在占据资源,不能释放资源,同时不能向下运行,导致系统资源耗尽,服务崩溃的问题。解决方法是**异步操作**。细细想来 Golang 也是解决这个问题的。go 的 csp 机制是 channle。Flower 的 csp 机制是 Actor(maibox)。go 中函数是一等公民,可以做函数式编程。flower 反应式编程框架的设计(通过接口限制住 service 的格式,应用开发中只要实现这些 service)和实现。

对设计原则的理解

软件开发的三要素:人、机器、领域问题。从编程语言的发展历史上看,初期是面向机器编程,这个时期的编程方式有:纸袋打孔、汇编语言。这个时期代码都是一个个指令,基本上谈不上内聚性。之后是面向人编程,这个时期的编程语言有:Basic 等语言,这些语言给开发带来了便利,但是系统规模的增大,导致了爆发了软件危机。《人月神话》这本书就是说的这个时期的事情。软件的低内聚带来了可复用、可维护,开发成本上的问题。现代的编程语言,面向对象编程,其实是面向领域问题编程。面向对象要解决的是系统的高内聚、低耦合问题。


面向对象更符合我们对问题的理解,也更符合我们对编程的认知。可以很方便的将现实世界的问题,映射成一个个对象。能更好的建立模型。编程的本质是通过层层的抽象,建立层层的映射,最终变成解决现实问题的系统。面向对象能更方便将领域问题的建成对象模型。也能更好的适应需求的变更。


面向对象语言目标是:高内聚、低耦合。它的 3 个特点是:继承、封装、多态。在这个的基础上提炼出了 6 个设计原则:开闭原则、里氏替换原则、依赖倒置原则、单一职责原则、接口隔离原则、迪米特原则。在 6 个设计原则的基础上,归纳出 23 种设计模式,设计模式分为:创建型、行为型、结构行三大类。另外对应不用的应用场景(领域)还有其他的设计模式(比如并发编程的模式)。


内聚和耦合是对立的。就行太极中的两个阴阳鱼,一阴一阳。阴盛则阳衰,阳盛则阴衰。内聚性高,则代码的复用性高,扩展性好,更强壮,容易阅读,可移植性好,重复代码少。相反耦合性高,则代码不易复用,扩展性差,容易出错,不易阅读,难以移植,重复代码多。内聚性高,相关代码聚合到一起,耦合性高,不相干代码聚到一起。内聚和耦合是功能相关性的指标。内聚和耦合是面向流程编程中,模块划分的指导思想。在面向对象中就变成了类设计的指导思想。


继承抽象出相关代码到父类,差异的代码在子类实现。这样提高了父类的内聚性。这样父类的代码可以复用,可以通过子类扩展不同的功能,子类更强壮。模板方法模式是继承的典型实例。


封装将可复用的功能提炼为一个类,隐藏类内部实现细节,通过一个供外部调用的方法(类间通过这个方法通信)。降低了对象间的耦合性,提高了内聚性。降低了改错代码的概率,代码也更容易扩展(只要供外部的方便不变),将错误封印在很小的范围内,适配器模式就是封装的典型实例。


多态是面向对象编程的一个重要的特点。有了多态,面向对象编程才表现出纷繁复杂的特点。各种编程技巧,都是围绕着多态展开的。多态的典型表现是重写和重载。子类重写父类方法,实现自己特有的逻辑,一组类可以实现一个接口。一个类内部可以重载多个同名方法,处理不同的业务逻辑。


通过多态内部结构不同的一组对象,可以享有相同的外部接口,通过一个公用类,它们可以用相同的方式调用。这样代码的扩展性大大的提高,可以做到在不修改原有功能的情况下,开发新的功能。同时代码也更强壮,更容易阅读,更简单,更容易阅读和维护,复用性也更好。策略模式、命令模式、观察者模式等是多态的典型实例。


里氏替换原则: 指导对象间继承关系设计。


依赖倒置原则:指导框架设计。


单一职责原则:指导对象的设计


接口隔离原则:指导接口的设计


开闭原则:在软件设计时,考虑到需求的不断变更,做到可以不修改的情况下天,实现需求变更。能做到开闭原则的设计,都是高内聚,低耦合的架构设计。


23 种设计模式体现的设计原则

待补充

软件框架设计的核心-依赖倒置原则


框架就是高层模块,框架定义自己的接口(也就是抽象,这些接口是高层模块定义的),根据抽象去设计和开发框架。使用框架去开发业务逻辑,这里就是低层模块,框架就可以根据接口去调用低层模块的应用程序。


依赖倒置原则,是框架设计的指导原则,是框架设计的核心技巧。它使架构师不纠结与程序设计的细节之中。架构师可以通过框架,框清代码,实现架构的落地


用户头像

鲁小鲁

关注

博学而笃志,切问而近思。 2018.09.29 加入

Go开发

评论

发布
暂无评论
架构师训练营第 1 期 -Week2 - 框架设计学习总结