工程化-微前端架构
概念
软件设计原则
单一职责原则
永远不应该有多余一个原因来改变某个类。
开放封闭原则
软件实体扩展应该是开放的,但是对于修改应该是封闭的。
即可以扩展类,但是不要去修改类,如使用组合或继承的方式扩展类的功能。
里氏替换原则
父类一定能够被子类替换。
最少知识原则
只与当前最直接的对象交流。
即低耦合,高内聚。
应用:做系统设计时,尽量减小依赖关系。
接口隔离原则
一个类与另一个类之间的依赖性,应该依赖于尽可能小的接口。
即不要对外暴露没有实际意义的接口。用户不应该依赖它不需要的接口。
应用:当需要对外暴露接口时,如果是非必要对外提供,尽量删除。
依赖倒置原则
高层模块不应该依赖于低层模块,它们应该依赖于抽象。抽象不应该依赖于细节,细节应该依赖于抽象。
即应该面向接口编程,不应该面向实现类编程。
其他附加软件设计原则
组合/聚合复用原则
当要扩展类的功能时,有限考虑使用组合,而不是继承。
如:代理模式、装饰模式、适配器模式。
无环依赖原则
循环依赖:A 模块依赖于 B 模块,B 模块依赖于 C 模块,C 模块依赖于 A 模块。
在设计中避免循环依赖问题,可以通过引入“中介者模式”解决。
共同封装原则
应该将易变的类放在同一个包里,将变化隔离出来。
基于“开放-封闭原则”。
共同重用原则
如果重用了包中的一个类,那么也就相当于重用了包中的所有类,我们要尽可能减小包的大小。
好莱坞原则
“控制反转”(或称为“依赖注入”)
不需要主动创建对象,而是由容器帮我们来创建并管理这些对象。
不重复原则
不要让重复的代码到处都是,要让它们足够的重用,所以要尽可能地封装。
保持简单
保持系统界面简洁,功能使用,操作方便。
高内聚与低耦合
模块内部需要做到内聚度高,模块之间需要做到耦合度低。
关注点分离
分而治之。
将一个复杂的问题分离为多个简单的问题,然后逐个解决。
难点:如何进行分离(分离的颗粒度、原则等)。
精益原则
初始设计时不要陷入“过度设计”的深渊,过度设计会带来付出大于收益的问题。
让系统足够简单,而又不失扩展性。
软件设计分层
按照架构的分类,难易程度逐层递减。
系统级架构
应用在整个系统内,如与后台服务如何通信,与第三方系统如何集成。
设计前端首要条件:了解前端系统与其他系统之间的关系。
关系包括:业务关系和协作机制。
设计后端:只需要规定与后台数据传递的机制。
包括:api 设计规则,访问授权的一个开放标准(OAuth)跳转 token 的验证,数据传递 cookie 等。
前后端的关系考虑的主要因素是:前后端分离的架构设计。
前后端分离架构其实是如何实施技术决策,用户鉴权、API接口管理和设计、API文档管理、Mock的使用、BFF(服务于前端的后端,nodejs),是否需要服务端渲染等。
应用级架构
可以看作是系统级架构的细化。
单个应用与其他外部应用的关系,如微服务架构下多个应用的协作,数据交换等。
实现形式
脚手架
模式库,如 UI 库等
设计系统
模块级架构
是开始业务编码之前进行设计,称为迭代。
代码级架构
规范与原则。
内容
开发流程
代码质量以及改善
规范而非默契
在系统整体开发过程中的注意事项:
- 可维护性、可扩展性、可重用性
- 简单的代码可维护性高;越是写的抽象的代码越难维护
架构设计的质量
系统的稳定性
当一个实际的系统处于一个平衡的状态时,如果收到外来作用的影响时,系统经过一个过渡过程仍然能够回到原来的平衡状态,称这个系统就是稳定的,否则称系统不稳定。
架构设计的基石。
可以更好的实现自我修复。
系统的健壮性(鲁棒性)
计算机软件在输入错误、磁盘故障、网络过载或有意攻击情况下,能否不死机、不崩溃,就是该软件健壮性的具体表现。
即一个系统的容错能力强,运行不易被干扰,安全性好。
度量标准
- 一个软件可以从错误的输入判断出正确合理的输入。
- 一个软件可以正确的运行在不同环境下
- 一个软件能够检测自己内部的设计或者编码错误,并得到正确的结果
架构质量的衡量
- 拓展性
- 维护性
- 可管理
- 高可用(故障修复、容灾、降级、熔断)
日常开发过程中的架构质量
- 理解难度
- 接入依赖的成本
- 崩溃率和错误率的指标
- 开发效率
- 错误上报和信息收集等功能
架构开发
架构师分类
系统架构师
从系统的维度,负责整体系统的架构设计。
主要时基础服务和各系统间协调,着眼全局。
比如关注负载,可靠性,伸缩,扩展,整体项目切分,缓存应用等方面的基础架构设计。
应用架构师
从应用程序的维度,负责某个应用的技术架构,主要偏业务系统。
关注理解业务,梳理模型,设计模式,接口,数据交互等方面。
业务架构师
从业务流程的维度,关注某一个行业、业务的领域分析,获取领域模型,最终获得系统的模型。
也可以叫做业务领域专家、行业专家、产品咨询师、资深顾问。
技术前期准备
技术选型:社区氛围、发展规模、未来发展趋势、与当前团队的契合度、执行成本、维护和迁移成本、执行效率等内容的调研和报告。
充分调研每一项技术可能带来的利与弊。
最大程度上预测架构设计中的缺陷,以防止问题的发生。
技术优化
在架构发展过程中,可能会存在一些有悖于当前架构设计的实现,造成了架构发展阻塞,所以需要进行架构优化,使架构设计的适应性更高。
架构优化
架构不是一蹴而就的,在业务发展过程中,架构也在不断演进。
对架构设计进行实时调优,使架构优化成为常态化。
通过不断调整架构实现,改进初始架构中涉及的不足,补足短板。
技术债务填补
技术债务产生的原因
- 开发过程中因为时间紧迫导致的实现不合理。
- 暂时没有想到更好的方式实现而妥协的版本。
- 架构设计前期没有考虑到的细节。
- 不合理的交互设计,导致技术实现复杂。
- 旧功能文档缺失,无正确扩展、修改和兼容旧功能,导致上线后问题剧增。
技术债务后果
- 修复变重构。
- 小的技术债务不做偿还,最后会演变成一场大规模的重构工作,导致产出不高。
- 影响开发速度。
- 技术债务的存在导致整体开发需要兼容的点过多,影响开发效率,极大影响上线速度,导致整体项目迭代缓慢,失去核心竞争力。
技术填补解决方案
优秀的架构设计是基础。
必须能够有效处理当前需求可预见的情况,对于未知的、可能出现的特殊情况,很小的改动就能解决问题。(预留接口,不做多余功能实现)
根据当前的业务,进行合理的项目拆分,尽量的代码解耦合。
必须有日志模块,操作日志,错误日志,业务日志等。
良好的技术培训和传帮带能力。
让每一位开发者可以从更深一层次理解自己所需要实现的功能。
从最开始的代码规范、到熟悉业务、最后再到编写文档。
充分的技术方案可避免一部分技术债务的产生。
技术方案是充分理解需求之后所能产出的对需求理想的实现方式,必要性不言而喻。
不同工程师之间可以相互 review。
提升对修复技术债务重要性的认知。
善于发现和定期处理一些技术债务。勇于发现系统中的技术债务。
预防架构崩溃
日志记录,如:操作日志,错误日志,业务日志等。
用户行为抓取 -> 争取在最新时间获取到用户操作链条。
解决存量问题 -> 技术债务。
遏制新增 -> 减少新增问题的概率。
对脏数据进行兜底和检验。
单元测试。
崩溃报警。
自动化测试。
更广的灰度触达。
性能优化体系。
系统重构
重构:对软件内部结构的一种调整。目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。
实现方式:使用一系列重构手法,在不改变软件可观察行为的前提下,调整其结构。
重构理念:运用大量微笑且保持软件行为的步骤,一步步达成大规模的修改。
当发现一个现有架构体系已经不能满足当前迭代速度的时候就需要进行重构工作。
重构流程:
- 确定问题点,确定重构功能和范围
- 旧架构设计和逻辑梳理
- 稳定性保证
- 性能保证
- 需求过程中的冲突问题
微前端架构
在一个系统内微前端是应用间的架构方案。
在多个应用之间,微前端则是一种系统间架构方案。调度所有子应用。
微前端是将多个前端应用以某种形式结合在一起进行应用。
微前端解决的问题
旨在解决单体应用在一个相对长的时间跨度下,由于参与的人员、团队的增多、变迁,从一个普通应用演变成一个巨石应用后,随之而来的应用不可维护的问题。
微前端实现形式
- 单实例:即同一时刻,只有一个子应用被展示,子应用具备一个完整的应用生命周期。
- 多实例:即同一时刻,多个子应用被展示。通常基于 url 的变化来做子应用的切换,或使用 Web Components 方案来做子应用封装,子应用更像是一个业务组件而不是应用。
微前端的优劣
优势
- 技术栈无关。主框架不限制接入应用的技术栈,子应用具备完全自主权。
- 独立开发,独立部署,子应用仓库独立,前后端可独立开发,主框架自动完成同步更新。
- 独立运行时,每个子应用之间状态隔离,运行状态不共享。
- 支持增量升级。
- 是一种非常好的实施渐进式重构的手段和策略。
劣势
- 接入难度较高
- 应用场景:移动端少、管理端多
微前端实现方式
Iframe
优势
- 技术成熟
- 支持页面嵌入
- 天然支持运行沙箱隔离、独立运行
劣势
- 页面之间可以是不同的域名,需要跨域处理。
- 需要设计一套对应的应哟个通讯机制,如何监听、传参格式等内容。
- 应用加载、渲染、缓存等体系的实现和控制。
web component
优势
- 支持自定义元素
- 支持
shadow dom
,并可通过关联进行控制 - 支持模板 template 和插槽 slot,引入自定义组件内容
劣势
- 接入微前端需要重写当前项目
- 生态系统不完善,技术过新容易出现兼容性问题
- 整体架构设计复杂,组件与组件之间拆分过细时,容易造成通讯和控制繁琐
自研框架
优势
- 高度定制化,满足需要做兼容的一切场景
- 独立的通信机制和沙箱运行环境,可解决应用之间相互影响的问题
- 支持不同技术栈子应用,可无缝实现页面无刷新渲染
劣势
- 技术实现难度较高
- 需要设计一套定制的通信机制
- 首次加载会出现资源过大的情况
实现方式
路由分发式
主应用控制路由匹配和子应用加载,共享依赖加载
子应用做功能,并接入主应用实现主子控制和联动
实践
技术栈选型
应用:
- 主应用
- 子应用
- 后端服务和发布应用