架构师从开发者的角度看待事物的方式是不同的,就像气象学家以艺术家的角度看待云层的方式一样。这就是所谓的架构思想。不幸的是,太多的架构师认为架构思想仅仅是“对架构的思考”。
架构思想远不止于此。它是用架构的眼光或架构的观点看待事物的发展。像架构师一样思考有四个主要方面:首先,了解架构与设计之间的区别,并了解如何与开发团队合作以使架构正常工作;其次,它是关于拥有广泛的技术知识,同时又保持一定水平的技术深度,使架构师能够看到其他人看不到的解决方案和可能性。第三,它是关于理解,分析和协调各种解决方案和技术之间的折衷。最后,了解业务驱动程序的重要性以及它们如何转化为架构的问题。
在本章中,我们探讨了像架构师一样思考和用架构眼光来看事物的四个方面。
架构与设计
架构与设计之间的差异通常令人困惑。架构设计从哪里结束,又从那里开始?与开发人员相比,架构师应承担哪些责任?像架构师一样思考是在理解架构与设计之间的区别,并理解二者如何紧密集成以及形成业务和技术问题的解决方案。
请考虑图2-1,该图说明了架构师与开发人员相比,所承担的传统职责。如图所示,架构师负责诸如分析业务需求以提取和定义架构特征(“ -ilities”),选择哪种架构模式和样式适合问题领域。以及创建组件(架构的组成部分)之类的活动。然后将通过这些活动创建的工件移交给开发团队,该团队负责为每个组件创建类图,创建用户界面交互,以及开发和测试源代码。
图2-1。传统架构与设计
传统的责任模型如图2-1所示,这里存在几个问题。实际上,此插图准确地说明了为什么架构很少起作用。具体而言,是单向箭头穿过架构师与开发人员分隔开的虚拟和物理障碍,从而导致与架构相关的所有问题。架构师有时不会向开发团队做出决策,而开发团队所做的决策却很少使架构变更回到架构师那里。在此模型中,架构师与开发团队断开了联系,因此架构很少提供了最初打算要做的设计。
为了使架构有效,我们必须打破架构师和开发人员之间存在的物理和虚拟障碍,从而使架构师和开发团队之间形成牢固的双向关系。架构师和开发人员必须在同一个虚拟团队中才能进行这项工作,如图2-2所示。该模型不仅有助于架构与开发之间的强大双向通信,而且还允许架构师为团队中的开发人员提供指导和培训。
图2-2。通过协作使架构工作
与传统的瀑布式静态和刚性软件架构方法不同,当今系统架构会演变成项目的每个迭代或阶段。架构师与开发团队之间的紧密合作对于任何软件项目的成功都是至关重要的。那么架构从什么时候结束架构设计呢?永远没有结束!它们都是软件项目中生命周期的一部分,必须始终保持同步彼此为了客户成功。
技术广度
技术细节的范围在开发人员和架构师之间有所不同。与必须拥有大量技术深度才能完成工作的开发人员不同,软件架构师必须具有相当多的技术广度才能像架构师一样思考并以架构的观点看待事物。图2-3中的知识金字塔说明了这一点,该知识金字塔封装了世界上所有的技术知识。事实证明,技术人员应重视的信息类型随职业阶段的不同而不同。
图2-3。代表所有知识的金字塔
如所示图2-3,任何个人都可以分区中的所有知识分为三个部分:你知道的东西,你知道你不知道的东西,你不知道你不知道的东西。
您知道的东西包括技术人员每天用来执行其工作的技术,框架,语言和工具,例如将Java理解为Java程序员。你知道你不知道的东西包括技术人员所了解或听说过的东西,但很少或没有专门知识。Clojure编程语言是这种知识水平是一个很好的例子。大多数技术人员都听说过 Clojure,并且知道这是一种基于Lisp的编程语言,但是他们无法使用该语言进行编程。你不知道你不知道的东西 是知识三角中最大的部分,包括全部技术,工具,框架和语言,这将完美解决技术人员要解决的问题,但是技术人员甚至不知道这些问题的存在。
开发人员的早期职业生涯专注于扩展金字塔的顶端,以积累经验和专业知识。这是早期的理想焦点,因为开发人员需要更多的视野,工作知识和动手经验。扩大顶部之后顺便扩大了中间部分。随着开发人员遇到更多技术和相关工件,它增加了他们不知道的东西。
在图2-4中,扩展金字塔的顶部是有益的,因为专业知识很重要。但是,您知道的东西,也是您必须维护的东西——在软件世界中没有什么是静态的。如果开发人员成为Ruby on Rails的专家,那么如果他们忽略Ruby on Rails一两年,那么这些专业知识将不会持续。金字塔顶端的事物需要时间投入才能保持专业知识。最终,一个人的金字塔顶的大小就是他们的技术深度。
图2-4。开发人员必须保持专业知识才能保留
但是,随着开发人员过渡到架构师角色,知识的性质也会发生变化。架构师的价值很大一部分是对技术以及如何使用技术解决特定问题的广泛理解。例如,作为一名架构师,理解一个特定问题有五个解决方案比仅拥有一个专门知识更为有益。对于架构师来说,金字塔最重要的部分是顶部和中间部分。如图2-5所示,中间部分深入底部的深度代表了架构师的技术宽度。
图2-5。某人知道的是技术深度,而某人知道的是技术广度
作为一名架构师,广度比深度更重要。由于架构师必须做出使功能与技术约束相匹配的决策,因此对各种解决方案的广泛了解非常有价值。因此,对于架构师而言,明智的做法是牺牲一些来之不易的专业知识,并利用这段时间来扩大他们的业务范围,如图2-6所示。如图所示,某些专业领域将保留,可能在特别令人愉悦的技术领域,而其他领域则将萎缩。
图2-6。增强了架构师角色的广度和收缩深度
我们的知识金字塔说明了架构师与开发人员相比在根本上有何不同。开发人员将整个职业生涯都花在磨练专业知识上,而转变为架构师的角色意味着这种观点的转变,这对许多人来说都是困难的。反过来,这导致了两个常见的功能失调:首先,架构师试图在各个领域保持专业知识,在这些领域都没有成功,并且自己在过程中参差不齐。其次,它表现为过时的专业知识 -错误的感觉,过时的信息仍在前沿。我们经常在大型公司中看到这种情况,在大型公司中,创建公司的开发人员已经担任领导职务,但仍然使用古老的标准做出技术决策(请参见“反面模式”)。
架构师应关注技术的广度,以便他们有更大的思想可以用来绘制蓝图。过渡到架构师角色的开发人员可能必须改变他们查看知识获取的方式。每个开发人员在整个职业生涯中都应考虑平衡他们的深度与广度知识组合。
反面模式
在野外通常会观察到一种行为反模式,即“ 冰冻穴居反面模式”,它描述了一个架构师,他总是对每种架构都回想起他们对宠物的非理性关注。例如,尼尔(Neal)的一位同事开发了一个具有集中式架构的系统。但是,每次他们将设计交付给客户架构师时,始终存在的问题是“但是如果我们失去意大利,该怎么办?” 几年前,一个怪异的通讯问题使总部无法与其在意大利的商店进行通讯,从而带来了极大的不便。虽然重现的机会非常小,但架构师对这种特殊的架构特性非常着迷。
通常,这种反模式体现在过去因错误的决策或意外事件而被毁灭的架构师中,这使他们在未来尤其谨慎。尽管风险评估很重要,但它也应该是现实的。了解真正风险与感知技术风险之间的区别是架构师正在进行的学习过程的一部分。像架构师一样思考需要克服这些“冰冻穴居人”的想法和经验,查看其他解决方案,并提出更多相关的问题。
分析权衡
像架构师一样思考,就是要在每种解决方案(无论是技术解决方案还是其他解决方案)中进行权衡,然后分析这些权衡以决定最佳解决方案。 引用Mark(您的作者之一):
架构是您无法使用Google的东西。
架构中的所有事物都需要权衡取舍,这就是为什么宇宙中每个架构问题的著名答案都是“取决于”。尽管许多人对此答案感到越来越烦恼,但不幸的是,这是事实。您无法找到REST或消息传递是否更好,还是微服务是否是正确的架构样式的答案,因为这确实取决于它。它取决于部署环境,业务驱动因素,公司文化,预算,时间表,开发人员技能集以及许多其他因素。每个人的环境,处境和问题都不尽相同,因此架构为何如此困难。 引用尼尔(另一位作者)的话:
在架构中没有正确或错误的答案,只有权衡取舍。
例如,考虑一个物品拍卖系统,如图2-7所示,在该系统中,有人为要拍卖的物品出价。
图2-7。权衡的拍卖系统示例-队列还是主题?
该Bid Producer服务生成从投标人的投标,然后发送该投标金额的Bid Capture,Bid Tracking和Bid Analytics服务。这可以通过使用点对点消息传递方式的队列或通过发布和订阅消息传递方式的主题来完成。架构师应该使用哪一个?您无法找到答案。架构思想要求架构师分析与每个选项相关的权衡,并根据具体情况选择最佳选项。
物品拍卖系统的两个消息传递选项如图2-8和2-9所示,其中图2-8说明了主题在发布和订阅消息传递模型中的使用,图2-9说明了使用点对点消息传递模型中的队列数量。
图2-8。使用主题在服务之间进行通信
图2-9。使用队列在服务之间进行通信
图2-8中此问题的明显优势(看似显而易见的解决方案)是架构可扩展性。该Bid
Producer服务仅需要一个主题的单个连接,这与图2-9中的队列解决方案不同,后者Bid
Producer需要连接到三个不同的队列。如果Bid
History由于要求向每个出价者提供他们在每次拍卖中所做的所有出价的历史记录而需要向该系统添加新的服务,则无需对现有系统进行任何更改。Bid History创建新服务后,它可以简单地订阅已经包含出价信息的主题。但是,在图2-9所示的队列选项中,该Bid
History服务Bid
Producer将需要一个新队列,并且需要对其进行修改以向该新队列添加其他连接。这里的要点是,使用队列需要在添加新的出价功能时对系统进行重大更改,而使用主题方法时,在现有基础架构中根本不需要进行任何更改。另外,请注意Bid Producer与主题选项之间的联系更加分离- Bid Producer不知道如何使用出价信息或由哪些服务使用。在队列选项中,他们Bid Producer确切地知道如何使用出价信息(以及由谁使用),因此更加与系统耦合。
通过这种分析,似乎很清楚使用发布和订阅的主题方法消息传递模型是显而易见的最佳选择。但是,引用Clojure编程语言的创建者Rich Hickey:
程序员知道一切的好处,而一无所获。架构师需要两者兼得。
从架构上考虑不仅要考虑给定解决方案的优势,而且还要分析与解决方案相关的负面因素或权衡取舍。继续拍卖系统示例,软件架构师将分析主题解决方案的负面影响。在分析差异时,首先请注意图2-8中的主题,任何人都可以访问投标数据,这可能会引起数据访问和数据安全性问题。在图2-9所示的队列模型中,发送到队列的数据只能接收该消息的特定使用者可以访问该消息。如果黑客服务确实在队列中侦听,则相应的服务将不会收到这些反馈,并且将立即发送有关数据丢失(因此可能导致安全漏洞)的通知。换句话说,很容易窃听一个主题,而不是排队。
除安全性问题外,图2-8中的主题解决方案仅支持同类合同。所有收到投标数据的服务必须接受相同的合同和一组投标数据。在图2-9中的队列选项中,每个使用者可以针对其所需数据拥有自己的合同。例如,假设新Bid History服务要求当前的要价以及出价,但是其他服务则不需要该信息。在这种情况下,将需要修改合同,从而影响使用该数据的所有其他服务。在队列模型中,这将是一个单独的渠道,因此,一个单独的合同不会影响任何其他服务。
图2-8中所示的主题模型的另一个缺点是,它不支持监视主题中消息的数量,因此不支持自动缩放功能。但是,使用图2-9中的队列选项,可以分别监视每个队列,并以编程方式将负载均衡应用于每个出价使用者,以便可以自动缩放彼此的独立性。注意,这种权衡是特定于技术的,因为高级消息队列协议(AMQP)可以支持编程负载平衡和监视,因为交换(生产者发送到的内容)和队列(消费者收听的内容)之间是分开的。
考虑到这种折衷分析,现在哪个是更好的选择?那答案呢?这取决于!表2-1总结了这些折衷方案。
这里的要点是,软件架构中的所有内容都需要权衡:优点和缺点。像架构师一样思考是在分析这些折衷,然后问“哪个更重要:可扩展性或安全性?” 不同解决方案之间的决定将始终取决于业务驱动因素,环境以及许多其他因素。
理解业务驱动
像架构师一样思考是在理解系统成功所需的业务驱动因素,并将这些需求转换为架构特征(例如可伸缩性,性能和可用性)。这是一项艰巨的任务,需要架构师具有一定程度的业务领域知识,并需要与关键业务利益相关者建立健康,协作的关系。在本书中,我们专门讨论了几章。在第4章中,我们定义了各种架构特征。在第5章中,我们描述了识别和限定架构特征的方法。在第6章中,我们描述了如何测量这些特征中的每一个因素,以确保满足系统的业务需求。
平衡架构设计和动手编码
架构师面临的困难任务之一是如何在动手编码和软件架构之间取得平衡。我们坚信,每个架构师都应该编写代码,并能够保持一定水平的技术深度(请参阅“技术广度”)。尽管这看起来很容易,但是有时却很难完成。
在动手编码和成为软件之间寻求平衡的第一个技巧 。架构师正在避免瓶颈陷阱。当架构师在项目的关键路径(通常是基础框架代码)中拥有代码所有权并成为团队的瓶颈时,就会发生瓶颈陷阱。发生这种情况是因为架构师不是专职开发人员,因此必须在扮演开发人员角色(编写和测试源代码)和架构师角色(绘制图表,参加会议以及参加更多会议)之间取得平衡。
作为有效的软件架构师,避免瓶颈陷阱的一种方法是,将关键路径和框架代码委托给开发团队中的其他人员,然后着重于对业务功能(服务或交互)进行一到三遍迭代。这样做会产生三件事。首先,架构师获得了编写生产代码的动手经验,而不再成为团队的瓶颈。其次,关键路径和框架代码已分发给开发团队(它属于该开发团队),从而使他们拥有所有权并更好地理解系统的较难部分。第三,也许是最重要的。假设架构师无法与开发团队一起开发代码,软件架构师如何还能保持动手并保持一定水平的技术深度?架构师仍然可以通过四种基本方法动手工作,而不必“在家进行编码”(尽管我们建议您也在家进行编码)。
第一种方法是频繁进行概念验证或POC。 这种做法不仅要求架构师编写源代码,而且还通过考虑实现细节来帮助验证架构决策。例如,如果架构师在尝试在两个缓存解决方案之间做出决定时陷入困境,那么做出此决定的一种有效方法是在每个缓存产品中开发一个工作示例并比较结果。这使架构师可以直接看到实施细节以及开发完整解决方案所需的工作量。它还允许架构师更好地比较架构特征,例如不同缓存解决方案的可伸缩性,性能或总体容错能力。
我们在进行概念验证工作时的建议是,架构师应尽可能编写最佳的生产质量代码。我们推荐此做法有两个原因。首先,通常一次性的概念验证代码会进入源代码存储库,并成为其他人遵循的参考架构或指导示例。架构师想要做的最后一件事就是将他们的一次性代码松散地表现出来。第二个原因是,通过编写生产质量的概念证明代码,架构师可以练习编写高质量,结构良好的代码,而不是不断开发不良的编码实践。
架构师可以动手的另一种方法是解决一些技术债务或优化架构的故事,从而使开发团队腾出精力来处理关键的功能用户故事。 这些故事通常优先级较低,因此,如果架构师没有机会在给定的迭代中完成技术债务或架构的故事,那就不是世界末日了,通常也不会影响迭代的成功。
同样,在迭代中进行错误修复是维护动手编码同时又对开发团队有所帮助的另一种方法。 虽然肯定不是很吸引人,但是这种技术使架构师能够确定问题和弱点可能存在于代码库甚至架构中。
通过创建简单的命令行工具和分析器来利用自动化来帮助开发团队完成日常任务,这是在保持动手编码技能的同时又使开发团队更高效的另一种好方法。寻找开发团队执行的重复性任务并使流程自动化。开发团队将感谢您的自动化。一些示例是自动源验证器,以帮助检查其他棉绒测试,自动清单和重复的手动代码重构任务中找不到的特定编码标准。
自动化也可以采用架构分析和适应性功能的形式,以确保架构的活力和合规性。例如,架构师可以在Java平台的ArchUnit中编写Java代码以自动执行架构合规性,或者编写自定义适应性功能以确保架构合规性,同时获得动手经验。我们将在第6章中讨论这些技术。
作为一名架构师,动手实践的最后一种方法是进行频繁的代码审查。尽管架构师实际上并未编写代码,但至少它们包含在源代码中。此外,进行代码审查还有其他好处,即能够确保符合架构并在团队中寻求指导和指导的机会。
原文 :https://www.jianshu.com/p/18c226a10304
声明:本资料仅供学习交流严禁使用于任何商业用途!请购买正版图书:https://www.oreilly.com/library/view/fundamentals-of-software/9781492043447/cover.html
资料整理和翻译:杨传池Chris IT老兵,人生三大爱好(爱好喝茶,喝酒和喜欢做梦)
10+年的软件研发和项目管理经验;
7+年大型房产信息化、数字化咨询经验;
50+人以上研发团队管理,擅长团队管理和人才梯队建设;
熟悉研发管理、工程构建、体系建设、DevOps和领域建模,掌握IT研发价值链和工具链。