软件架构可能不是你想象的那个样子
软件架构在敏捷社区中存在争议。在许多人的经验中,架构只会导致毫无价值的会议和无关紧要的文件,“地图不是领土”的说法可以恰当地概括这一观点。然而,架构不佳的应用程序很快就会变得像被遗弃在路边的车辆一样,破损且无法修复。那么,在毫无意义的两极之间是否有一个有用的中间地带呢?
产生这个问题的一部分原因是,对于软件系统架构工作的成果来说,建筑设计是一个不恰当的比喻。对照建筑设计师的工作,这个词会让人联想到预示着乌托邦式美好未来的设计。但是,软件系统的架构远比建筑架构更富于变化。建筑物是静态的,建筑设计师的工作只做一次。软件,就其本质而言,是不断变化的、动态的;当它停止变化时,就开始走向死亡了。
为了更好地理解软件架构,我们有必要追溯下建筑师(architect)这个词的起源。它来自于古希腊词 arkitekton,即 ρχι-(arkhi-,“chief”)+ τ κτων(téktōn,“builder”)。建筑是由建造东西的人创造的。在建筑设计师的工作中,这种意义已经消失了。他们中的许多人从未浇筑过地基,也没有为建筑物搭过框架,更没有安装过水管或暖气管。设计和建造已经被分开了。但在软件领域却不是这样,构建方式会影响到构建内容,反之亦然。
1
软件架构关乎决策,而非结构
以建筑物作类比导致一些软件架构师过于关注结构和行为,而不是产生这些结构和行为的决策。这并不是说结构和行为不重要,而是它们是思想过程的结果。如果系统要随着时间的推移持续演进,就必须保留这个思想过程。知道某人为什么做某事与知道他们做了什么同样重要。如果代码组织得很好并且有注释的话,那么它们所做的事情应该很容易从代码中看出来,但是为什么要这样做却常常被忽略。
其原因是,软件的架构决策很少是一目了然的;几乎每一个架构决策都是在相互竞争的备选方案之间做出妥协。而且,有一些备选方案,如果你不尝试一下,看看它们是如何工作的,就很难看出它们的优点。知道试过什么,放弃了什么,往往比知道什么有效更有价值。有句老话说得好,好的判断来自于经验,而大部分的经验来自于坏的判断。
这也是为什么软件架构师必须仍然是开发人员的原因之一;如果不开发和测试一些东西,他们就无法理解或预测系统中的影响因素。软件架构师不应该作为某种酬金,付给那些已经从活跃的开发中退出,但拥有的知识被组织认为仍然有价值的人;它的意义应该不止于此。架构工作需要对系统有足够的了解,以便能够提出有益于质量属性的假设,还需要有编写代码和设计测试以评估假设的专业知识(或与能够评估这些假设的团队成员紧密合作)。
2
架构是一项技能,而架构师不是一种角色
事实上,就工作性质而言,使用像软件架构师这样的头衔传达了错误的信息。现实情况是,很多软件开发人员都在做架构工作,只是他们没有意识到这一点。只要他们对如何满足质量属性做出决策,就会影响到系统的架构。充分了解背后的决策如何影响系统实现质量目标的能力,是改进系统架构的第一步。
那么,人们需要掌握什么样的技能来提高其架构工作的质量呢?有以下几个方面:
多关注质量属性,这是好的架构应该解决的关键的横切(cross-cutting)需求。功能需求很容易受到团队关注,因为它们往往是有形的,甚至是系统帮其用户做的一些肉眼可见的事情。但是,系统的质量属性决定了它是否能长期存在下去,如可扩展性、性能、安全性、承载能力和可维护性,等等。
有能力将整个系统的问题概念化并加以解决。质量属性往往是由能影响整个系统而不是仅仅影响某个部分的因素决定的。虽然模块化设计和关注点分离对构建良好的系统至关重要,但它们也使团队成员更难对系统有一个整体的认识。
理解系统的完整生命周期。这就要求我们不仅要有开发系统的经验,还要有测试系统、部署系统、在生产环境中运行系统、长期维护系统的经验,以及在系统需要重大创新时对其进行实质性的现代化改造。了解系统的生命周期以及它如何应对变化,对于做出明智的决策,限制技术债务至关重要,因为随着时间的推移,技术债务会威胁到系统的生存。
平衡关切以及调和折中的能力。架构工作很少会有正确答案。架构经常涉及到在相互冲突的质量属性要求(QAR)和约束条件之间做出权衡。
从经验中学习和合成新方法的能力。这种能力是指直接进行尝试(运行实验),并将实验结果概括为可以进一步指导实验的原则。其中一些原则采取了“标准”形式。这个术语有点误导性,因为标准需要不断地通过实验来检验,以确定它们何时不再有用。我们看到,许多开发人员对组织的“标准”感到沮丧,因为它们在过去某个时候是有意义的,但现在却把团队困在了过去。
展示领导力的能力。能够提出关注点,能够让持有不同观点的人展开讨论并达成共识,这有助于团队面对并克服复杂的架构问题。团队中的任何人都可以这样做,而任何负责架构设计的人都必须做到这一点。
3
架构意味着持续探索
现代软件应用程序架构设计是一项基础性的探索活动。现如今,构建应用程序的团队每天都会遇到新的挑战:前所未有的技术挑战,以及为客户提供解决新问题和其他各种问题的新方法。这种持续性的探索意味着架构不能根据过去的经验预先确定;团队必须找到满足质量要求的新方法。
关于探索对于架构发现的重要性,请考虑这样一个例子:假设你是一个从事软件系统开发工作的团队的一员。根据最初的设计,该系统是为了处理存储在 SQL 数据库中的结构化表格数据。现在,这个系统需要增强,以便可以处理非结构化数据,包括图像和视频,而且数据量预计会比系统目前处理的多得多。你考虑在技术栈中引入 NoSQL 数据库来处理新的数据类型,但由于你的团队在这项技术上没有多少经验,所以要选择合适的数据库产品,进行配置并满足新的数据量要求,实验必不可少。
在团队解决这些技术问题的过程中,关于哪些方法能最好地满足所期望的 QAR,他们形成了自己的假设,这些假设会随着时间变化。他们构建一部分解决方案来检验这些假设,并根据结果做出决策。这些关于如何满足 QAR 的决策叠加起来就是系统的架构。团队可能会以不同的方式沟通这些决策,包括使用文档和图表。但是,文档和图表不是架构,重要的是决策以及做出决策的原因。
关于这些决策,以下信息很重要:
如果有必要的话,说明推翻一项决策的成本。如果你必须更换一个服务、一个 DBMS、甚至一个框架,那么要知道更换的代价有多大。在某些情况下,这可能意味着重写应用程序。
清楚地阐明所有限制或假设。了解使用约束和假设可能会帮助到将来要对你的工作进行更新的团队。例如,知道你做了并发用户个数不超过 X 的假设,并导致你对并发线程或进程做出某些决定,这有助于你未来的同事了解,如果超过这个约束,他们可能需要做出什么改变。
你是如何满足具体的质量属性要求(QAR)的。对于每个 QAR,你应该描述你做了什么来确保它可以得到满足,不仅仅是在理论上,还要说明你运行了什么测试来证明。链接到具体的测试用例及其相关的自动测试。这样,当 QAR 发生变化时,就能够很容易地重新评估系统的架构质量。
在做出决策之前,你考虑过哪些选项。知道你考虑了什么以及放弃了什么,往往比知道你最终的决策更有用;它展示了你的思考过程,其他人可以从中看出你做决定时可能受到了什么样的限制。如果这些限制将来消失了,那么知道你为什么做出某些决策将有助于未来的开发者做出更好的决策。
图 1:QAR、决策和技术债务的关系
在知情的情况下产生了哪些技术债务。有些决策将不可避免地导致技术债务;例如,使用 SQL 数据库来满足可靠性目标的决策会对技术债务有一些副作用(见图 1)。现在,早已成为过去式的“千年虫问题”就源于开发人员当时有意识的决策。为了减少了数据存储、内存使用和处理时间,他们在存储标准日期时没有存储世纪数据。产生这个问题的原因是,他们没有想到应用程序会存在这么久,在那些限制不合时宜之后还存在很长时间。如果他们能更准确地传达他们的决策并描述潜在的影响,可能人们就不会在上个世纪末出现如此强烈的反应。
转载请在文章开头和结尾显眼处标注:作者、出处和链接。不按规范转载侵权必究。
未经授权严禁转载,授权事宜请联系作者本人,侵权必究。
本文禁止转载,侵权必究。
授权事宜请至数英微信公众号(ID: digitaling) 后台授权,侵权必究。
评论
评论
推荐评论
暂无评论哦,快来评论一下吧!
全部评论(0条)