人们普遍认为态度是成功的关键,这是有道理的。正如亨利·福特说的:
“不管你认为自己是否能够做到——你都是对的。”
如果你不相信自己能做好一件事,而且不去尝试,就可能永远做不好,这一点似乎是显而易见的。
然而,只是相信自己能够做到也仅止步于此,准备和计划也很重要。
怀疑也是如此,但这是一种特定的类型,这里我们指的是怀疑主义。更具体地说,哲学怀疑主义是这样一种信念,即在没有证据的情况下,至少在软件领域,不可能知道某事的真相。
在我们的经验中,怀疑主义是一种架构超能力,可以帮助我们在错误的假设走得太远之前——在它们占用了你太多的时间并给你带来了太多的工作,以至于你永远无法完成之前——识破它们。
稍后有更多详细的内容。
图 1:一些话头,它们在告诉你,这些假设可能需要进行测试
“过度的实证主义(Positivism)”会导致盲目
积极思考的力量是真实存在的,然而,如果用得太过头了,可能会导致我们无法甚至不愿意看到的与乐观预期不符的结果。我们不止一次地遇到这样的经理,当他们看到数据中出现了一个重要的利益相关者喜欢但对客户来说没有价值的特征,他们会命令开发团队压制这些信息,这样利益相关者就不至于“看起来很糟糕”。
即使高管没有让团队去做他们怀疑是错误的事情,展示积极结果的压力也会让他们不敢提出可能表明他们不在正确轨道上的问题。或者,团队可能会经历确认偏差,忽略那些不会加强他们“知道”是正确的决策的数据,而将它们视为“噪音”。
当一个团队试图理解为什么一个客户非常需要的功能在发布几周后还没有被客户接受,就可能会出现这种情况。团队可能认为这个功能很难被客户找到,所以需要重新设计 UI。然而,真正的原因可能是新功能并没有解决用户的问题,在调查清楚之前,他们不应该忽略这个可能性。如果他们只是简单地假设功能是有价值的,可能会着手进行高成本而徒劳的 UI 重构,而这并不是问题所在。
泰坦尼克号已经收到其他船只的警告,在她航行的区域有浮冰,但船长爱德华·史密斯决定继续全速航行,这是当时的标准做法。如果他质疑“冰山对大型船只几乎不构成危险”和“泰坦尼克号不会沉没”的信念,那么这一起在和平时期最致命的游轮沉没事故可能就不会发生了。
怀疑主义(Skepticism)并不等同于否定主义(Negativism)
人们经常将“怀疑主义”这个词作为“否定主义”的同义词,而否定主义被定义为“一种以怀疑为标志的心态,尤其是对几乎所有别人肯定的事情。”怀疑的态度会变成否定主义,特别是被犬儒主义放大时。尽管如此,我们认为在应对复杂的挑战(未知的东西比已知的东西多)时,怀疑主义是有它的用处的。
当我们使用怀疑主义这个词时,我们指的是之前提到的哲学怀疑主义。在应对复杂的挑战时,尤其是在早期,我们所知甚少——不仅对解决方案知之甚少,有时甚至对问题本身也知之甚少。在这种情况下,哲学怀疑主义可以帮助我们看穿错误的假设,克服我们的认知偏见,为现实问题找到更好的解决方案。这就是为什么我们认为怀疑主义是一种架构超能力:它就像 X 光透视,帮助我们看到世界的本来面目,而不是我们心中希望看到的样子。
怀疑主义的概念与经验主义(Empiricism)有着相似的根源,后者是形成敏捷方法的基础,而怀疑主义这个词起源于希腊单词σκέψη(sképsi̱),它的意思是思考或调查,其中的调查部分对软件架构来说非常重要。
怀疑主义的软件架构是怎样的
正如前一篇文章所述,构建和设计现代软件应用程序基本上是探索性的。构建应用程序的团队每天都会遇到新的挑战:前所未有的技术挑战和为客户提供解决新问题的新方法。这种不断的探索意味着架构不能被预先确定。
软件架构设计是由质量属性需求(QAR)驱动的,而不是由功能需求驱动的。在初始迭代中不考虑 QAR 通常会在软件系统部署超出初始试验阶段并拥有少量用户时出现问题。每一个需求,包括驱动架构设计的 QAR,都代表了一个关于价值的假设。当我们采用怀疑主义的方法时,目标之一是让这些假设变得明确,并有意识地设计实验,专门测试需求的价值。
可惜的是,QAR 通常没有被明确地定义。模糊的需求,如“系统的速度必须快”或“系统必须可伸缩”,对架构设计没有多大帮助。过度膨胀的可伸缩性 QAR(如“新系统能够处理的业务量必须至少是当前的 10 倍”)也是,因为这些需求通常是基于系统利益相关者不切实际的期望。对这些模糊的需求持怀疑态度是很重要的,因为它们可能会导致过度设计,并构建出不必要的功能。对需求的价值进行验证也很重要,研究表明,大多数需求实际上是没有用的,我们需要通过实验将它们与其他需求分开。
团队不需要在完全满足整个需求的情况下才能确定其价值,他们只需要构建简单且足够的系统来执行测试,验证(或反驳)假设并证明或否定需求价值就足够了。类似地,团队也不需要构建整个解决方案来评估解决方案所依赖的关键假设。但只是识别出假设是不够的,团队还需要对假设进行测试。
然而,团队在构建足够的系统来测试假设时,必须对测试系统做一些增强。最后,团队需要运行可能会失败或用于确定何时会失败的测试,这一点也很重要。
更好地了解正在做出的隐性架构决策,让这些决策变得明确,这样有助于开发团队使用他们从 sprint/迭代中获得的经验数据做出更好的决策。基于过去的经验,团队必须找到新的可以满足质量需求的方法。
怀疑主义有助于做出决策
团队有时会经历分析瘫痪,这使他们害怕做出决策。产生怀疑往往是其中的一个原因,但这也可能把他们引向解决方案。我们假设团队认为没有在没有实验的情况下就无法知道一个决策是对是错。这个时候,他们可以通过对替代方案进行实证测试来避免出现分析瘫痪。当团队试图在没有任何信息的情况下评估决策时,分析瘫痪尤其会成为问题:由于没有新的信息来指导他们,他们会不断地忽略相同的替代方案。
对于与解决方案相关的决策来说,唯一有用的数据来自于执行代码,其他一切都是猜测。熟悉某项特定技术的团队成员可能会认为这项技术决策是正确的,但要确定其正确与否的唯一方法仍然是编写一些代码并测试代码背后的假设。编写代码是解决架构师之间争论的唯一方法,再多的信念也不能证实或否定一个假设。
实践中的怀疑主义
应用怀疑主义应该像确定假设和提出诸如“我们需要看到什么证据才能知道这是对的”这样的问题一样简单,然后建立度量方法对假设进行测试。但根据我们的观察,提出怀疑似乎很难。考虑下面的例子:
一家保险公司的一些高级技术团队成员一直在试验规则引擎技术。他们似乎发现了这个规则引擎的许多用途,比如可以取代应用程序中的“if-then-else”代码。他们发现,有了规则引擎,他们就可以在不修改、编译和部署代码的情况下改变应用程序的行为。可能根本不需要技术人员参与,可以直接由运营人员负责维护规则。
在早期成功实现了控制保单发行和定价(主要是幕后工作)的规则之后,他们开始跌跌撞撞地进入了一个似乎更具挑战性的阶段。一些规则的变更不仅会改变程序逻辑,还会改变 UI 的外观和行为。经过一番考虑,团队发现 UI 行为是一种不一样的应用程序逻辑,他们可以开发定义 UI 行为的规则。
于是,他们开始雄心勃勃地重新设计应用程序的 UI,编写与 UI 观感和行为相关的规则。从技术上讲,这是可以实现的,但其影响相当大:应用程序变慢了,管理 UI 规则的人需要具备开发经验。这样一来,开发灵活性没有得到提升,反而产生了一个更复杂的问题:在缺乏良好开发和测试工具(规则引擎)的环境中编写 UI 行为。当出现问题时,系统中的行为变得不可追踪。
这个例子与一句古话如出一辙:“如果你只有一把锤子,那么所有东西看起来都像钉子。”规则引擎对于问题的某些部分是有效的,但这个比喻也仅限于与之相匹配的问题。如果采用一种怀疑主义方法,确定与可维护性相关的 QAR,然后基于它们测试所提出的解决方案,很快就可以看出这一点。规则引擎有它的作用,但团队在 UI 设计中对它的使用超出了这些工具的预期用途。
一个非决策类型的例子:可伸缩性假设
传统上,可伸缩性不被认为是软件系统的重要 QAR,但这种看法在过去几年发生了变化,可能是因为大型电子商务和社交媒体公司对可伸缩性的关注。可伸缩性可以被认为是系统通过增加(或减少)系统成本来处理增长(或减少)的工作负载的属性。可伸缩系统是一种常见的简化说法。可伸缩性是一个多维度概念,因为它可能指应用程序可伸缩性、数据可伸缩性或基础设施可伸缩性。
令人感到惊讶的是,软件系统通常被认为是可伸缩的,特别是如果托管在商业云上,正如《持续架构实践》中所说的:
“云计算提供了允许应用程序以合理的成本处理意外工作负载的承诺,并且不会对应用程序的用户造成任何明显的服务中断,因此,云计算对可伸缩性来说非常重要。”
然而,只有设计良好的系统才能在云环境中进行良好的伸缩。换句话说,将一个设计糟糕的系统移植到云环境中不太可能获得良好的可伸缩性,特别是如果没有设计好水平可伸缩性的话。
例如,一个为新软件系统开发最小可行产品(MVP)的团队通常专注于尽可能快地交付系统,它并不关心 MVP 成功后会发生什么。如果系统的用户基础在最初的发布之后出现快速且意外的增长,系统可能需要进行快速的伸缩,而这超出了团队最初的工作负载假设。他们可能认为在商业云平台上托管系统就把可伸缩性问题转交给了云供应商!商业云平台确实可以提供有效的伸缩性,但前提是应用程序需要被设计为可以利用这些云平台的特性。即使是这样,云平台也不能解决所有的可伸缩性问题,比如当设计中存在资源瓶颈问题时。
有时候,我们会混淆了可伸缩性与性能。与可伸缩性不同,性能是关于软件系统满足其时间需求的能力,并且比可伸缩性更容易测试。如果系统的性能在初始版本中是足够的,团队可能会认为系统能够应付未来增长的工作负载。问题是,如果在架构设计期间不将可伸缩性作为重要的 QAR 之一,就不是这么回事了。
当然,我们通常不会很明确地指定可伸缩性需求,特别是对于实现了 MVP 的系统来说,因为通常没有人能够猜测有多少用户会对新的 MVP 感兴趣,但这不应该成为不做决策和忽略可伸缩性的理由。另一方面,为了“以防万一”而过度构建系统的可伸缩性,以及基于大量膨胀的工作负载来估计架构设计也不是一个好方法。
例如,谷歌、亚马逊、Facebook 和奈飞系统具有出色的伸缩能力,但这些公司使用的设计策略并不一定适用于需要处理不同工作负载的公司。在理解这些策略的含义并将 QAR 和假设明确地作为一系列架构决策之前,我们应该谨慎地使用可伸缩性策略,如基于微服务的架构、异步通信、数据库分片和复杂的分布式系统。
对这些估计持怀疑态度可以防止团队过度设计系统和构建出不必要的功能。
基于怀疑主义测试提出的解决方案
公司也可以利用怀疑主义来达到更积极的结果。一些团队成员对某个开源框架的经验有限,他们认为可以用它开发一个新的全球制造商的保修管理系统。每个国家的法律限制和业务要求略有不同,但全球的核心流程是相同的。这个团队认为,开源框架可能可以帮助他们开发系统的基本功能,因此,与从头开发基本功能相比,针对当地国家的需求进行定制会更容易、更快、成本更低。使用这个框架做出的有限的原型让他们看到了希望,但还不足以评估其整体适用性。
他们没有直接开发整个系统,而是决定采用怀疑主义方法:他们从代表系统整体功能的功能中剥离出一部分。在一个多月的时间里,他们使用这个框架构建并测试了这个部分,甚至将其部署到一个较小的业务部门进行内部测试和反馈。开发这个部分的成本接近 50 万美元。尽管如此,开发团队认为,由于这部分是他们的“最小可行产品”,被用于测试他们提出的“最小可行架构”,因此支出是合理的。
在这个过程中,他们发现了一些问题:
他们能够构建所需的功能,并且确实能够在与生产环境类似的环境中运行,但是……
开源框架并不像他们所希望的那样灵活和高效。事实上,这个框架让代码变得更加难以维护,而不是更容易维护,因为这个框架与底层工作流所需的模型不完全匹配。
作为实验的结果,公司决定在开发中不使用开源框架,而是自己构建更适合用来解决手头问题的框架。如果他们只使用外部框架开发整个系统,预计开发成本将达到 2000 万美元。如果在开发的后期发现不合适的话将导致大量的返工,需要移除外部框架,并重新构建系统。在我们所观察到的项目中,这有时候意味着需要重新开始,原始的投入将功亏一篑。
如何巧妙地应用怀疑主义
应用怀疑主义是具有挑战性的,不仅仅是在技术层面。在一个组织中,人们可能不习惯他们提出的陈述被质疑,无论背后有什么积极的意图。为了培养怀疑主义文化,团队必须开放地验证断言,无论这些断言是谁提出的。
这里有一些方法,可以让看似尖锐的东西变得柔和。团队可以先制定一个原则,即所有假设都需要进行测试,无论它们的来源是什么。当一个团队同意这是“工作方式”的一部分时,团队成员就不会觉得自己的想法受到了挑战。当特定的断言或假设需要进行测试时,这样做就成了团队决定如何工作的一部分。
另一个方法是让团队问自己:“如果我们的假设被证明是错误的,那么哪些假设可能会阻止我们实现我们需要实现的目标?”这是一个关于所有假设的一般性问题,而不是针对某一个人的假设或断言。
还一个方法是参考这句格言——“事实总是是友好的”,这意味着更多或更好的信息将帮助我们实现目标,而不是伤害我们。为工作方式制定一个原则,即“没有不好的想法,只有不完整的信息”,这样也有助于消除对假设和断言的挑战。
有趣的是,天主教会在 16 世纪建立了“信仰捍卫者”角色(也就是人们所熟知的“魔鬼代言人”),使怀疑主义成为他们册封圣徒过程中不可或缺的一部分。“信仰捍卫者”通过对候选人的性格和行为持怀疑态度来反对他们被封为圣徒。这个角色今天已经不存在了,但机智的怀疑主义仍然是封圣过程中不可或缺的一部分。例如,候选人的批评者可能会接受天主教会的评审,这是这个过程的一部分。
结论
怀疑主义是一种有价值的对抗手段,可以对抗那种只看最好结果的不合理的美好图景。虽然积极的态度是必不可少的,但通常最好的做法是“抱最好的希望,做最坏的打算”。
在实践中,应用怀疑主义通常意味着为团队成员创造空间,通过寻找证明(或反驳)团队假设的方法来质疑假设和断言。怀疑主义不仅仅是简单地对假设进行分类,还需要积极判断这些假设是否有效。
团队需要认识到,每一个需求,包括驱动架构设计的 QAR 都代表了关于价值的假设。当我们采用怀疑主义的方法时,目标之一是让这些假设变得明确,并有意识地设计实验,专门测试需求的价值。
怀疑并不代表对人的不尊重,这实际上是对在混乱的世界中为客户提供卓越成果的复杂性的尊重。这意味着需要认真对待团队为产出产品目标和 QAR 理想结果所做的努力。怀疑有助于团队以积极的方式对假设和隐藏的偏见提出质疑。
谨慎地应用怀疑主义是每一个软件开发团队必不可少的工具,它可以帮助他们在开发早期以更低的成本做出更好的决策。
原文链接:
https://www.infoq.com/articles/architecture-skeptics-guide/
相关阅读:
Netflix 构建可伸缩注解服务:使用 Cassandra、Elasticsearch 和 Iceberg
评论