想象一下飞过的体系结构审查。 一位建筑师走进来,环顾四周,掩饰着自己的双筒望远镜。 他提供的评论通常过于笼统或脱离上下文。 评论时常常会充耳不闻或保持沉默。 他们很少会帮助任何人。 每个程序员都很害怕。 每个建筑师也很害怕。
据说软件架构师应该像园丁而不是指挥官那样思考。 前者可以塑造,管理和去除杂草,而后者则可以定义和支配。 架构师应该策展而不是命令,塑造而不是定义,并鼓励讨论而不是标签。 但是,如何使其工作?
在WSO2,我已经进行了八年多的体系结构审查。 WSO2拥有广泛的产品组合,包括众所周知的WSO2 ESB , WSO2 API Manager和WSO2 SP 。 在过去的八年中,我们对许多产品和功能进行了辩论,设计,改进和重新设计。
我们设计过程的关键部分是架构不是由建筑师完成的。 我们没有一组架构师来决定由他人实施的架构蓝图。 相反,设计是由编写代码的团队完成的。 建筑师修复,抱怨,策划和改进设计。 我们有一个架构团队,但是他们是向导和看门人,而不是独裁者。
在接下来的演讲中,Gregor Hohpe很好地抓住了这个想法。
https://www.youtube.com/watch?v=qVyt3qQ_7TA
在短期内,指示架构更快,甚至可能更便宜。 是真的。 但是,从长远来看,我们可以通过让他们自己思考,让他们发展架构,有时让他们犯错误来组建更好的团队。 当我们专注于团队时,随着时间的推移他们会变得更好。 首先,架构是团队的想法,因此执行变得更加容易。
但是,架构审查也有其陷阱。 Paul( @pzfreo )过去曾用架构来称呼此驱动器,建筑师可以走进来,聆听,发表评论并继续前进。 作为一名建筑师,您可以轻松地检查,投诉和分解设计。 但是,如果您不小心,可能会使团队感到困惑,并且不确定该怎么做。
我们通过列出共享体系结构主体来解决此问题。 这些是每个人都同意的原则。 建筑师通过说由于原则X不好,从而给出了反馈。原则指导着我们,并使我们的讨论根深蒂固。 他们还避免了永远进行的哲学斗争。 最后,如果设计师从未听说过该原理,那么对他来说很容易学习。
以下是其中一些原则。 一些是众所周知的,而另一些则是我们艰难的选择。
基本的
原则1: KISS(请保持简单)和“一切都应尽可能简单,但不要简单。” 这个想法是使用最简单的解决方案。
原则2: YAGNI( 您将不需要它) —在需要它之前,不要构建它。
原则3:爬行,行走,奔跑。 换句话说,使其工作,使其更好,使其更出色。 进行迭代开发-进行敏捷的迭代开发。 对于每个功能,创建里程碑(最多2周)并进行迭代。
原则4:构建稳定,高质量产品的唯一方法是通过自动化测试。 具有自动化测试的创造力; 一切都可以自动化! 设计时请考虑一下。
原则5:始终考虑投资回报率(ROI),并将最大的精力投入到最大的影响力上。
原则6:了解您的用户并相应地平衡您的工作。 对于大多数产品,将有成千上万的最终用户,20个扩展产品的开发人员以及100个设置产品的DevOp人士。 例如,不要花几个月的时间为不太可能使用它的UI for DevOp(他们喜欢脚本!)。 这是原则5的特例。
原则7:尽可能独立地设计和测试功能。 设计时请考虑一下。 从长远来看,这将省去很多麻烦,否则您将无法在构建所有组件之前测试系统。 同样,遵循这一原则,您的发布也会更加顺畅。
原则8:监视Google Envy。 我们都喜欢闪亮的设计。 将您永远不需要的功能和解决方案带入体系结构很容易。
选择功能
原则9:无法思考用户将如何充分使用我们的产品。 因此,请接受MVP(最小可行产品)。 这样做的目的是找出很少的用例,仅提供支持这些用例的功能,交付产品并根据反馈和经验来塑造未来的产品。
原则10:如有疑问,请尽量减少功能。 许多功能从未使用过,也许您应该保留扩展点。
原则11:等待有人提出要求(例如,不是交易破坏者的功能,请等到需要时使用)
原则12:如果客户要求的功能弄乱了整体形象,则应勇于与客户抗争。 找出更大的图景,尝试找到另一种解决问题的方法。 记住福特的名言“如果我问人们他们想要什么,他们会说更快的马。” 另外,请记住您是专家。 你应该领导。 做正确的事而不是受欢迎的事是领导者的工作。 用户稍后会感谢您。
服务器设计和并发
原则13:从硬件,操作系统到您的编程语言,了解服务器的工作方式。 优化IO调用数量是通往最佳架构的第一条指南灯。
原理14:了解关于同步的阿姆达尔定律。 线程之间共享的可变数据会降低程序速度。 如果可以,请使用并发数据结构,仅在必要时使用同步。 尝试尽可能少地握住锁。 如果您打算在拿着锁时阻止,请确保您知道自己在做什么。 如果它可以打破,它会。
原则15:如果您的设计是基于无阻塞,基于事件驱动的架构,则不要阻塞线程或从这些线程中进行IO。 如果这样做,系统将像slow子一样慢。
分布式系统
原则16:无状态系统具有可伸缩性和直接性。 尽可能了解并使用无共享架构 。
原则17:无论失败与否,消息传递只有一次很难,除非您同时控制客户端和服务器中的代码。 尝试设计您的系统以减少需求(例如,使用原则18)。 知道大多数承诺完全交付的系统都会在某个地方开一个角。
原则18:尽可能将操作实现为幂等操作。 这样就很容易恢复,并且至少可以交付一次。
原则19:了解CAP定理。 扩展交易很难。 尽可能使用补偿。 基于RDBMS的事务无法扩展。
原则20:分布式共识不扩展,组通信也不集群范围内的可靠消息传递。 一天中的任何一个的最大节点限制约为八个节点。
原则21:您永远无法隐藏分布式系统中的延迟和故障。 (请参阅《分布式计算的谬论》 )。
用户体验
原则22:了解您的用户并了解他们的目标:他是新手,专家还是临时用户? 他对计算机科学了解多少? 怪胎喜欢扩展点,开发人员喜欢样本和脚本,普通人喜欢UI。
原则23:最好的产品不需要手册。 它的使用是不言而喻的。
原则24:当您无法在两个选择之间做出选择时,请勿通过将其配置选项来传递问题。 您正在为用户和解决方案架构师加油。 他们比您对系统的工作原理了解得更少,他们如何决定? 最好的选择是找到每次都可行的选择。 次佳的选择是自动做出选择,次佳的选择是添加配置参数并设置合理的默认值。
原则25:始终对配置使用明智的默认设置。
原则26:设计不当的配置会引起很多混乱。 始终记录一些配置示例值。
原则27:询问配置值时,用户无需进行任何计算即可设置值(例如,不要求提供最大高速缓存条目数,而是要求应用于高速缓存的最大内存),这是用户可以从头上回答的事情
原则28:如果看到未知的配置,则会引发错误。 永远不要无视它。 静默的配置错误是调试时许多损失时间的根源。
难题
原则29:梦想新语言很容易,但是正确使用它们却很困难。 除非团队可以花至少十个人年,否则请不要这样做。 如果您仍然不确定,请阅读有关语言设计的五个问题 。
原则30:可组合的拖放UI很难,除非团队准备投入十个人年的时间,否则不要开始使用它。
最后,让我谈谈随着时间的推移我改变主意的事情。 在理想情况下,平台必须由正交组件组成,每个组件都处理一个方面(例如,安全性,消息传递,注册表,中介,分析)。 具有此类功能的系统将是最佳的。
不幸的是,很难达到那种状态。 甚至很难呆在那里。 严格执行此操作可能是一个错误,特别是在新功能的初始状态下,由于我们试图使所有事物正交,因此简单功能可以层叠成较大的更改。 有时,我们发现添加的功能毕竟没有用,然后所有其他工作都花光了。 最后,如果这导致多个团队之间进行谈判,则该功能可能永远无法完成。
事后看来,当我尝试删除它会导致相当大的复杂性时,我现在愿意忍受重复。 治愈可能比疾病还糟。
结论
作为建筑师,应该像加德纳(Gardner)一样思考,塑造,整理和清除杂草,而不是进行定义和构建。 您应该策划而不是命令,塑造而不是定义,并且应该鼓励讨论而不是标签。 尽管在短期内决定体系结构可能更便宜且更容易,但从长远来看,指导并让团队找到自己的方式会带来好处。
如果您不小心,则按架构进行飞行会更容易,在架构师中,设计师仅告诉他架构是错误的,而不是为什么它是错误的。 避免这种情况的一种方法是拥有一套被普遍接受的原则,这些原则将成为讨论的锚点,以及初学者的学习途径。