前篇简要讲述了软件领域修炼各阶段的特点及目标,适用于个人发展的阶段性规划。本篇将概要讲述软件领域修炼的方法论即软件架构设计的思想及其适用性,适用于每一阶段。
回顾
软件架构是指有关软件整体结构与组件的抽象描述,用于指导大型软件系统各个方面的设计。软件架构分析与设计的相关概念早在19世纪60年代就已经出现,伴随着信息技术的发展而不断发展。
软件架构设计是一个复杂的过程,一般来说需要针对目标战略进行业务分析,根据业务战略形成解决方案,明确方案中信息化部分的功能设计,针对系统功能给出系统架构,然后确定系统架构的技术体系。
前篇我们提到软件领域修炼的四个阶段,即:驾驭代码,驾驭模块,驾驭框架和驾驭体系。这既代表了软件人员修炼提升的不同阶段,也代表了系统的各个层面。而软件架构设计模式和思想则蕴含在每一个层面的每一个细小决策中。
要理解架构设计必须先学会架构分析,就如同要掌握组装必须先学会拆解。
面向数据流的分析
撇弃冗长晦涩的理论和术语,面向数据流的分析可以简单概括为一种自外到内,自顶向下,逐层分解数据的输入/输出的结构化分析方法。
任何一个系统的软件架构设计实现都可以分解为数据在不同层面不同维度的IO及这些IO之间的流转策略。这里有三个重点:1)不同层面不同维度;2)数据在IO两端的存在和变换;3)数据在多个IO之间的流转策略。
不同层面及维度
从交互维度来看,一个Button按钮,一个输入框或者一个链接都代表着一种数据的输入和输出。
从空间维度来说,数据可以在进程内,跨进程,跨节点间流转。如果再加上时间维度,则变成了并行和并发处理。
从粒度层面来说,一个方法就是一个典型的IO,方法的参数为数据输入,方法的返回结果为数据输出;同样的,一个接口是定义了一组方法的IO,一个模块是定义了一组接口的IO,一个系统则是定义了一组系统外部和内部的模块IO。
从服务维度来说,方法声明了内部操作的交互契约,接口声明了模块间交互的行为契约,服务则声明了系统间的业务契约。而数据在IO两端的存在形式即为契约的表象定义。
数据在IO两端的变换
数据在IO两端的变换意味着数据的存在形式产生了变化。这种变化要么是系统的最终需求形式,要么是为了达到最终目标所生成的中间形式。适当的引入中间数据存在形式可以让系统在特定层面解耦,能够增加系统的易用性,可扩展性,可维护性和可复用性。
如一个具有1000行代码的方法,程序员很难阅读,理解,扩展和维护,更不要说复用;如果拆解为5个200行代码的方法,相对就比较容易阅读,理解,扩展和维护,甚至复用;当然,过多的拆分,如变为10个方法,可能就会增加复杂性,维护也会变得困难。
到了模块层面,数据在一个模块的两端同样存在不同的形式,此时,数据的存在形式相比于方法层面,其具有更多的上下文元信息(Metadata),如消息信封,POJO,HTTP 文等,便于数据在不同的IO之间流转时进行处理决策。
到了更高的层面,数据在IO两端可能存在更多的业务规则定义。
在IO内部,GoF总结了很多常见的软件设计问题的解决方案。
数据在多个IO之间的流转策略
数据在两个或多个IO之间的流转,同样有着各种不同的设计决策。这些决策可能是为了性能,可能是为了满足业务需求,也可能是为了加强系统的可扩展性和可用性等等,不同的决策决定了系统的不同特点。
比如方法层面,可以通过多线程考虑并行和并发处理来增强性能,可以通过事务确保处理的原子性和可靠性。在模块层面,可以考虑队列或缓存,确保系统的可用性;可以考虑多进程提升系统的处理性能。在系统层面可以考虑集群增强系统的并发处理能力,可以考虑缓存,队列和持久存储来提升性能和可靠性等诸多决策。
数据流转也可以看做是数据从一个IO(或多个IO)到下一个IO(或多个IO)的过程。这里有多种设计决策,如消息交换模式MEP(In-Only,Robust In-Only,In-Out,In-Optional-Out,Out-Only,Robust Out-Only,Out-In,Out-Optional-In),?MQ模式(Request-reply,Publish-subscribe,Push-pull,Exclusive pair)和企业应用集成模式EIP(管道,过滤器,路由,变换和端点等等)。
针对数据的分布式流转,则需要考虑诸如:异步,非阻塞和单向,均质、单向和均匀传递,并发、连续和分布式等特征及设计决策。
综上所述,面向数据流的架构分析本质上是驾驭在系统不同层面的数据变换及其流转。在实际分析场景中,首先要弄清楚系统能够处理什么样的数据也就是输入,以及系统能够输出什么数据。然后沿着数据的流转,确定数据的中间存在形式,理解整体层面的环节划分和数据流转变换的过程。然后再对数据降维(拆解),重复之前的步骤进行下一层的分析,直至分析完成。
理解了面向数据流的架构分析,对于面向数据流的架构设计问题就演变成为如何驾驭在系统不同层面的数据变换及其流转,也就是如何在系统不同层面为数据变换及流转选择合适的设计方案的决策过程。
软件架构设计思想的适应性
随着信息技术的不断发展,很多解决软件架构设计的具体技术已经过时或者消亡,但是,软件架构设计的模式、思想是不会过时的。即便技术或需求场景发生变化,这些架构设计的模式和思想或许不再适用于当前的主流场景,但是如果换一些层面,维度或者领域,它很可能又会发挥其巨大的价值。下面来看一些实例。
方法
以数据在IO两端的变换为例,前面提到了数据在方法,接口,模块和系统不同IO层面的变换。在面向对象编程中,方法层面的数据变换看似简单,是系统开发的基础操作,但是,站在数据映射的角度,通过map,flatMap和reduce等抽象定义的数据在方法层面的映射变换成为函数式编程的基石。再进一步,通过提升数据的规模,对大规模数据执行map和reduce的操作,这种架构设计思想就成为Hadoop大数据分析的核心。
以上可以看出,很多软件设计思想应用到不同层面,不同维度都会有一定的适应性,甚至带来新的突破。
模块
十多年前,笔者设计了这样一个基于JAVA的企业应用集成产品:将两个应用之间的集成需求,抽象分解成为一组任务,每个任务包含源连接器,目标连接器和若干中间的处理管道。任务中数据的流转处理即所需的组件及顺序通过XML进行定义。
如上图所示,这个产品的设计现在看来相当简单,但值得重新提及的是,该产品在设计上已经开始涉及流式处理和组件编排的相关概念,而在当时的技术发展阶段,所有的设计思考都是局限在单一JVM内部的。
目光回转到现在,分布式环境已经成为服务器端架构设计的基本前提。如果将之前产品中的设计思想摆脱单JVM的限制,应用在分布式环境中,我们可以很容易想到一个非常流行的大数据流式处理框架Apache Storm。
同样,组件编排的思想也值得一提,如果将组件编排切换到服务的维度就是面向服务的编排;如果将组件提升到容器层面,则是当前最为流行的容器编排:Kubernetes和Mesos。
这也进一步证明了软件架构设计思想是不会随着技术的发展和时间的推移而消亡的。
服务
此处服务的概念相比于接口是指更高层面的契约,其最终目的是在一个更高的层面对交互(两个IO之间的数据流转)进行标准化。SOA是一种开始,微服务是进一步优化和探索,要达到目标,还有很长的路要走。有关SOA与微服务的比较,可以参考Mark Richards写的《Microservices vs. Service-Oriented Architecture》一书。
微服务是当前非常流行的一种架构设计。刚刚接触微服务架构的技术人员很多是从当前流行的Spring Boot/Cloud开始了解微服务的概念,如果不去探究微服务背后的模式和设计思想,很多人往往会将微服务与Spring Boot/Cloud的开发模式对等起来,错误地认为微服务就是Spring Boot/Cloud。
前面提到Apache Storm是一个大数据流式处理框架,这里提出一个问题供读者思考,Apache Storm中的拓扑是否可以看作是一种微服务设计?
总结
作为一名架构师或正在迈向架构师之路的程序员,在熟练运用一些具体的应用技术对系统进行架构设计的同时,还要善于探究这些技术背后的设计模式,思想及其场景适用性。一个优秀的软件架构师,要有全局思维,战略思维,前瞻性思维,抽象思维和逆向思维。
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!