设计恰如其分的架构

远在2009年,Martin Fowler与Rebecca Parsons在QCon SF作了一次题为Agilists and Architects: Allies not Adversaries Presentation的演讲。演讲主要讨论了在敏捷方法中的架构活动。类似的话题,Neal Ford则提出了紧急设计的概念,并发表了名为Evelutionary Architecture and Emergent Design(演进架构与紧急设计)的系列文章。这是很棒的一个讲解演进架构的系列文章,谈到了TDD、代码复用、连贯接口、DSL、重构、惯用法模式、指标等与演进架构和紧急设计有关的内容。安全

Neal Ford对软件架构的主要观点基于以下事实:架构

将来是不可预测的;
软件设计的最终目标是得到完整的源代码;
系统的复杂度分为偶发复杂度(accidental complexity)与本质复杂度(essential complexity);并发

因而,咱们应该选择在最后责任时刻(Last Responsible Moment)去应对系统的复杂度。所谓“最后责任时刻”,即咱们若是未及时采起措施,可能致使复杂度线性增长的时刻,以下图所示:分布式

Image Title

Ford提出的方法就是在开发中善于发现抽象与模式,并借助测试驱动开发,利用重构去导向设计。同时,咱们还能够尝试使用一些考量代码质量的工具,得到质量指标,经过这些指标去发现问题(这些问题其实就是技术债),而后去及时解决问题。针对较难作出的架构决策,则能够利用Spike方式快速得出结论,甚至是原型方案。ide

事实上,演进式架构这个话题已是老调重弹。让咱们再回到2004年,Martin Fowler固然发表了文章Is Design Dead。文中谈到了计划式设计与演进式设计之间的区别。这篇文章算得上是溯本清源。在2007年我本身的书《软件设计精要与模式》中,也简单阐述了我对两者的理解。我给出了一个建筑学的隐喻:拙政园与周庄。拙政园是计划式设计的典范,没有详尽的计划,也许就不会有疏朗典雅的拙政园。周庄却并不是某人在某一时刻灵感捕捉后的设计成果,而是经历了数百年的历史沧桑,渐进地增添与更替各类建筑,最后造成如今这般灵秀的水乡风貌。我在书中写道:工具

演进的设计,一样须要遵循架构设计的基本准则,它与计划的设计惟一的区别是设计的目标。演进的设计提倡知足客户现有的需求;而计划的设计则须要考虑将来的功能扩展。演进的设计推崇尽快地实现,追求快速肯定解决方案,快速编码以及快速实现;而计划的设计则须要考虑计划的周密性,架构的完整性并保证开发过程的有条不紊。测试

2010年,我翻译了George Fairbanks的著做Just Enough Software Architecture。大数据

Image Title

书中除了计划式设计和演进式设计以外,还提到了第三种设计:Minimal planned design(最小计划设计),这算是一种中庸之道的选择。书中认为,演进式设计须要与一些敏捷实践配合,包括重构、测试驱动设计与持续集成。George认为计划式设计背后隐藏的思想是在构造开始以前,制订的计划能够设计出很好的细节。他还提到:编码

当架构为并行的多个团队所共享时,计划式架构设计就具备实践意义,在子团队开始工做以前,这种计划式设计颇为有效。架构设计

书中还写道:(对于多团队开发而言)计划式架构定义了高层的组件与链接器,并与局部的设计相匹配,而子团队则设计这些组件与链接器的内部模型。架构经常会保证总体的不变量与设计决策,例如创建并发策略、链接器的标准集、分配高层职责或定义某些局部的质量属性场景。

最小计划设计,则介乎于演进式设计与计划式设计之间。支持这种设计的人认为:若是彻底采起演进式设计,可能会使得设计走向死胡同;而计划式设计又很是难,由于事先对系统并无全面的了解,可能致使设计错误。在2002年Bill Venners对Martin Fowler的采访中,Martin Fowler认为,最合理的分配是20%的计划式设计,80%的演进式设计。在George的书中,做者认为须要权衡计划式与演进式设计。一种作法是在项目初期进行计划式设计,确保架构可以处理最大的风险。以后,就能够经过局部的设计来应对需求的变化,或者采用演进式设计,经过推行重构、测试驱动设计与持续集成对架构进行演化。

