一、软件设计六大原则
单一职责原则
- 永远不应该有多于一个原因来改变某个类
- 理解:对于一个类而言,应该仅有一个引起它变化的原因
- 应用:如果一个类拥有了两种职责,那就可以将这个类分成两个类
举例:
登录页面(验证用户名和密码),其中验证用户名和密码不应该写在同一个函数中,应拆分成两个方法去实现。
开放封闭原则:
- 软件实体扩展应该是开放的,但对于修改应该是封闭的
- 理解:对扩展开放,对修改封闭。可以去扩展类,但不要去修改类
- 应用:当需求有改动,尽量用继承或组合的方式来扩展类的功能,而不是直接修改类的代码
举例:
登录页面(在验证用户名和密码的基础上添加对图片验证码的验证,只有图片验证码验证通过后才可以验证密码),如果直接修改验证密码函数功能,则需付出大量时间对原有功能进行验证。针对这种情况,可以对原有功能进行封装,通过返回true或者false,判断是否要进行接下来的流程,最大程度上减少对原有功能的侵入。
里式替换原则:
- 理解:父类一定能够被子类替换
注:里式替换原则在使用面向对象的时候,会着重注意到,但在使用函数式编程的时候,对于里式替换原则关注度则没那么高。
接口隔离原则:
- 一个类与另一个类之间的依赖性,应该依赖于尽可能小的接口
- 理解:不要对外暴露没有实际意义的接口。用户不应该依赖它不需要的接口
- 应用:当需要对外暴露接口时,如果是非必要对外提供,尽量删除
注:什么是接口?在程序设计中通过接口去预设一部分类型来限定一个类的实现。
依赖倒置原则:
- 高层模块不应该依赖于低层模块,它们应该依赖于抽象。抽象不应该依赖于细节,细节应该依赖于抽象。
- 理解:应该面向接口编程,不应该面向实现类编程
- 并不是说,所有的类都要有一个对应的接口,而是说,如果有接口,那就尽量使用接口来编程吧
最少知识原则:
- 只与你最直接的对象交流
- 理解:低耦合、高内聚
- 应用:做系统设计时,尽量减小依赖关系
二、其他设计原则
组合/聚合复用原则
- 当要扩展类的功能时,优先考虑使用组合,而不是继承
- 该原则在23种经典设计模式中频繁使用
- 如:代理模式、装饰模式、适配器模式
注:在ES6中,通过装饰模式扩展类的新功能。
无环依赖原则
- 场景:当A模块依赖于B模块,B模块依赖于C模块,C依赖于A模块,此时将出现循环依赖;
- 在设计中避免该问题,可通过引入”中介者模式” 解决
共同封装原则
- 应该将易变的类放在同一个包里,将变化隔离出来
- 该原则是“开发-封闭原则”的衍生
共用重用原则
- 如果重用了包中的一个类,那么也就相当于重用了包中的所有类,我们要尽可能减小包的大小
好莱坞原则
- Don’t call me, I’ll call you.
- “控制反转”(或称为”依赖注入”)
- 不需要主动创建对象,而是由容器帮我们来创建并管理这些对象
注:inversify 这个库可以帮我们主动创建对象。
不要重复你自己
- 不要让重复的代码到处都是,要让它们足够的重用,所以要尽可能地封装
保持它简单与傻瓜
- 保持系统界面简洁,功能实用,操作方便
高内聚与低耦合
- 模块内部需要做到内聚度高,模块之间需要做到耦合度低
关注点分离
- 将一个复杂的问题分离为多个简单的问题,然后逐个解决(注:通常所说的分而治之)
- 难点:如何进行分离
你不需要它
- 不要一开始就把系统设计得非常复杂,不要陷入”过度设计”的深渊
- 让系统足够简单,而又不失扩展性
三、软件设计分层
系统级架构 => 应用级架构 => 模块级架构 => 代码级架构,难度逐层递减。
3.1 系统级架构
系统级架构涉及到的内容:
- 应用在整个系统内涉及到主要内容是与后台服务如何通信,与第三方系统如何集成;
- 设计前端首要条件需了解前端系统与其他系统之间的关系,其中关系包括业务关系和协助机制;
- 设计后端只需要规定与后台数据传递的机制,这种机制包括API设计规则、访问授权的一个开放标准(OAuth)跳转token的验证、数据传递cookie等;
- 前端与后端的关系考虑的主要因素:前后端分离的架构设计。前后端分离架构指的是如何实施技术决策,如用户鉴权、API接口管理和设计、API文档管理、Mock的使用、BFF(服务于前端的后端,nodejs)、是否需要服务端渲染等;
微前端是将多个前端应用以某种形式结合在一起进行应用,旨在解决单体应用在一个相对长的时间跨度下,由于参与的人员、团队的增多、变迁,从一个普通应用演变成一个巨石应用(Frontend Monolith)后,随之而来的应用不可维护的问题。对于微前端而言,它的整体地位比较特殊:
- 在一个系统内微前端是应用间的架构方案。但是对于整体应用而言,微前端则是一种系统间等架构方案;
- 微前端的两种实现形式:
- 单实例:同一个时刻,只有一个子应用被展示,子应用具备一个完整的应用生命周期;
- 多实例:同一时刻可展示多个子应用。通常基于url的变化来做子应用的切换;
- 通常使用 Web Components 方案来做子应用封装,子应用更像是一个业务组件而不是应用;
3.2 应用级架构
应用级架构可以看作是系统级架构的细化,需考虑单个应用与其他外部应用的关系,如微服务架构下多个应用的协作、数据交换等。应用级架构使用场景如下:脚手架、模式库(比如说方法库、UI库)、设计系统(应用级架构的内部系统设计)。
3.3 模块级架构
模块级架构可以理解为我们在开始业务编码之前进行设计,这个过程也可称为迭代的过程。
3.4 代码级架构
对于代码级架构,讲得更多的是规范与原则。代码级架构内容有如下:
- 开发流程
- 代码质量以及改善
- 规范而非默契
注:
- 在开发中,要注意可维护性、可扩展性
- 简单的代码可维护性高;越是写的抽象的代码越难维护;
参考资料