产品展示
谈软件架构设计 - 开篇

发布于:2023-09-27 21:08:29  来源:产品展示  点击量:14次

  这几年我一直从事软件架构设计相关的工作,也看过市面上大部分的软件架构相关的书籍,结合自己的实践及思考,我打算通过几篇文章来梳理和总结下,算是我对这样的领域理解的一个Milestone。本文是一个开篇,来谈下什么是软件架构,以及为什么要关注其设计。

  虽然业界已经有了一些定义,但仍然没有一个统一的定义,一般的定义是这样的:

  软件架构是以组件,组件之间的关系,组件与环境之间的关系为内容的系统的基本组织架构,还包含了一系列的决策及指导其基本组织架构设计、实现与演化的原则,最终达到确保其满足软件的功能性和非功能性需求的目的。

  虽然这个定义看起来挺好,但仔细看却充满漏洞。什么叫‘基本组织结构’,由谁来定义哪些是基本的,哪些不是基本的,‘决策’和‘原则’这两个词也非常的主观,啥状况下由谁以什么标准做出决策?怎么判断做出的决策的好坏?由此能够看出,上面的所有定义都是主观的定义,所以软件架构本身就是一个主观的东西,这就让人想到一个很有意思的说法,“软件架构是架构师认为的架构”,物理世界的软件架构的存在性不重要,真正重要的是主观层面的东西,即软件架构是架构师用于把控整个软件的软件要素。

  但只要某个软件存在,不管这个软件是复杂还是简单,不管有没有人专门去设计,有没有相关文档记录,也不管有没有人理解。一定有其组织架构,经历了各种决策(隐式或者显式的),至少满足了既定的(功能和非功能性)需求,可能还有一些不需要的功能,特别是复杂的系统,这么看,一个软件的架构也一定是客观存在的,问题只是关于软件架构的描述,无论如何描述,如何定义,都无法将其描述清楚(这就涉及到了复杂系统的描述视角的问题)。如果有一天,我们无需进行软件架构的描述,AI能自动分析需求,自动实现,获得反馈并自动优化,这样一个时间段软件的架构客观或者主观上的存在或者不存在,就毫无意义了,甚至软件工程都可能不存在了。

  所以,我想说的是,关于什么是软件架构的精确定义,其实不重要,在AI没有完全替代人类之前,我们应该关注软件的架构,从而让软件成功,并且是持续成功。其核心是对软件的把控,虽然何为’把控住了‘因人而异,但假如没有人去把控,则就没有人控制软件复杂度(技术债)的熵增,就会突然有一天,软件改不动了(成本太大)。

  当前的软件研发还是以人为主,并且是一个多人协作的活动,‘人‘能理解是一切的前提,不理解就不能参与到一系列的设计活动中,也就把控不住软件,也就无法确保软件的持续成功。

  注意,这里说的是‘复杂‘,也就是说,在软件系统变得足够复杂之前,我们都可以少关注或者不关注其架构,这也就是很多讲软件架构的书,都会先讲‘什么是复杂系统’的原因。

  关于大脑的限制,这属于‘大脑认知科学’的范畴,简单来说,信息过载,推理困难,创造力不足与认知偏见等等都是大脑处理复杂问题的障碍。

  信息过载。由于人类工作记忆有限,一般能容量在7±2个信息单元,导致有大量信息的时候,很容易过载

  推理困难。进行多步推理是处理复杂问题的关键,但研究显示人类的逻辑推理能力是有限的

  创造力不足。探索和抽象问题的创造性思维对处理复杂问题也很重要。但是创造性思维并不是人类大脑的强项

  思维定势与认知偏见。大量认知和社会心理学研究证实,人类存在许多不一样的认知偏见,比如归因偏误、群体偏见等,这影响我们对信息的客观处理

  所有的软件系统都会越来越复杂,技术债都会慢慢的变多,合理的架构干预会将这些技术债控制在合理的范围内,从而让软件成功或者持续演进。

  我听到很多类似的说法:“别搞这些虚的,先做出来再说”,“没有架构设计我的软件不是也work的挺好的吗”,“我是MVP产品,做太多设计会影响进度”,“不是说演进式架构吗,让架构自己演进就好了啊”。

  这些说法的对错其实毫无意义,毕竟脱离了具体场景了。比如,所谓MVP产品,其实也符合上述定义。对于这类软件系统,其目的一般是要快速上线,验证产品功能和市场。这类的软件系统一般都不会很复杂,因为复杂就从另一方面代表着高成本,一个随时有可能改变商业策略的产品,前期的投入随时都可能打水漂。这类软件产品最简单的实现方式是功能堆砌,可以先不过多干预软件的架构,对于非功能性需求考虑的也比较有限,如性能,可维护性等。但需要有人持续关注软件的复杂度,但到了一个节点时(这个节点并没有标准,跟团队能力,公司氛围,商品市场等都有关系)就要开始关注软件的架构,可能会出现一部分工作是处理前期功能堆砌而造成的问题,但由于系统还没有太复杂,处理的成本不会太高,甚至关键的设计都能重新做。以控制软件的技术债的熵增,让软件随着产品功能需求而持续演进。

  这是架构设计的起点,也是最需要投入精力进行把控的地方,但也是最难的地方。架构师不能直接定义或直接改变目标,只可以通过理性的分析和推演来左右目标,同时所有的目标都应该指向同一个源方向。

  在企业中,任何软件的目标都应该有利于企业的长期生存价值的需要,要么将本增效,要么直接或者间接带来盈利,要么推进企业的长期战略目标。

  软件的初始目标一般都是模糊的,甚至是错误的,比如产品经理说“我要对现有产品做一个改版,以提高用户的体验”。这个目标就是模糊的,架构师拿到这个目标的第一件事情应该是尽量清晰目标,运用逻辑和专业的技术知识,帮助产品经理搞清楚真正的目标,虽然很多人,特别是同时兼任架构师和研发经理的同学,会强烈反对,认为搞清楚目标是产品经理的职责,不是架构师的职责,在我的认知里,软件研发活动首先是一个协作的活动,其次架构目标的明确肯定是架构师的职责,而这个周期有一些时候很长,或许从产品经理一开始提出一个想法的时候就开始了,架构师需要一直跟进,在适合的时候加大投入精力,将目标尽量的明确。

  干系人管理也是很重要的一个点。所谓干系人,就是与此软件相关的人,一种简单的划分方法就是

  架构师需要首先识别干系人,然后对干系人进行一定的管理,这样的一个过程贯穿整个架构活动,这与项目经理对干系人的管理通常是一种配合的关系,但侧重点不同,比如:架构师需要管理干系人的目标,解决目标的冲突。

  一个很有意思的问题是:架构设计和一般设计的区别是什么?如何才算是架构设计?这同样是一个没有标准答案的问题,还是回到“如何把控一个软件”的问题上,我认为架构设计的范围只需要足够把控一个软件就够了。所谓“把控”,其实是架构师的一种感觉,也叫“架构信心”,就是理性的了解这一个事情是能够实现的。甚至架构review的过程,从某种角度来说,都是为增强架构师(所有干系人)的“架构信心”。

  一种简单的评判准则是,但一个决策被做出后,后期改动的成本非常大或者基本不可能改动,那这个决策就是架构决策,做出这个决策的过程就是架构设计的过程。比如,当我们设计一个公司统一的SSO架构的时候,决定是不是选用第三方AD存储,是否自研认证服务(IDP),是否使用基于API Gateway的架构,还是分散式的架构,都是架构决策,与之相对的,用户认证的流程中是否支持MFA就不算架构决策,因为这是能添加而不可能影响到刚刚的架构决策的(如,不会说由于我要支持MFA,导致我一定要使用基于API Gateway的SSO架构)

  当然,架构决策的做出与很多因素相关,比如团队的能力,团队是否以前已经有了某些设计共识,跨部门的沟通交流是否顺畅,架构师能力如何,对业务是否了解,对使用到的技术是否心中有数等等。

  “概念的明确”,也叫“统一语言”,这样的一个过程贯穿了整个架构活动。即根据公司环境、团队情况来明确定义某些概念,以便大家基于这些定义来讨论、设计和实现。要知道,架构师的一个重要的职责就是要推进建立共识、消除歧义,而统一语言是一切的前提,这也是特别容易忽略的一个点,这也是为什么DDD(Domain Driven Design)中特别强调统一语言的重要性的原因。使用与干系人一起共创的方式,能更容易的统一概念,如通过 【事件风暴工作坊】 的方式。

  抽象和分层是分离关注点重要的两个方法,而分离关注点则是理解复杂系统的关键方法之一。所谓抽象(Abstraction),就是将细节隐藏,通过抽象来涵盖更广更本质的系统面,比如数字就是人类最伟大的抽象,‘1’可以表示任何是‘一个’的事物,比如一个苹果,一辆汽车等等。所谓分层,即只关注其中某一部分,这部分与别的部分能够最终靠“接口”(广义的含义,不是指编程语言中的接口)进行关联,比如模块化(Modularization),分视角(Perspective,如某些编程语言就支持面向切面编程Aspect Oriented Programming)等。

  设计的过程就是建立逻辑链的过程,就是对方案进行逻辑推演的过程。以前经常听到一种类似说法:“***只要能自圆其说就行”,这并不是偷懒,这里的“自圆其说”就是建立逻辑链,所谓逻辑链,就是从一个业务目标出发,识别重点设计的目标,推导怎么来实现这些目标,每个推导的节点就是逻辑链的节点,如果逻辑过于跳跃,则逻辑链会断裂,如果逻辑不在一个抽象层级上,则逻辑链无法构建,如果逻辑太细,则逻辑链会太长(很可能是设计太细)。

  而设计文档是展示自己的逻辑链的媒介,所以在写设计文档的时候同样要基于逻辑链。仔细想来,会发现几乎所有与逻辑思考有关的事务都要基于逻辑链。特别是讨论一个设计问题的时候,所谓的“talk is cheap, show me the code”,其实是因为无法讨论,才需要从代码中去寻找逻辑链,是无奈之举,并不是炫技。

  设计假设通常会在不自知的情况下做出,这就涉及到了架构师对设计决策的敏感度。这也对应了前面提到的逻辑链,设计假设实际上的意思就是在假设某些逻辑节点,因为架构师不可能知道所有信息,所以基于逻辑推理,自然会产生一些结论,而这些结论是否成立,需要架构师去求证,有几种求证的方式:

  另外值得一提的是,在AI时代,有了LLM工具的辅助,架构师可以高效的通过生成代码或Demo进行某些设计的快速验证,对架构师的工作非常有利,如果你还没有开始使用相关的LLM工具,赶紧使用起来。

  相较于‘文档’这个词,我更喜欢使用‘描述’,因为本质上我们就是通过写文档的方式来描述我们的架构设计,而之所以架构师需要将自己的设计描述出来,是因为:

  如果架构设计决策没有被记录下来,那就不能说做过架构设计,这是架构师重要的产出之一

  架构描述文档的书写过程就是架构师做架构设计的过程,架构师自己也是架构描述的主要用户之一,架构描述文档会辅助架构师理清思路、充当记忆辅助、进一步分析的基础等,如果你没办法有组织有结构的写下来,就不能说你想清楚了。

  架构描述文档是架构活动中与各个stakeholders沟通,让他们了解设计及其选择原因并达成共识的重要工具。

  我们一般说的“飘在天上的架构”或者“PPT架构师设计的架构”,就是没考虑软件架构设计的落地问题,这也是大多数的架构设计缺乏考虑的问题。

  不存在完美的软件架构,只有最适合现状的,这就应该要依据现状,比如研发团队能力的限制、时间的限制、技术组件的限制等,考虑短期和长期的性价比,一个理想的设计实施要1年,但短期的问题先解决可能就只需要1个月,这1年也不可能将业务都停掉,这时候正确的思路应该是更多的考虑架构的演进视角,如:隔离需求的易变点。让更容易变动的在变动的时候对其他模块影响较小。

  另一个问题是,如何保证最终实现出来的软件与架构设计一致。其实没什么特别的方法,就是:

  软件架构师似乎是一个神秘的职业,就像软件架构本身一样,没有很好的方法对其有一个统一的定义,但架构师就是那个设计软件架构的人,也是最需要把控整个软件的人,他们主要通过管理软件研发生命周期中的架构活动来干预软件的架构。

  很有意思的是,架构师一般没有研发下属,也不能定义软件的目标,甚至细节设计也不是出自架构师之手,架构师拥有的实际硬核的(指在企业中行政的)权利机会几乎为零。在这种情况下如何干预和把控整个软件呢?这里我认为有两点,一个是专业的技能和方法工具,包括认知层面的东西。

  比如架构师要认知到软件设计本质上是挑选软件的一部分视角进行逻辑建模,推演;

  又比如设计的描述文档的目的是为了辅助推演,辅助和干系人交流,而不可能将所有的设计反映在文档上,这也是毫无意义的;

  再比如每个架构师都会构建自己的工具箱,其目的是为增加以后架构活动成功的概率,也是自己职业发展的重要筹码。比如各种架构模式,架构分析方法,工具(如Event Storming),人际沟通方法,一些底层认知逻辑等。

  另一个很重要的点是刚刚提到的‘威信’,这是一种隐形的东西(你可以想想在自己身边,是否有这么几个人,相关的事情交给他们,就会特别的放心,他们的意见你就会特别的重视)。‘威信’要一直的积累,积累的方法就是成事,也就是不断的将事情做成。有人的地方就有‘江湖’,所以这样的一个过程又涉及到人际关系的构建,毋庸置疑的是,良好的人际关键对软件架构设计的落地有很大的助益,但架构师要时刻保持清醒,要时刻记住你做的一切事情都是为了架构活动的成功,而所有的架构活动都要满足企业的长期生存价值,而不是个人或者其中单个组织的成功。

  由于每个架构师对软件架构的干预策略及干预程度不完全一样,这就导致了即使同一个软件,对于不同的架构师来说,其架构及其设计也有一定差别。但总的来说,只要架构师能把控住整个软件,将技术债控制在一些范围,这个软件又能持续的创造业务价值,为企业的长期生存价值做出贡献,那这个软件就是成功的。

  所谓的软件要素,是关于某个软件的任何东西,包括:软件的基本组成结构,某一个重要的软件视角,软件设计/实施的共识,软件运营时的流程等。只要这么多东西能让架构师把控住整个软件。

  本文简述了我对软件架构,及其设计的思考,后续的关于软件架构的文章会根据本文展开,比如软件架构活动的关键步骤,架构设计的几个核心问题(逻辑链问题,抽象与分层问题,设计描述问题,架构设计落地问题等),软件架构设计的常见模式,架构师与个人成长相关的话题。