软件架构构成了一个系统的骨架。它定义了当面对不一样的功能性和非功能性需求时的系统行为。一方面,传统瀑布式方法对项目开发的全部阶段提出了硬性约束要求,所以传统瀑布式方法显得僵化。另外一方面,敏捷运动让咱们拥抱改变,即便是处于开发阶段后期的改变。尽管咱们正推进本身从僵化的开发模式迈向更灵活的模式,软件架构因为其系统骨架的定位,自然地对变化敏感。所以关键之处在于,敏捷运动拥抱的软件架构必须是可持续的——具有可持续概念的软件架构,支持在项目复杂度不断增长的同时,系统能以渐进式的、简单的以及可维护的方法进行扩展。数据库
在这篇文章里,我回顾了本身在传统瀑布式软件架构和敏捷软件架构下的工做经历。描述了二者在如下三个方面表现出来的类似性及差别性:编程
软件架构扮演的具体角色;缓存
软件架构的时间跨度;架构
软件架构的输出。编程语言
什么是软件架构?工具
软件架构的定义(实际上你也能添加你本身下的定义)成百上千。存在这么多种定义的缘由在于每一个人都是基于自身情境下定义。我对IEEE给出的定义特别推崇,这个定义描述的基本概念很是形象化。此外,该定义描述出了软件架构的精髓本质,同时适用于瀑布式和敏捷流程,而不是只能匹配某一个。在本文的后续部分,我会引述到该定义:测试
一个系统的基本组织结构、基本组成构件和互相之间的关系,以及构件于外部环境间的关系。同时,软件架构为后续的设计和架构演化提供了指导性原则。spa
瀑布式软件架构架构设计
传统瀑布式开发的特征在于其由一系列有明确的开始和结束时间的阶段构成,每一个阶段包含肯定的活动集。全部阶段串接在一块儿,每一个阶段严重依赖于前一个阶段的交付产出。图1阐述了瀑布式开发过程涉及到的常见阶段。设计
软件架构工做一般在软件需求肯定后开始启动,认为在此时,关于系统应作什么,已经肯定好了。下一步是审查负责肯定软件架构的人以及当前阶段的实际输出结果。
传统软件架构
软件架构实践中一般由软件架构师完成。软件架构师拥有丰富的技术知识和经验——每每是由公司中已经达到必定等级的开发人员晋升而来的。软件架构师负责分析软件需求,并基于这些需求为将来系统的演化作某些技术决策。许多公司一般是一个项目对应一个软件架构师,但在一些更大的公司里,软件架构师们可能以团队的形式共同合做。当项目所在领域很是复杂或者项目的周期很长,好比长达2到3年甚至更久时,一般状况下就会有软件架构师团队。不是全部的公司都有指定的软件架构师角色——许多公司把这部分职责委托给他们的高级开发人员承担。在本文的后续部分,我所谈的是指由软件架构师执行的具体活动项,而不是执行活动项的人,除非另有明确说明。
传统的软件架构师有4大主要特征:
关注大格局——软件架构师应当思考,系统在将来的几个月(有时间甚至是几年)会变成什么样子。此外,他还应当一并考虑到全部其余相关的系统(好比第三方系统和数据库),以及系统间的通信问题。
听从性导向——软件架构师应考虑到可能的听从性问题。可能的有法律规范、许可证、标准或其它,身为软件架构师他应确保系统在将来可以知足这些相当重要的标准。
绘制蓝图——软件架构师的一项重要交付是从不一样角度描述架构设计的文档和图表集。开发团队利用这些交付件开始进行系统构建。
不太多的实际操做经验——软件架构师的工做目标是产出最终文档以供开发人员使用。尽管软件架构师一般拥有开发经验,但他不多参与到开发过程当中去——而是指导开发人员构建已设计好的系统。在某些时候他甚至可能调去参加另外一个项目,留下开发人员本身完成开发。
真实世界之痛
我曾经为全球最大的啤酒公司的其中之一作一个软件项目。项目用了2到3年的时间,使用典型的瀑布式方法,在不一样的阶段有对应的负责人——软件架构师、开发人员、测试人员。我是一个小团队里的开发,咱们根据软件架构师传达的指示和指导意见,执行系统的开发工做。最初软件架构师提供在场支持,但过了不久他转到另外一个项目去了,所以就减少了在这个项目上的工做量。当新的依赖不断出现,有时候很难照着拟定的软件架构推动,由于和已有架构设计的规定不相符。尽管尝试过让咱们的高级开发人员接管架构设计,但项目仍是逐渐成为所谓的意大利面条式代码(spaghetti code),每一个人都惧怕去改代码,由于极可能在哪一个地方就出问题了。遗憾的是,项目已经来不及作任何重大的改变了,没法回到正轨,因此尽管项目最终发布了,但往后仍然被停掉了。
敏捷运动
传统的瀑布式架构的性质是一次性活动,活动有明确的起止时间,而敏捷软件架构是一个持续不断的过程,也许没有终点。敏捷软件架构使咱们能够对架构设计实施更改,若是须要的话,能够按期实施。拥抱变化的一大机制是在项目里运用迭代和增量开发。在Scrum里,这些迭代被称之为sprint,如图2所示,典型的一个sprint的周期约为2-4星期。周期窗口如此之小,因此能对提出的任何改变作快速讨论。此外,敏捷很是关注团队的协做,团队成员之间存在的任何问题应当即解决掉,以防止出现误解及沟通不顺畅的状况。
敏捷运动使得人们能够拥抱项目中的变化,但它并无告诉你应当以多快的速度响应变化。软件架构设计做为系统的骨干支柱,对变化很是敏感。好比说,在项目中期,你以为你能更改项目使用的平台或编程语言吗?这样的更改,即使很罕见,也须要经过多轮的迭代才能完成。这种改变甚至能把你从新拉回到项目的启动阶段。当牵扯到软件架构设计时,有些类型的变化就比较苦楚,须要较多的执行时间。
敏捷软件架构师
Scrum定义了三类角色:
产品负责人(product owner)——负责提供具体业务领域的信息
scrum master——负责推动团队的沟通和协做
开发团队(development team)——负责实现用户story以及软件编写
为了将传统软件架构师角色转换为适配敏捷世界,咱们须要先分析下一些可能的变种。构建Scrum团队的一个方法是让开发团队和一个单独的软件架构师团队一块儿紧密地合做。图3说明了多Scrum团队的构建场景。
凭这种方法确实能够完成团队的构建,但存在两个问题:
软件架构师团队可能会变成需求方,而开发团队成为实现方,这正是瀑布式方法下出现的典型状况。最后呈现的结果是,软件架构师定义项目的前景,留给开发人员去完成实现。若是开发人员没有足够的参与,不被尊重对待,他们的积极性被降低。
上面这样作的后果,致使一部分开发人员可能也想加入软件架构师团队,这样就可以给其余开发人员分配工做。Trustpilot提供了一个例子,他们有一个核心团队和开发团队,但总的来讲却破坏了工做风气和彼此的协做,因而他们把核心团队的全部成员都移到一个开发团队中去,收到了积极的效果。
另外一种作法是将软件架构师直接置于开发团队中。
这种状况下,敏捷软件架构师的责任发生了一些变化:
在当前和宏图愿景之间保持平衡——敏捷软件架构师须要同时思考两点,当前开发过程当中发生的事情以及将其与整个系统的宏图愿景进行对齐。
实际操做经验——敏捷软件架构师同时也是开发人员,参与系统的实现工做。这样使得敏捷软件架构师可以得到关于作出的架构决策的第一手反馈信息。
建立原型,明智决策——当须要作出重大的技术决策时,快速建立原型能够揭示这个决策是否可行以及它会如何影响到现有系统。再者,与全体开发团队的沟通很是关键,团队合做的效果远好于独自一人埋头苦干。
关注可持续性——极其重要的一点是,架构设计决策造就可持续的软件架构,从长期来看,可持续的软件架构能很好地支撑起项目。我的责任感和情怀是其中不可或缺的一部分。敏捷软件架构师是开发团队的一份子,因此如前所述他能获得本身所作决策的第一手反馈。相比瀑布式方法,软件架构师的决策传递到开发团队并由开发团队负责执行,敏捷方法提高了我的责任感。
若是想在不一样的开发团队(也多是不一样的项目)之间共享软件架构师资源,能够选择构建拥有独立软件架构师团队的组织结构。除此以外,若是从事的领域很复杂,须要考虑的视角不少,也能够采用拥有独立软件架构师团队的组织结构。在这类状况,必须保证软件架构师与开发人员的合做紧密,并展示出了对开发人员的支持。敏捷方法关注协做,将软件架构师从开发人员从分离出来,使得协做变得困难了。结果开发过程变得更贴近于瀑布式模型。我我的更青睐第二种变体,在那软件架构师处于开发团队中,所以团队成员之间的沟通交流更有效。在一个更高的层次上架构师仍能(也应当能)协调一致。
敏捷软件架构的时间跨度
敏捷软件架构的一个重要方面是什么时候开始进行架构设计。不一样于瀑布式模型对每个阶段都作了明肯定义,在敏捷的世界里,不存在一个全部人都赞成开始的肯定的时间点。一个典型的作法是引入sprint #0,这是一个特殊的sprint,开发环境已经配置好了,一些重要的决策已肯定(好比编程语言、平台、数据库等等)。
这种方法有个常见的陷阱,即人们倾向于延长sprint #0,由于总会发现事情“几乎就快准备好了”。常常听到“再给一个星期,咱们就能开始进入常规的sprint”这样的话。不少时候你会发现本身已经在开发系统了,但用户story还没见着,由于“提早帮忙完成功能实现真的很酷”。这种状况你应当预先商定出sprint #0的结束日期,能够设置在一个常规sprint的持续周期内,或者相似相近的时间。
可能有人会疑惑,万一到常规sprint应启动的时候,还没完成架构设计,要怎么办。嗯,其实这也不要紧。事实上有可能永远不会有准备好的一天。那也不要紧。软件架构设计是一个持续不断的过程。你应当常常性地从新看回来,去修正系统的骨干。在架构设计不能给予支持保证时,你是没法进行系统开发的。Simon Brown说:
敏捷团队不必建立敏捷软件架构。但一个好的架构确能作到敏捷。
控制原则
咱们生活在一个复杂的世界,每个业务领域也都是如此复杂。当构建一个软件的架构时,真的很容易从一开始就把事情复杂化了,进而让后续开发更容易出错。如下两条原则是作决策时事实上的标准:
保持简单,愚笨(KISS,Keep It Simple, Stupid)
你不须要它(YAGNI,You Aren’t Gonna Need It)
若是在那一刻咱们真的须要一个具体的功能和作成决策,这两条原则试图让咱们对此作慎重的思考。若是咱们把作决策推迟到一个更晚的时段,就能保持架构的简单,并所以在一个更长的时间里方便管理。软件架构变得复杂的一个一般作法是引入抽象——可能变成一个新的花式层,以一种格式复制数据,而后转换为另外一种格式,或者为了让代码具有可测试性,可能建立出许许多多的类、接口、工厂等等。
不过,在运用这两条原则时还要提防一处陷阱,咱们倾向于把全部事情都延缓处理直到最后一刻。到那个时候,可能已经变得太难实施所需的变动了。为了避开陷阱,咱们的任务可贵多,由于
咱们不该在最后一刻作出决策,而应在最有责任这么作的时刻作出决策。
当我准备作出架构上的决策决定时,若是作这个决定的肯定性很高,我一般的作法是先作一些不那么花时间的小的准备。我也会去咨询个人同事,咱们一块儿讨论问题。
真实世界之痛
我曾经作过一个轮渡票务在线销售的项目。这是一个复杂的系统,它须要和4个其它第三方系统进行通信。一开始咱们的首要关注点是基于用户story完成功能实现。尽管咱们知道咱们须要一个更复杂巧妙的缓存机制,但那时还没必要要——咱们得先完成当前的用户story,因而咱们选择了延缓处理。而后到后面,因为与其它第三方系统的大量通信,系统变慢了。咱们别无选择,只能中止用户story开发,一门心思扑在缓存机制上——但这时事情已经很差办了。
如何组织文档
瀑布式方法要求编写大量的文档,由于须要用文档来在不一样的阶段(以及每一个阶段的参与者)之间进行信息传递。编写文档的过程不只耗时间,并且因为文档存在对功能的不当描述,还常常形成误解。更进一步,难以保持文档的及时更新,由于开发倾向于快速推动,不少时候不会再理会文档了。正如咱们使用敏捷来迭代地编写代码,一样能够如此处理文档。咱们开始只描述系统的重要方面,而后在须要时持续地加入更多新的信息。
哪些内容应写入文档
切勿对同一个东西以不一样的方式作屡次的文档化处理。举个例子,有工具能帮助你从代码中生成图表——和建立独立的图表相比,这样作方便不少,图表很容易过期的。除此以外,假如你为了描述系统的某一方面而建立了可视化工件,就不必再使用文字(除非你想要增长一些不能用视觉方式表达的细节)建立一大堆文本文档去描述同一件事情。这里有一点很重要,你和你的团队应对使用的绘图符号有一致的理解。
怎样文档化可能会想到使用UML来对软件架构进行文档化。UML是标准语言,每一个人都能理解,大学里也教,所以UML必定是团结起组织内每一个人的不二选择。个人经验却显示,实践中不多有人使用UML。缘由之一多是UML提供的描述系统的方法很是多,能够从不一样的视角进行描述,因此不常用UML的人会感到挫败。
在敏捷业界,没有特定的工具用来文档化软件架构。可使用涂写白板、便利贴、文本文档、wiki等等(见图5)。实践中,只使用2到3种不一样的格式会比较稳妥些,要否则信息可能会变得难以存储和检索。好比说,在白板上涂写一阵后,你可能须要对其进行拍照,这样就保存下来了图表的电子版本。若是后面你要再次编辑,这时你得选择究竟是直接数字编辑照片,仍是从新在白板上画一遍而后再照一张相。
我用图表工具来生成系统构件的简图。一般用Microsoft Visio或draw.io(已集成在Google Drive中),不过还有大量的其它工具可选,在线和离线的都有。若是开会时在白板上作了绘制,我会在会议结束后用图表工具重画一遍如出一辙的图,以保持我画的东西的格式统一,彼此不存在大的差别。若是我须要对图表添加额外的注解,我通常会另行建立文本文档。
总结
软件架构定义了将来系统的骨架。它不仅是由线点组成的图画,而是一系列管理支配着系统开发的完整决策,包括代码自己。应细致地考虑每个作出的决策与决定,它们都是一种权衡折衷。敏捷理念要求对变化持开放心态,甚至是来自项目晚期的变化,和传统的瀑布式模型不一样,瀑布式模型但愿需求比较稳定。不过,系统骨架的变动每每并不容易实施,甚至可能把你拉回到开发阶段。所以,不要等到最后一刻才作出该作的决策决定,这点很重要,而应该在最有责任这么多的时候作出决定,为此甚至能够不惜冒点小风险,实现某些在那个时间点不作要求的东西。再者,敏捷软件架构要求综合全面地看待宏图愿景和“如今”,构建出一个每一个人都能在上面添砖加瓦的可持续的平台。