我的架构思想(三十七):架构原则,技艺、艺术与美——架构原则(架构第一原则:架构面向问题,但满足需求。)

阅读数:20 2019 年 10 月 12 日 17:12

我的架构思想(三十七):架构原则,技艺、艺术与美——架构原则(架构第一原则:架构面向问题,但满足需求。)

1. 我们已接受的许多东西是有着商业背景的

事实上,我们已经被迫接受了许多种“面向些什么”的架构实现,这既包括“面向企业的架构”这样直言不讳的,也包括像“面向互联网络解决方案”这样披着外衣的。总而言之,这些架构的推广者总是试图声称它们在某个方面具有丰富的经验,有着广泛而显著的成功案例。并且,他们试图用种种措辞来掩饰“这些架构”的背景,而寄期望于你去复制这些结果。

这种“复制”的背后就是商业行为了。

然而几乎没有人会走过来深入你的系统,帮助你指出你的问题在哪里,以及需要如何应对它们或者绕过这些问题。因为如果你的系统没有了问题,那么看起来也就不需要解决方案了,那么看起来方案提供商也就没什么事可做了。

事实上,我是反对“方案”这样的东西的。因为在大多数情况下,那些向你推广这些东西的人根本就不了解你的问题,他们只是通过对你的需求的了解,拼凑了这样一套方案以应付你那些急迫的购买冲动罢了。

2. 面向需求通常是不考虑系统的背景的

从提供方来考虑的方案,通常是面向“同类系统的同类需求”的。这种需求上的相似性才决定了方案的价值。它并不考虑确定系统的背景,因为背景的不同正好削弱了方案的价值。然而,我们事实上是无法脱离背景来讨论系统问题的。举例来说,如果问题是“某个模块导致了性能较低”,方案是选择某个.NET 架构方案,因为它已经被证实过在这方面异常优秀。那么选择正确吗?

虽然看起来我们解决了“问题”——性能较低,但事实上这并不一定是正确的架构选择。因为如果开发方、用户方根本没有.NET 技术人员,则这一选择事实上没有解决问题,反而制造了更多的问题。又假设我们确实有很多.NET 技术人员,但是系统当前并没有围绕.NET 架构方案来实施,那么这一选择就增加了问题的规模。所以问题本身是有背景的,而它的需求可能表现出来与这一背景无关。

3. 面向问题首先是客户视角的变化

“面向需求”本身是没什么错的,因为我们的软件开发活动最终总是要解决用户的实际需求。但需求的“持续可变”是所有问题浮在冰海上的表象,正是它们随海水的、风力的变化而变化着,才导致我们“面向需求”去求解时疲于奔命。这其中,一个重要的问题在于:客户是很难从系统角度上识别问题的,并且当他们站在“客户与供应商”的层面上思考时,他们也完全不必要对可能的系统问题作出解释

提出需求,这近乎于客户的本能,否则他们便不需要供应商了。但对于问题,却只有当客户将供应商视作“合作者”时才可能提出来。从“采购-供应”的视角上看问题,客户与供应商是争利的。因此传统的工程方法以及架构、开发的思路,事实上已经主动将客户摆在了对立面,进而出现“你们——作为客户必须在需求文档上签字”这一局面就是必然的、顺理成章的事情。换个角度,只有当二者站到“共同解决问题”的角度上来看,才是共赢的,进而问题本身就变成了焦点:需求可以通过对问题的阶段性关注、梳理来明确;需求的变化可以通过架构的确定性来消化。

退一步来说,若既已存在“客户与供应商”这样的事实关系,那么供应商从面向需求转而面向问题,仍然可以最大程度地得到客户的谅解——尽管“面向什么”在客户眼里确实是一个过于空泛的概念(这也是尤其要注意的地方)。对于“供应商 / 开发方”来说,面向问题会是一个主动发起合作,进而争取普遍合作的开端。这无论对内部项目、自有产品还是外部项目来说,都有着明显的积极意义。

4. 面向问题与开发实作并无冲突

但是“面向问题”这一概念对于开发人员同样显得空乏。因为问题的关键求解在于架构,而不在于具体实作阶段的某一个技术行为。以平台层次为例,假定架构对某一问题的决策是“数据建模的过程可以延后至第二阶段”,这意味着平台层次中的底层数据结构是模糊的。那么这时开发人员如何做实施呢?答案是:开发人员可以在任意时候、任意位置,就地实现数据库或数据结构1。但是,这必将给架构角色带来层次规划上的灾难。因为如果推进这一方法,则在“第二阶段”来考虑数据建模时,系统架构将无法进行调整以容纳、应用新的数据模型。

1 这里的意思是说,是否使用内存数据库,或者某种特定的数据结构(可以考虑结构化文件存储),或者特定的本地数据库等,这些方案的选择是由开发人员来决定的。

因此,架构在第一阶段既不能“放任”开发人员的数据规划行为,也没有足够的信息与时间来进行数据建模。但这一矛盾的实质并不在于“谁做数据建模”,而在于“何时定义其细节”。而使架构角色在这里陷入了两难困境的原因则在于,他对自身的职责仍然缺乏必要的了解。回顾此前我们在架构过程中提及的两项架构责任:

  • 其一,架构对实施的约束;
  • 其二,架构的阶段抽象在实现域与交付域的映射。

由此看来,架构应当在第一阶段中与开发人员约定(注意做这些约定,其本质上也是数据建模活动):

  • 开发人员的数据规划行为必须限于当前应用中的数据层;
  • 必须通过一个界面交付到应用层,避免直接访问;
  • 若该数据规划涉及多个应用,则必须由架构角色来确认规划的有效性;
  • 数据层的交付界面必须不涉及特定数据层实现方案的细节2

2 这里涉及两点,其一是所谓“特定……实现方案”,例如交付界面不能是“对于 a 用户,存取 personal.dat 文件以得到 user 数据结构中的 age 成员”,应当抽象为“对于用户名 a,存取 user 数据项(或 age 值)”;其二,这也意味着要求这样的开发人员有一定的系统设计能力。

这些约束将对实现域中的行为构成明确的影响,并且也将影响到部署域。这些影响使得开发人员无法透过“自由地数据规划”来直接影响第二阶段中的数据建模工作,也不会对各个阶段中的部署过程构成威胁。

但是反观上述约定,其事实上也不会对开发人员的具体实施造成“巨大”的影响。架构的约束既体现为对问题的把握,也体现为面向问题的、阶段性的隔离。它对整个系统工程构成影响的方式既包括一系列架构图例,也包括上述的一些实施规则,最后——也最为重要的是,还包括架构师对问题的分解。

5. 面向问题是架构活动的必须

软件架构活动的来处并不在于“变化的需求”,只有将架构所解决的本质对象定义为“问题”,架构本身才有长期与持续性的需求;架构本身的复杂性与规模才有出处;架构应对于“持续可变的需求”才能寻得方法。

总的来说,需求可能一样,但问题却未必相同;需求可能被满足,但问题未必会因满足需求而消失;需求可能是破碎的,但问题却恒久而弥新。因此,架构的思维对象必须直接指向问题。唯只如此,架构活动的本质,才在于面向问题的求解;而其结果,才会是一个长期的、有效的、可持续推进的架构,而非应对一时之所需的技法。

评论

发布