设计良好的架构必须支持以下4
点
可以看到,正常运行,只是其中的一项。
用例也叫使用案例。它描述系统如何响应外界请求,每个用例会提供一个或多个场景,告知用户如何使用交互。编写用例时,应当避免技术用语,要让用户都能看懂的语言。
一个系统,应当不需要查看源码,仅查看用例,就能完整的覆盖该系统的所有功能。即用例要完整,要全。
架构在支持系统运行方面,扮演着更实际的角色。架构必须能够支持,各种场景的运行,比如大数据量的访问,快速的查询等。
这意味着它的架构应该支持将其计算部分,拆分成一系列小型服务。单体模式编写的系统,之后想改架构比较难。微服务可以有更多的组合和空间。
需要恰当的将系统切分为一系列的隔离良好,可独立开发的组件,才能将组件分配给不同的团队进行独立开发。
一个设计良好的架构通常不会依赖成堆的脚本和配置文件,也不需要用户手动创建一堆有严格要求的目录与文件。好的架构可以让系统在构建完成之后立刻就能部署。
要做到这些也需要通过正确的划分隔离系统组件,才能实现。其中包括了主组件,它的作用是将整个系统黏合在一起,启动,连接并监控每个组件。
通过之前学习的一些架构原则,可以帮助我们将系统划分为一系列隔离良好的组件,这样可以长时间的为未来保留尽可能多的可选项。良好的架构设计,让系统可以在任何情况下都能做出必要的变更。
架构师的目的,是让系统支持其所需要的所有用例。但难点在于我们无法预知所有的用例。好在架构师知道我们要做的是一个什么样的系统。所以可以通过采用单一职责原则(SRP)
和共同闭包原则(CCP)
,隔离那些变更原因不同的部分,集成变更原因相同的部分。
比如,用户的界面变更,肯定是和业务无关的。即UI
要和业务逻辑
部分隔离。
比如,字段的校验逻辑
,和计算用户利息的业务逻辑
,也应当隔离。因为它们的变更逻辑不一样。
比如,数据库,和编程语言无关,属于技术细节。和上述的业务逻辑都无关。
这样一来,我们可以发现,一个系统,可以被分为若干个水平分层。
UI
界面,代码的业务逻辑,领域普适的业务逻辑,数据库,等。
对用例也需要进行细分划分,颗粒度要细。
解耦对架构设计的第二个目标系统运行,有什么意义?如果用例得到了良好的隔离,那么需要高吞吐量的用例和低吞吐量的用例也就互相自然分开了。如果水平分层了,那么比如UI
和数据库,就能单独部署在其他服务器上。而需要较大宽带的应用就能运行在多个实例上。比如微服务。这里不是鼓吹SOA
是一种最佳的软件架构,只是有时候我们必须要把组件切割到服务这个应用层次。
进行架构设计的第三个目标就是支持系统的开发。组件被高度解耦后,开发团队之间的干扰就大大减少了,能支持多团队开发,不管组织是分功能进行开发,分组件开发,分层开发,还是按照别的什么方式开发。
按水平分层的解耦,还能带来部署的灵活性。比如在系统的运行中,可以热切换分层的实现和具体用例,而不会影响其他的组件。
架构师经常会钻牛角尖——害怕重复。
当然,重复在这个行业一般来说都是坏事。我们有责任减少这种重复。但有些是真的重复,有些是假的重复。例如两段代码一样,但是他们走的是不同的演进路线,有着不同的变更原因和变更速率,它们就不是真正的重复。
之所以讨论重复的问题,是因为我们在垂直切分系统时,这样的困惑经常出现。例如两个不同的系统,需要展示的数据大部分相同,少部分不同,这两个系统交由不同的用户使用,那么就应当分开,因为很有可能他们的变更原因和变更速率不同。
回到解耦模式上面来,按水平和用例解耦一个系统,可以有很多方式。例如,源码层次上解耦,二进制层次上解耦(部署),也可以在执行单元层次上解耦(服务)。
控制源码模块之间的依赖,以此达到模块的变更不会导致其他模块也需要变更和重新编译。这种解耦模式通常系统是单体结构。组件之间的通信是调用内部函数。
我们可以控制部署单元
之间的依赖关系
,以此实现一个模块的变更,不会导致其他模块的重新构建
和部署
。这种模式一般会在同一个进程中运行,但也有的会进行跨进程通讯。重要的是这种模式会解耦出很多可独立部署的单元。组件之间的通信大多还是同一进程内调用函数。
将组件之间的依赖关系,降低到了数据结构层次,组件之间仅通过网络数据包通信。它们在源码和二进制层次上都是独立的个体。它们的变更不会影响到其他组件。比如微服务。
现在我们要问,哪个最好呢?答案是在项目早期,很难知道哪种最好,随着项目的逐渐成熟,最好的模式可能会发生变化。
服务层次解耦,一般都用微服务,但是成本太高,不仅系统资源成本高,人力成本也高。所以应当要将系统在最开始时,将解耦推进到一旦有需要,就可以随时转变为服务的程度即可。让整个程序尽量长时间保持为单体结构,以便给未来留下可选项。
上述三个层次,应当按照项目成熟度来实时推进。
一个良好的架构,应该允许一个系统从单体开始,以单一文件或项目进行部署,然后逐渐成长为互相单独部署,甚至是独立的服务或者微服务。最后还能随着情况的变化,允许系统逐渐退回到单体。
并且在上述过程中,还能保持大部分源码不受变更影响。解耦是一个可选项,大型项目部署可以采用一种模式,而在小项目中则可以采取另一种模式。
要达到上述要求难度不小。一个系统所适用的解耦模式,可能会随着时间变化,优秀的架构师,应该能预见这一点,并且做出相应的对策。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。