写点什么

架构师训练营 - 第二章课程总结 - 软件设计 & 面向对象

用户头像
而立
关注
发布于: 2020 年 06 月 16 日
架构师训练营-第二章课程总结-软件设计&面向对象

第二章的课程内容还是很丰富的,感谢智慧老师的讲解。

框架&工具

首先,课程讲解了框架和工具的区别。

在一个软件系统当中,框架负责调用开发人员编写的业务代码来实现整体系统运行。工具被业务代码调用来完成特定的功能。

调用还是被调用是框架和工具的一个重要区分。

比如,一个基于springboot开发的web系统。springboot 就是框架,它负责调用开发人员编写的控制器、service等代码来实现系统运行。系统中负责记录日志的组件log4j,就是一个工具,开发人员使用log4j这个工具来完成记录日志的功能。

这里引入一个架构师的定义,如果一个人在团队当中负责开发框架、工具,或者负责决定引入什么框架、什么工具(就是技术选型),那么这个人所担负的就是架构师的职责。

框架和工具都是架构师工作时的重要媒介。

架构师利用框架来落地自己的系统设计,使用工具来加快研发效率。



软件设计的目的&软件的坏味道

一般,我们认为软件设计的目的,是为了使软件达到“强内聚,松耦合”。达到这个目的的软件有如下几个标准:

1·易扩展:易于增加新功能。

2·更强壮:不容易被粗心的程序员破坏,就是说新增功能不容易引入bug。

3·可移植:能够在多样的环境运行。

4·更简单:易于理解、容易维护。



相反不好的软件一般有如下几种“坏味道”:

1·僵硬:添加一个功能,只能通过修改原有代码的方式来实现。

2·粘滞:一个系统的历史包袱比较严重。实现一个好的设计比实现一个坏的设计更加困难,难以重构改善。

3·脆弱:增加一个功能,或是修改一个功能,很容易引起另一个地方出现异常。

4·不可移植:程序很难适应环境的变化。

5·不必要的复杂:设计中包含不具备任何好处的基础结构。当程序员预测需求的变更,并在软件中放置了那些处理潜在变化的代码时,容易出现这种问题。

6·不必要的重复:设计中包含重复结构,而该重复的结构本该使用单一抽象来统一。

7·过度设计:程序员为了应付可能的需求变更,想象了很多设计元素加入到系统当中。

8·牢固性:功能不容易被移植,很难被复用。

9·晦涩:难以阅读,代码难以理解。

10·导致误用的陷阱:做错误的事比做正确的事容易。系统会引诱程序员破坏原有设计。



上述都是系统中可能出现的坏味道,如果你的系统中出现了上述的症状,那么说明系统的设计已经开始腐化变坏了。( 画外音:好像我们公司的系统大部分问题都存在(*/ω\*) )



应对软件坏味道的最核心思想就是:抽象!



面向对象的六大原则

1·单一职责原则:接口应该只负责一个功能,不应该把多个功能集中在一个接口中,要保持接口的功能内聚。

2·理氏替换原则:凡是可以使用父类的地方,都可以使用子类替换,而调用方代码无需调整。这个原则要求,子类只能扩展父类,不能影藏或者覆盖父类,是一个相对比较严格的原则。

3·开闭原则:接口应该对扩展开放,对修改关闭。

4·接口隔离原则:接口应该尽可能的小,和单一职责原则有一定的相似性。

5·依赖倒置原则:程序应该依赖接口,而不是依赖具体的实现。

6·迪米特原则:类对其他的类了解的越少越好,可以降低类之间的耦合。



为什么这些原则可以拯救坏味道的代码?

一开始接触面向对象的原则,经常摸不着头脑。为什么要这么做,作为程序员已经习惯了new一个对象直接拿来用,既然new一个对象就能直接调用完成功能,为什么还要用接口?

这里我试着举个例子说明一下:

我们有一个电商系统,每天承载着几千万的交易,底层服务之间的消息通信一部分是通过消息队列完成。系统早期,消息队列是基于redis实现。



后来因为消息数量越来越多,使用redis作为消息队列需要越来越多的内存,导致成本增加,同时redis的早期队列实现没有消息的ack机制,不能保证消息消费的可靠性,所以团队决定更换为基于阿里云的mns队列。

那这种情况下,如果我们的业务程序直接依赖与redis队列的实现类,那所有使用消息队列的地方都需要调整代码,可想而知这是多么大的工作量啊!而且调整所带来的系统风险将没法估量!

这个时候,如果我们的业务程序不是直接依赖redis的具体消息队列实现,而是依赖一个消息队列的抽象接口,那么更换的动作就是只需要再实现一个基于mns的消息队列实现类,该类实现了 消息队列抽象 接口,业务系统不需要做任何的代码,只需要向业务系统注入不同的消息队列实现就能解决了上述问题。

开发的范围变成了,开发一个具体的消息队列实现类,并且调整框架的注入,测试团队的工作范围变成了针对这个消息队列具体实现类的单点测试。

整体的工作量和风险都处于可控范围内。



在这个例子中,如果业务系统直接依赖redis的消息队列具体实现类,那么这个系统就是僵硬且脆弱的。

更换为基于抽象的消息队列接口,系统就符合了面向对象的开闭原则、依赖倒置原则。

这个过程中,将redis的消息队列实现,抽象为消息队列接口尤为重要。有了这个稳定的抽象,业务类也才具有了稳定的可能。



用户头像

而立

关注

还未添加个人签名 2018.01.25 加入

还未添加个人简介

评论

发布
暂无评论
架构师训练营-第二章课程总结-软件设计&面向对象