记录个人学习,感悟,吐槽
为什需要软件架构设计原则
为了不让自己的成果被别人说成屎山(扩展、维护) 【软件设计原则】工作中经常被分配去写一个功能模块,可能是基础功能模块(消息触达、文件生成),也有业务的模块,如:SSO,商品管理,订单管理,促销管理等
当开开心心完成产品一期需求,一切完美上线后,产品提出四期五期需求有重大修改,现在的代码设计很难从容的完成需求。给予的时间不充裕,无法完成重构,只能通过兼容来实现需求。慢慢的项目变成一座屎山,自己维护很痛苦,别人维护更痛苦。如果在项目开始初期,从架构设计上考虑到软件的健壮性,可读性,灵活性 易扩展,易复用,易用等等……那该是多么美妙的一件事。
软件设计原则
原则一 开闭原则(Open-Closed Principle)
对扩展开放,对修改关闭
该原则强调的是用抽象构建框架,用实现扩展细节,可以提高系统的可复用行和可维护性。开闭原则是面相对象设计只能怪最基础的设计原则,它指导我们如何建立稳定,灵活的系统,列入版本更新,我们尽可能的不修改源码,有可以实现功能。
在开发会员系统的时候,需要根据会员等级提供不同特权,使用该思想会使得功能扩展变得非常清楚容易。
eg: base -> level1 extends leve1 -> level2 extends level1
原则二 依赖倒置原则(Dependence Iversion Principle)
高层模块不依赖低层模块,二者都依赖其抽象
抽象不该依赖与细节,细节应该依赖与抽象。通过依赖倒置,可以减少类与类之间的耦合性,提高系统的稳定性,提高代码的可读性与可维护性,并能够降低修改程序所造成的风险。
依赖倒置原则(控制反转)在spring框架的基础思想
原则三 单一职责原则(Simple Responsibility Principle)
不要存在多于一个导致类变更的原因
该原则主要目的是用于解耦。假设我们有一个类负责两个职责,一单发生变更,修改期中一个职责的逻辑实现代码,有可能导致另一个职责功能发生故障。设计当初需要考虑某个类的职责问题。这样的设计,可以降低类的复杂度,提高类的可读性,功能的可维护性,降低变更引起的风险。
类如:消息触达中的消息推送,推送给小米手机与推送给华为手机。
IA,IB,AbsPush > MiPush extend AbsPush imp IA, HuaWeiPush extend AbsPush
imp IA,IB
原则四 借口隔离原则(Interface Segregation Principle)
多个单一职责接口,不要使用一个总接口
客户端应该依赖它不需要的接口,这个原则指导我们在设计接口的时候应当注意一下几点:
- 一个类对另一个类的依赖应当建立在最小接口之上
- 建立单一接口,不要建立太臃肿的接口
- 经量细化接口,接口中的方法应当尽量少(不是越少越好)
原则五 迪米特原则 (Law of Demeter LoD)
一个对象应该对其他对象保持最少的了解
经量降低类与类之间的耦合度,迪米特原则主要强调:只喝朋友交流,不喝陌生人说话。出现在成员变量,方法的输入,输出参数中的类都可以成为成员朋友类,而出现在方法体内部的类不属于朋友类。
当 a 通过 b 获取 c 的信息,a 在代码中不要与 c出现任何关联。
原则六 里氏替换原则(Liskov Substitution Principle, LSP) 如果每一个类型为 T1 的对象 O1,都有类型为 T2 的对象 O2,使得以 T1 定义的所有程序 P 在所有的对象 O1 都替换成 O2 时,程序 P 的行为都没有发生变化,那么 T2 是 T1 的子类型。
这个定义是抽象,刚刚看起来非常简洁易懂,但是理解需要深度,学习的如下。
可以理解为一个软件实体的如果适用于父类肯定实用其子类,所有引用父类的地方必须透明的使用其子类的对象,子类对象能够替代父类对象,而程序逻辑不变,根据这个理解,引申含义为:子类可以扩展父类的功能,但不能改变父类的原有功能。
- 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法
- 子类可以增加自己的特有方法
- 当之类的方法重载父类的方法时,方法的前置条件(方法的输入/入参)要比父类的输入参数更加宽松
- 档子类的方法实现父类的方法时(重写/重载或者实现父类的抽象方法),方法的后置条件(返回值)要比父类严格或与类一样
本文主要知识来自于 谭勇德《Spring 5 核心原理》