博客coding the architecture上的一篇文章Just enough architecture,从方法学的角度分析如何得到恰如其分的架构。

Image Title

文章以及上图所表达出来的含义是:传统的瀑布式采起事先设计的作法,能够认为是计划式设计;敏捷方法学倾向于演进式设计;处于其中的RUP则更像是前面提到的最小计划设计。文中主要仍是关注咱们在架构过程当中如何作到架构的“just enough”。事实上,这一观点在George Fairbanks的著做Just enough software architecture中被反复提到,要作到这一点,就须要采用风险驱动模型(Risk-Driven Model)。RDM的架构步骤分为三步:

  • 识别风险并进行优先级排列
  • 选择并应用相关技术
  • 评估风险是否下降

其实风险驱动模型的三个步骤很容易理解,关键是咱们应该如何识别风险,如何排列优先级,又该如何肯定解决或控制风险的技术,并进行合理地评估,这是风险驱动模型的难点。我认为RDM带来的益处在于它给出了一个很是具备实践意义的驱动原则与方法,它告诉架构师,当咱们在对系统进行架构时,须要从一开始就要重视风险,例如系统的安全性、可伸缩性、安全等诸多与质量属性有关的技术风险。

总体而言,这三种方式的设计各有优劣,咱们应根据具体的场景,具体的项目,具体的团队进行针对性地分析。应该把握“因地制宜”的原则,认识到不一样的项目须要不一样的设计方式。对于不一样的开发团队,作出的选择也会不一样。例如,若是开发团队精于重构、测试驱动设计,并能很好地实施持续集成,就能够考虑采用演进式设计或最小计划设计。

我我的较倾向于Minimal planned design,至于它在演进式设计与计划式设计以前的权衡,没必要彻底照搬Martin Fowler给出的比例。参考DDD的分类,我将计划式设计的部分规划到战略式设计中,此时,我能够从用例出发,引入Bounded Context来寻找系统的核心领域与子领域。

经过Context Map并结合六边形架构,能够帮助咱们识别Context或者说领域之间的通讯方式与集成方式,从而得到整个系统的分布式架构模型。运用分层架构以及六边形架构驱动得出的Port与Adapter,能够帮助咱们得到整个系统的应用逻辑架构。而Context自身,则能够做为业务逻辑架构的基础。

软件系统的质量属性算是特殊的一部分,能够借鉴质量驱动设计或风险驱动设计,来肯定知足质量属性的架构方案。在这个过程当中,咱们能够参考经常使用的架构风格与架构模式。例如针对大数据处理、并发处理、资源管理、分布式架构,都有许多相应的模式与风格可供咱们选择。架构风格与架构模式的选择,会直接影响到咱们的系统架构。

当咱们分别有了物理架构、应用逻辑架构与业务逻辑架构以后,计划式设计的过程就能够画一个句号了。因为咱们有了Context做为领域边界,使得咱们可以更好地划分特性团队。如DDD所述,团队之间的关系能够参考Context Map,例如Partnership、Consumer-Provider等。以后的过程就进入了DDD的战术设计层面。在这个层次,咱们能够结合团队成员的能力来选择不一样的设计方法。例如,能够选择DDD方法继续对子领域进行领域建模;也能够从Application层面,经过用例驱动设计,结合CRC卡和时序图进一步细化;固然,也能够经过ATDD与TDD进行测试驱动。

不管选择何种方式,咱们的设计都应该把握“恰如其分”这个原则,不作没必要要的“过分工程”。这或者能够看作敏捷架构的中心原则。

相关文章
相关标签/搜索