【IT168 技术文章】
如何更好地进行软件架构设计,这是软件工程领域中一个永恒的重点话题。过去几十年来,国际软件工程界在软件架构设计方面已经获得了长足发展,大量图书、文章和文献记载了这方面的成熟经验与成果。软件架构设计往往是一件非常复杂的工作,涉及到很多细节和方方面面,可探讨的话题也非常之多。囿于篇幅限制,以下只能根据笔者个人理解,遴选出软件架构设计的个别要点,结合当前流行的敏捷软件工程思想,与大家分享一下自己在软件架构设计方面的心得和体会。
架构决定成败
软件架构是软件产品、软件系统设计当中的主体结构和主要矛盾。任何软件都有架构,哪怕一段短小的HelloWorld程序。软件架构设计的成败决定了软件产品和系统研发的成败。软件架构自身所具有的属性和特点,决定了软件架构设计的复杂性和难度。
这几年流行一个说法(管理谚语):“细节决定成败”,这句话其实只说对了一半。细节确实很重要,很多项目、产品就输在细节的执行上。一方面,战术细节固然很重要,但另一方面,战略全局也同样重要,对应的我们可以说:“战略决定成败”。战略性失败,就好比下一盘围棋,局部下得再漂亮、再凌厉,如果罔顾大盘,己方连空都不够了,还有官子(细节)获胜的机会吗?必然是中盘告负。
类似地,正确的软件架构设计,应该既包括战略全局上的设计,也包括战术细节(关键路径)上的设计。有一种错误的观点认为,软件架构设计只要分分层和包,画一个大体的轮廓草图,就完事了。这种“纸上谈兵”型的架构师行为是非常有害的。事实上,既然软件架构是软件建筑的主体结构、隐蔽工程、承重墙和要害部位,那么软件架构也必然要落实到实际的算法和代码,不但要有实现代码,还要包括对这部分架构进行测试的代码,以保证获得高质量的、满足各种功能和非功能质量属性要求的架构。除了完成概念、模型设计外,软件架构师一定要参与实际的编码、测试和调试,做一位真正的hands-on practitioner,这已经成为了敏捷软件工程所倡导的主流文化。
两个架构
我们在日常的软件产品和系统开发中,实际上会遇到两种、两个部分的软件架构,即待开发的应用部分的软件架构(简称“应用架构”),以及既有的基础平台部分的软件架构(简称“基础架构”)。这两部分架构之间是互为依赖、相辅相成的关系,它们共同组成了整个软件产品和系统的架构。
基础架构的例子包括:.NET和J2EE等主流的基础平台和各种公共应用框架,由基础库API、对象模型、事件模型、各种开发和应用的扩展规则等内容组成。我们只有熟悉基础架构的构造细节、应用机理,才能有效地开发出高质量、高性能的上层应用。然而,开发一个面向最终用户的软件应用系统和产品,仅仅掌握一般的计算机高级编程语言知识和基础平台架构、API的使用知识显然是不够的,我们还需要根据客户应用的类型和特点,在基础架构之上,设计出符合用户要求的高质量应用软件。
熟悉OOA、OOD抽象建模技术、设计原则以及架构模式和设计模式等等方法技术,不但有助于我们更好地理解和利用基础平台架构,也有助于我们设计开发出更高质量的应用软件架构。
风险驱动、敏捷迭代的架构设计与开发
软件架构将随着软件产品和系统的生命周期而演化,其生命期往往超过了一个项目、一次发布,甚至有可能长达数年之久,因而软件架构无论对于客户还是开发商来说都是一项极其重要的资产。
软件架构的设计应该遵循什么样的开发过程?或者说,有没有更好的、成熟的软件架构设计和开发过程?回答是,21世纪的软件架构设计应该优先采用敏捷迭代的开发方式和方法。与传统做法不同,敏捷迭代开发主张软件架构采用演进式设计(evolutionary design),一个软件产品或系统的架构是通过多次迭代,乃至多次发布,在开发生命周期中逐步建立和完善起来的。
好的软件架构不是一蹴而就的。在架构设计开发过程中,我们应该尽量避免瀑布式思维,通过一个“架构设计阶段”来完成系统的架构设计乃至详细设计,然后再根据架构图纸和模型,在“编码实现阶段”按图索骥进行架构的编码与实现。这种传统做法的错误在于认为软件架构就是图纸上的模型,而不是真正可以高质量执行的源代码。几十年的软件工程实践表明,没有经过代码实现、测试、用户确认过的架构设计,往往会存在着不可靠的臆想、猜测和过度设计、过度工程,极易造成浪费和返工,导致较高的失败率。
风险是任何可能阻碍和导致软件产品/系统研发失败的潜在因素和问题。软件架构是软件产品和系统研发的主要矛盾和主要技术风险,软件架构的质量决定了整个软件系统和产品的质量。不确定性往往是软件架构设计当中一种最大的潜在风险。因此,软件架构的设计与开发应该遵循风险驱动的原则,在整个开发生命周期内至始至终维护一张风险问题清单,随着迭代的前进,根据风险的实时动态变化,首先化解和处理最主要的架构风险,再依次化解和处理次要的架构风险。