“一个软件架构是一个软件系统在其操作的某个阶段的运行时(run-time) 元素的抽象。一个系统可能由很多层抽象和很多个操作阶段组成,每个抽象和操作阶段都有自己的软件架构。”
根据Fielding博士的解释,软件架构可以从纵向和横向两方面来划分。架构的核心是抽象原则,即通过封装来隐藏系统运行时表现功能的具体实现细节或不同模块间组合与协调的细节。从横向上来看,整个系统可以根据其职责被划分为各个不同的层次,如数据访问层和业务逻辑层等,这里对于每一层的架构可以被描述为提供给同层的其他元素的抽象接口,以及对上层架构的具体化描述,而不是另一个独立的架构层次。比如数据访问层的Add接口应该被理解为进一步解释业务逻辑层Add接口在系统运行时表现的行为,而不是被看成一个独立的数据库添加操作。另一方面,从纵向上来看,系统架构可以根据整个系统的运作阶段切片,也就是说位于不同层次的接口集合可以被用来描述系统运行时某一个特定阶段的行为。不管从横向还是纵向划分,架构都体现为一种对系统运行时功能的精确表述,向下(实现该架构的开发人员)它是一份技术上的规范文档,向上(客户)它可以是一种有点商务味道的契约与准则。
尽管以前自己理解在表述方式上和Fielding博士的论述大体一致,但观念上似乎有着不小的差距。软件架构所做的应该仅仅是对于系统功能的描述,它与具体的代码设计,即软件结构,应当被区别对待。后者作为设计时(design-time)的代码设计,为实现运行时的功能描述服务,所以从这个角度来看开始编码以后的设计已经成为一种实现,而不是从一个宏观的角度去看整个系统。过去我所做的设计似乎都有这样的问题,忽略了真正的软件架构,而直接开始了对软件结构的设计和组织。对于软件需要体现的功能,我们放给了需求人员去思考,而这部分内容恰恰是软件架构的核心。对于软件结构设计的目的在于通过组织代码来实现系统的模块化,以及各个功能组件的可复用性与灵活性,所以一旦开始关注这部分内容,代码的组织就会变成设计阶段的主导,而系统的运行时特性便沦为调试阶段作为正确结果与之进行比对的一份参照。虽然将静态源代码结构的设计作为主导会产生出可复用的功能组件,但是该组件很可能过多的考虑了某些当前系统并不需要的行为。比如说客户需要设计一个分布式留言板,让公司内部的员工可以像贴便条一样分享自己的经验。如果直接对软件结构设计我们很可能会构建一个具有Add, Edit, Remove, GetById, GetBySubject, GetByEmployee等方法的MessageBoard实体,但是其中的Remove和GetById操作真的会被作为系统功能展现给用户吗?是的,他们肯定是有价值的,但其价值登场的时间是在具体的模块开发过程中而不是在软件架构的过程中。一开始便考虑此类接口有两个缺点,其一是设计人员可能花费更多的时间去思考一些最终用户并不关心的功能;二是这些过多的考虑很可能让开发人员在潜意识里降低用户实际需求的优先级,而醉心于编码之中。归根到底,技术服务的是需求,所以需求设计和架构设计应该同时提出,而不是一个先需求后架构的流程,这样才能让后面的代码结构设计有的放矢,不做多余的工作,加速项目迭代周期。