软件架构实际上包括了:代码架构,以及承载代码运行的硬件部署架构。实际上,硬件部署架构最终还是由代码的架构来决定。因为代码架构不合理,是无法把一个运行单元分拆出多个来的,那么硬件架构能分拆的就非常的有限,整个系统最终很难长的更大。
重写代码,推翻原有架构,重新设计等等说法,来说明架构的进化。这实际上就是当初为了完成任务,没有充分思考所带来的后果。软件实际上是对现实生活的模拟,虚拟化。这是一个非常重要的前提,直接决定了我们的代码应该分为几部分。结合每个部署单元所承担的责任,可以明确的拆分为两个不同的责任: 1. 表达业务逻辑的代码。很多人把这部分叫做 Domain Logic,或者叫 Domain Model。这部分实际是来源于生活的,必须保持和现实生活中的切分一致,并非人为的抽象而成。
2. 对用户提供访问并保存业务逻辑运行结果的代码。计算机的状态保存有一个缺陷,本机保留业务运行结果有很大的问题,一般都在外存储设备上保存,也便于扩展。
所以单个部署单元的代码可以分为两个部分,如下图所示:
从这个图中可以看出,软件代码的相关利益人为运行时的访问人员和存储设备。而 service 的代码是最复杂的,需要服务于三方,代码人员的负担是最重的。为了把这三方的变化对 service 的影响降到最低,对于 service 还必须进一步的分拆为三个部分,让每一个部分都能够独立的变化,这样这三方的变化就不会产生连锁响应,降低成本。
架构拆分可以用来节省人们执行事务生命周期活动所需的时间,这就是传说中购买“寸光阴”的方式,也是传说中的“银弹”。不过要获得这个“银弹”,也不是没有代价的。但既然节省的是时间,而时间又是无价的,因此人们也愿意采用架构拆分,哪怕要因此而付出巨大的代价。因为相比“无价”而言,“巨大的代价”也是可以接受的。
可是架构也不是万能的。那么在采用架构拆分之前,了解这些“巨大的代价” 是非常有必要的,可以帮助我们认清架构的局限,厘清对作架构拆分的人的要求。因为不合理的架构拆分,反而会浪费更多的时间;哪怕是合理的架构拆分, 但是如果不能够重新组装回原有生命周期的话,也无法达到节省时间的目的, 最终也会导致浪费时间。
拆分时就要想好怎么把拆分出来的软件组合成原有的系统。这些软件在拆分前处在同一个应用的时候,它们共享计算机的内存、 CPU、网络、磁盘等硬件,操作系统等软件。一旦分离开来,每个应用就有了自己的计算机资源,有了自己的对外访问,有了自己的利益,有了自己的计算机硬件和软件的边界。虽然这些刚分离出来的软件暂时仅仅服务于原来的业务, 但是随着时间的变化,这些软件一定会有自己独立的业务出现,这些软件的拥 有者一定会有自己的诉求。因为一个事物只要出生,它必然要长大,这是不可避免的。在组合这些软件时要明白,这是针对不同个体的访问,需要考虑跨越网络,需要考虑这些个体自身利益,比如它们的流量分配、访问边界、安全与隔离等等。如果仅仅是简单粗暴的组合,忽视不同应用各自的利益,一定会带来极大的沟通成本,甚至会导致组合的失败。