本文主要对架构的概念做一些介绍,并引申出需求分析的重要性。
后续准备做一个系列,定期介绍我工作以来的一些需求实现的案例。
注:因为架构的内容比较庞大,里面的每个点,都可以扩展成一系列的文章,
因此,本文只是漫谈,多数内容仅做介绍,后续有时间,我再考虑展开写一写。
架构简介
1、误区
说到架构,很多开发人员,尤其是后端开发,会关联到一堆技术内容:
- 分库分表
- 负载均衡
- 微服务设计
- 分布式CAP原理
- 熔断降级限流
- 注册发现
- ServiceMesh
其实,这些都不是架构的主要内容,这些只是一些需求或问题的一小部分解决方案,
甚至这些解决方案的适用面也很窄,这些仅主要是用于互联网项目(高并发、高性能、大数据的要求)
绝大多数的项目,尤其是初创项目,根本用不上这些解决方案,因为一开始的相当一段时间内,没有那么大的数据量或用户量、并发量。
2、概念
在不同的平台,对架构有不同的解释:
- 维基百科:软件架构是有关软件整体结构与组件的抽象描述,用于指导大型软件系统各个方面的设计
- ISO/IEC:系统的基础结构方式,包含了系统组成元素,这些元素之间的关系,以及指导系统设计和实现的原则
- IEEE:架构是一个系统在其组件层面的基本组织结构表现,包括系统内部组件之间的关系、组件与外部的关系以及决定其设计和演进的原则
- 百度百科:架构是有关软件整体结构与组件的抽象描述,用于指导大型软件系统各个方面的设计。
我自己在网上找了一个,我认为比较合适,更易于理解的,关于架构的定义:
- 根据要解决的问题,对目标系统的边界进行界定。
- 并对目标系统按某个原则的进行切分。切分的原则,要便于不同的角色,对切分出来的部分,并行或串行开展工作,一般并行才能减少时间。
- 对这些切分出来的部分,设立沟通机制。
- 根据上一步的沟通机制,使得这些部分之间能够进行有机的联系,合并组装成为一个整体,完成目标系统的所有工作
注:切分不代表是拆分微服务,也可以多模块部署成单体,不过切分完,后续比较方便按微服务部署就是了。
3、为什么需要架构
看一张图:
这张图,说我们所处的时代,是一个易变的时代;这张图同样适用于很多的产品/需求,有一句话是这么说的:
需求最大的确定性,就是需求的不确定性。
意思就是【需求多变】,这种特性是稳定不变的。
网上摘录:
- 架构设计的主要目的:在实现系统的目标功能前提下,解决系统复杂度带来的问题。
系统的复杂性来源:- 需求让技术变复杂
- 人员让技术变复杂
- 技术本身的复杂度
- 系统稳定运行的复杂度
为了应对系统的复杂性和需求的多变性,必须要提前进行架构规划和设计,我认为架构设计的大概步骤如下:
- 收集需求和理解需求
包括但不限于跟市场人员、产品经理、最终用户沟通和对齐,以及做可行性分析; - 需求分析
明确系统要实现的目标,包括功能性需求、非功能性需求(含安全需求),以及时间约束等;
这一步通常要整理一些用例图、时序图、状态图来准备描述需求和沟通; - 技术选型/技术设计
这一步要明确采用的开发语言、开发工具、技术框架、数据库、中间件等,以及进行概要设计、详细设计; - 团队分工/技术排期
- 迭代开发/持续交付
- 运维部署/监控
架构设计的每一步骤,都需要架构人员结合当下背景,做出一个相对平衡的方案,
能否实现需求是最重要的评判标准,甚至是唯一的评判标准,
且任何一个需求,都没有唯一正确的架构或唯一的实现方案。
架构人员的背景因素一般有:
- 架构师的个人技术经验,这个主要会影响技术选型
比如数据库我会选择MySQL,并不会选择PostgreSQL或MongoDB,因为我有相对丰富的MySQL问题处理经验,而其它数据库经验较少; - 架构师的项目经验,这个主要会影响边界认知、模块划分
比如我做过SaaS系统,设计时就会提前考虑全局SaaS-ID的传输,以及未来的灰度发布;
但是我没有从事过保险业务,如果做保险项目,就必须花相当大的精力先了解保险业务才能进行设计; - 系统需求,包含系统能实现的功能及未来期望,含非功能性需求;
比如我们经过调研以及MVP产品的试用,预估一年内用户量可以达到多少,并发可以达到多少,那么在设计时是按单体部署还是按微服务设计,数据库是否需要提前考虑分库分表; - 工期要求,系统要求的交付时间,是否可以分期交付
- 团队能力,这会影响技术选型,工作分工,项目管理
比如团队里有C++高手,那么做客户端,或一些服务端的图片压缩之类可以考虑用C++实现 - 软件限制,影响技术选型
比如我们只能用Centos部署,那么就不能选择.Net Framework开发 - 硬件限制,影响技术选型,成本考量
比如我们跟xx云有合作,但是他们没有RabbitMQ支持,那我们的消息队列就要换其它可用的类型
需求分析
1、发现问题比解决问题更重要
在架构设计的步骤中,最重要的是需求分析的步骤,因为:
【发现问题比解决问题更重要】
如果理解错了问题,那么解决问题的投入,可能浪费了,甚至可能错过了解决正确问题的时机,导致不可预估的后果。
看一张图,有人去做西红柿鸡蛋汤:
我想通过这个图片说明一个道理:
每个人的阅历、知识不同,会导致不同的认知结果,有些你认为是常识,换一个人根本不懂
所以要通过不断的沟通/复述,正确的理解需求/问题,才能正确的进行后续的步骤。
再帖一张图,说明如果执行了一个错误的需求,在实现到不同的阶段,成本的差异,可以看到,在需求分析阶段的成本浪费是最低的,到了编码阶段已经是10倍的差距了,更不要说要上线维护阶段了:
2、怎么做需求分析
需求分析最主要的作用,是要识别有效需求,通常需求有三个层次:
-
业务需求( Business requirement )表示组织或客户高层次的目标。业务需求通常来自项目投资人、购买产品的客户、实际用户的管理者、市场营销部门或产品策划部门。业务需求描述了组织为什么要开发一个系统,即组织希望达到的目标。
理解:就是谁要建设这个系统,也可以理解为市场需求,解决了什么市场问题或痛点,
比如房产开发商提出要盖房子的需求 -
用户需求( user requirement )描述的是用户的目标,或用户要求系统必须能完成的任务。用例、场景描述和事件――响应表都是表达用户需求的有效途径。也就是说用户需求描述了用户能使用系统来做些什么。
理解:谁在使用这个系统。比如买房用户提出的对房子需求。 -
功能需求( functional requirement )规定开发人员必须在产品中实现的软件功能,用户利用这些功能来完成任务,满足业务需求
理解:系统本身要实现哪些功能,来满足上述2类需求,如房子本身要有哪些能力
我们在不同的阶段会输出不同层次的需求,业务开发时应当了解3个层次的需求,并依次考虑和满足各个你父亲人要求。
需求分析一般步骤如下,通常会有相应的需求文档和各种UML图例输出:
3、常见的UML图:
本文只介绍5种常用的UML图。
系统上下文图
定义待建系统与外部实体(人员、设备、其它系统)之间的边界和接口。
只关注与当前系统有直接关系的实体,不考虑依赖的依赖
下面是一个同城快递系统的上下文图:
系统上下文图的作用:
1、软件需求不能脱离目标系统的上下文环境,一般在做需求分析前使用,先确定好系统上下文,再进行用例建模。
2、帮助系统参与者在一个较高的层次,直观了解待建系统的用户是谁?可以用系统干什么?不能干什么?系统依赖谁?
3、帮助系统构建者,在正式开始前,理清系统的边界和范围,更容易与相关方讨论和完善系统范围;
用例图
定义了系统的参与者、系统包含的用例,以及它们之间的关系。
下面是同城快递系统的用例图:
用例图的作用:
用例图是需求分析中的产物,主要作用是描述参与者和用例之间的关系,帮助开发人员可视化的了解系统的功能。借助于用例图,系统用户、系统分析人员、系统设计人员、领域专家能够以可视化的方式对问题进行探讨,减少了大量交流上的障碍,便于对问题达成共识。
用例图可视化地表达了系统的需求,具有直观、规范等优点,克服了纯文字性说明的不足。
用例方法是完全从外部来定义系统功能,它把需求和设计完全的分离开来。我们不用关心系统内部是如何完成各种功能的,系统对于我们来说就是一个黑箱子。
状态图
描述系统中某实体基于事件反应的动态行为或状态变迁。
下面是同城快递系统的订单状态图:
状态图的作用:
状态图清晰地描述了状态之间的转换顺序,通过状态的转换顺序也就可以清晰地看出事件的执行顺序。
如果没有状态图我们就不可避免地要使用大量文字来描述外部事件的合法顺序。
清晰的事件顺序有利于程序员在开发程序时避免出现事件顺序错误的情况。
系统时序图
用于描述对象之间发送消息的时间顺序,显示多个对象之间的动态协作。
下面是同城快递系统下单抢单的时序图:
时序图作用:
时序图用于展示对象之间在特定时间范围内的交互和消息传递。时序图能够帮助我们可视化并理解系统的行为,以及各个对象在执行特定功能时的协作方式。这对于分析、设计和理解软件系统非常有价值。
系统活动图(流程图)
用于描述系统的活动、判定点和分支等
下面是同城快递系统下单抢单的业务活动图:
活动图作用:
活动图主要用于描述系统中的业务逻辑、工作流程和操作序列。活动图以图形化的方式展示了在特定上下文中,不同活动之间的动态关系和流程控制。它可以帮助我们深入分析系统的行为和操作顺序,从而在设计阶段就明确需求和逻辑。
注:活动图在实际开发活动中,使用最为频繁,一般画一个活动图,相当于在脑海中已经进行了一遍程序开发。
4、非功能性需求
在需求分析时,也要确认系统的非功能性需求,并输出在需求分析的产出物中。
非功能性需求的常见考虑因素:
- 完成任务的时间要求
- 结果的精度
- 操作的安全性
- 产品的容量
- 允许的值的范围
- 吞吐量,例如tps
- 资源使用的效率
- 可靠性
- 容错能力和健壮性
- 伸缩性
- 可扩展性
下篇文章,会专题介绍下非功能性需求的收集和产生过程。