前言
关于架构设计这个话题对于我而言,可能有些大,但这是作业,所以就把学习的东西自己理解一下,写一写,整理一下思考过程和笔记。
预览
如果一个项目要做架构设计,需要做什么?
要回答这个问题,我觉得我们得先搞清楚一件事情——需求、需求背景!然后是设计目标。有了设计目标之后,明确指导思想。然后才是架构设计-架构图。这大概也是本节课的一个思路。
架构设计第一步——需求分析
只有充分搞清楚用户诉求,我们才能够有的放矢的来设计架构,才能够有效的针对用户诉求来设计。
什么是需求分析
理解和挖掘用户诉求、以及背后的逻辑,转换成可行性的分析结果。从非结构化到结构化,确定系统的职责、模块的过程。
我觉得这个第一句是重重之重,怎么样来理解挖掘?
这个离不开与业务团队的深入沟通、调研。但是实际上对于开发者而言,通常会有一个产品经理来做这个事情。但是与其充分沟通,理解需求。沟通调研的目的:
- 分析背后的人性:这个需求的目的是什么?背景是什么?满足的是什么诉求?
在此过程中,我们应当注意识别伪需求:没有调研、没有目标、没有逻辑的需求。做上去也没有人使用的需求。
那么识别出来后,怎么回应:
- 摆数据,用数据来证明需求的合理性。
- 用正反案例/场景,来指出需要改进的地方。
- 用户路径和触点推演需求的合理性。
简而言之就是,摆数据、举例子、角色代入推演来举证。但是一定要明确一点,这里的目的不是为了反驳产品经理,而是为了得到一个合理的需求!
问题的分层
除了识别出用户诉求之外,一个系统要解决的问题,从来就不是单一层面的。以支付场景为例
用户问题(本源问题)
本源问题就是解决用户如何支付。
业务问题(经营视角)
支持一切可以支付的第三方工具
产品问题(体系结构)
要做到产品级别,就必须考虑逆向流程(回滚/撤销操作)、异常场景:退款、支付失败、对账
技术问题(代码结构)
支持高并发、高可用、可弹性拓展,实现第三方支付链路。
高并发,支付接口对于平台而言会并会比较高一些。如果第三方接口的并发比较低,怎么处理?
高可用,第三方支付不可达怎么处理、如何减少此类情况?
可弹性拓展,如何快速接入新的第三方支付渠道。
需求分析产出
需求产品化:
- 模块化:识别模块的边界,模块的核心领域。
- 配置化:什么需求是需要弹性配置的
- 有逻辑:逻辑是否完整闭环。除了正向流程,还有上面提到的撤销操作和异常场景。
需求落地路径:
需求分析 -> 可行性 -> 设计 -> 编码 -> 测试 -> 发布。
架构设计的第二步——明确指导思想
KISS原则:keep it simple and smile
架构设计的理念是大道至简:解决问题。什么意思呢?就是用最简单、最容易理解的方式来解决问题。
解决什么问题呢?
- 如何让我们的系统有良好的可拓展性和可维护性?
- 如何让我们的系统能够恰到好处的解决问题,而不会增加复杂度?
- 如何让我们的系统能够运行3-5年不重构。
所谓smile,是因为现代软件需要很强的协调能力,需要我们保持微笑来迎接各种否定。
1. 业务部门的挑战(价值问题)
2. 成本部门的挑战(ROI问题)
3. 测试部门的挑战(可测试问题)
4. 技术部门的挑战(可行性和工期)
DRY原则:Don’t repeat yourself
一切重复的代码都可以抽象。
危害:
- 不一致。改了一个地方,另外一个地方没有改。
- 代码冗余。
- 容易出BUG。这个跟不一致有相似之处。
七大设计原则
相信大家都知道面向对象设计的七大原则,其实在架构设计层面一样也可以作为我们的知道思想。SOLID + 组合复用。
他们的共同点:提升软件的可拓展性,可维护性,是抽象和归纳的集中体现。
单一职责 S
一个类只做一个事情。定义很简单,但是落地很困难。单一职责实际上是高内聚、低耦合的延伸。在架构设计层面,需要属性和行为向着模块预定义的功能内聚。
这里说到一个点就是:名字。相信有很多同学,在给变量、方法、类等取名字的时候都很随意。这恰恰是最不可取的,因为实际上,每一个名字都隐含了这个事物的属性和职责。简单来说就是,这个东西是什么?能干什么?一旦名字取的不好,那这个类就很容易失控。
这同时也告诉我们,在定义类的时候要把类的职责在类的头部说明清楚,在改动一个类的时候,先看下类头部的职责声明,而不是一股脑的加方法,加依赖等。
开闭原则 O
对拓展开放,对修改关闭。核心要义是,识别可变的地方定义成接口以组合的形式完成功能。
里氏替换原则 L
凡是父类能够出现的地方,子类一定能够出现。他们是IS A关系。
迪米特原则
又叫最少知识原则。强调只跟朋友说话。最好就是,我只需要知道出参和入参就够了。
接口隔离原则 I
接口粒度要尽可能的小,同一接口的方法强内聚于同一特征。也就是说,要有共同特征,围绕着这个一个特征的行为。
依赖倒置原则 D
细节依赖于抽象。
底层依赖于高层。
强调面向接口编程。