看一下大佬是怎么说的:
计算机系统的软件架构是构建这个系统所需要的一组结构,包括软件元素、它们之间的关系以及两者的属性。
--Bass等著《Documenting Software Architectures:Views and Beyond》
这个定义将软件分解为元素和元素之间的关系两个部分,就像一辆汽车可以分为发动机、底盘、轮胎等元素,同时各个元素之间还存在关系,他们需要互相交互,汽车才能正常使用。这样分解有以下两个原因:
从4个不同的视角来看一个软件的价架构:
除了这四个视图以外,4+1中的+1是指场景,它负责把视图串联在一起。每个场景负责描述在一个视图中的多个架构元素如何协作,以完成一个请求。例如,在逻辑视图中的场景,展现了类是如何协作的。同样,在进程视图中的场景,展现了进程是如何协作的。4+1视图是描述应用程序的绝佳方式。每一个视图都描述了架构的一个重要侧面,场景把视图中的元素和协作串联在一起。
应用程序有两个层面的需求:
个人理解这段说的就是我们在完成老板或者产品给的一个需求的时候,除了实现功能以外,还要自己考虑实现的方式是不是能可扩展,高可用等等。实现架构如果不合适,项目随时间会变得复杂,不易维护和扩展,这时候还得需要治理。
像不同时代不同国家的建筑有着不同的建筑风格一样,软件架构也有几种不同的风格。什么是架构风格?David Garlan 和 Mary Shaw (An Introduction to Software Architecture,January 1994)这两位软件架构学科的先驱是这样定义的:
因此,架构风格根据结构组织模式定义了一系列此类系统。更具体地说,架构风格确定可以在该风格的实例中使用的组件和连接器的词汇表,以及关于如何组合它们的一组约束。详情链接:https://wwwcs.cmu.edu/afs/cs/project/able/ftp/intro softarch/intro softarch.pdf
太抽象了。不深究,先来看看具体的几种架构风格:
弊端:
个人感觉说的是没错,但这几个弊端貌似都影响不大呢?工作中也是分层架构也是一种很常用的架构
https://alistair.cockburn.us/hexagonal-architecture/
微服务架构也是一种架构风格。它的实现视图由多个组件构成:一组可执行文件或 WAR文件。
它的组件是服务,连接器是使这些服务能够协作的通信协议。每个服务都有自己的逻辑视图架构,通常也是六边形架构.(感觉三层架构更多些)
微服务架构将应用程序构建为松耦合、可独立部署的一组服务。请参阅:http://microservices.iolpatterns/microserviceshtml,FTGO可能微服务架构如下:
微服务架构的最核心特性是服务之间的松耦合性(https://enwikipediaorg/wiki/Loosecoupling)。服务之间的交互通过API完成,这样做有以下几个好处:
开发中我们经常把一些通用的功能打包到库或模块中,目的就是为了多个应用程序用到他的时候可以重用它而无需复制代码。
如果没有 Maven或npm库,我们今天的开发工作都会变得更困难。那么我们可能就会想在微服务架构中使用是否能使用共享库好呢?表面上看,它似乎是减少服务中代码重复的好方法。但是我们这样做的时候,需要确保不会意外地在服务之间引入耦合。举个栗子:
假如多个服务需要更新 order 业务对象的场景,一种选择是将该功能打包为可供多个服务使用的库。这样做的优点是可以消除代码重复。缺点是如果业务需求的变更影响了 order业务对象,开发者需要同时重建和重新部署所有使用了共享库的服务。这就非常麻烦了。相比之下,更好的选择是把这些可能会更改的通用功能(例如order 管理)作为服务来实现,而不是共享库。
所以我们应该尽量把不太可能改变的功能放入共享库中。例如,在典型的应用程序中,如果在每个服务中都实现一个通用的 Money类(例如用来实现币种转换等固定功能),没有任何意义,它不会经常改变,而且也很通用,这样就可以把它放到共享类库中。
如何定义一个微服务架构呢?文章中介绍了一个三部式流,世界上没有一个完美的机械化方法可以遵循,这个也只是大概方法, 现实中还需要具体分析I,不断的迭代。三部式流程如下:
1. 定义系统操作
根据功能性需求文档,定义系统可以提供的操作。如FTGO中,顾客需要下单,那么系统就需要提供需要提供让顾客下单的操作;而商家需要接单,那么商家还需要提供给可以让接单的操作。
2. 定义服务
这里说的就是如何分解服务。有几种策略可供选择。一种源于业务架构学派的策略是定义与业务能力相对应的服务。另一种策略是围绕领域驱动设计的子域来分解和设计服务。但这些策略的最终结果都是围绕业务概念而非技术概念分解和设计的服务。什么是子域?简单来说,一个子域是的领域Domain的子部分。无论公司的规模如何,每个领域都可以划分为子域,通过这样做,我们将公司领域的整个复杂性划分为更小的部分,我们将拥有能够很好地理解业务方面的领域专家,因为它是一个特定的子域。
3. 定义服务API和协作方式
定义应用程序架构的第三步是确定每个服务的API。为此,你将第一步中标识的每个系统操作分配给服务。服务可以完全独立地实现操作。或者,它可能需要与其他服务协作。在这种情况下,你可以确定服务的协作方式,这通常需要服务来支持其他操作。你还需要确定选用第3章中描述的哪种进程间通信机制来实现每个服务的API。
待补充
业务能力是一个来自于业务架构建模的术语。业务能力是指一些能够为公司(或组织)产生价值的商业活动。特定业务的业务能力取决于这个业务的类型。例如,保险公司业务能力通常包括承保、理赔管理账务和合规等。在线商店的业务能力包括:订单管理、库存管理和发货,等等
模式:根据业务能力进行服务拆分
定义与业务能力相对应的服务。请参阅:http://microservicesio/patterns/decomposition/%20decompose-by-business-capability.html
组织的业务能力通常是指这个组织的业务是做什么,它们通常都是稳定的。与之相反组织采用何种方式来实现它的业务能力,是随着时间不断变化的。这个准则在今天尤其明显,很多新技术在被快速采用,商业流程的自动化程度越来越高。例如,不久之前你还通过把支票交给银行柜员的方式来兑现支票,现在很多ATM 机都支持直接兑现支票,而今,人们甚至可以使用智能手机拍照的方式来兑现支票。正如你所见,“兑现支票”这个业务能力是稳定不变的,但是这个能力的实现方式正在发生戏剧性的变化。
这段作者讲的挺好,业务能力是稳定的,也就定义了一个组织的工作,但实现业务能力方式确实随着时间不断变化的,事实也确实如此。
一个组织有哪些业务能力,是通过对组织的目标、结构和商业流程的分析得来的。每一个业务能力都可以被认为是一个服务,除非它是面向业务的而非面向技术的。业务能力规范包含多项元素,比如输入和输出、服务等级协议(SLA)。例如,保险承保能力的输人来自客户的应用程序,这个业务能力的输出是完成核保并报价。
业务能力通常集中在特定的业务对象上。例如,理赔业务对象是理赔管理功能的重点能力通常可以分解为子能力。例如,理赔管理能力具有多个子能力,包括理赔信息管理、理赔审核和理赔付款管理。
把FTGO的业务能力逐一列出如下所示。
供应商管理:
Courier management:送餐员相关信息管理
Restaurant information management:餐馆菜单和其他信息管理,例如营业地址和时间
消费者管理:消费者有关信息的管理订单获取和履行。
Order management:让消费者可以创建和管理订单
Restaurant order management:让餐馆可以管理订单的生产过程
送餐
Courier availabilitymanagement:管理送餐员的实时状态
Deliverymanagement:把订单送到用户手中。
会计记账。
consumeraccounting:管理跟消费者相关的会计记账
Restaurant accounting:管理跟餐馆相关的会计记账
Courieraccounting:管理跟送餐员相关的会计记账。
其他
这个能力层次的有趣方面是有三个餐馆相关的能力:餐馆信息管理、餐馆订单管理和餐馆会计记账。那是因为它们代表了餐馆运营的三个截然不同的方面。
业务能力定义清楚了,就可以将业务能力映射到对应的服务了。将FTGO业务能力映射到服务,如下:
映射理由如下:
围绕能力组织服务的一个关键好处是,因为它们是稳定的,所以最终的架构也将相对稳架构的各个组件可能会随着业务的具体实现方式的变化而发展,但架构仍保持不变
待补充
改变一个类应该只有一个理由。-Robert C.Martin
如果一个类承载了多个职责,并且互相之间的修改是独立的,那么这个类就会变得非常不稳定。所以定义的每一个类都应该只有一个职责,因此也就只有一个理由对它进行修改。我们在设计微服务架构时也应该遵循SRP 原则,设计小的、内聚的、仅仅含有单一职责的服务。这会缩小服务的大小并提升它的稳定性。新的FTGO架构是应用SRP的一个例子为客户获取餐食的每一个方面(订单获取、订单准备、送餐等) 都由一个单一的服务承载。其实这个原则在实现类的每个方法时,每个类时,也都会用到。
在包中包含的所有类应该是对同类的变化的一个集合,也就是说,如果对包做出修改,需要调整的类应该都在这个包之内。-Robert C.Martin
闭包原则就是如果一个类的修改另一个类也必须修改,那么就要把他们两个放到一个包里,这里做目的是当业务规则发生变化时,开发者只需要对一个包做出修改,可以极大改成程序的可维护性。同样我们可以把它应用到拆分服务中,如果一个服务变化会影响到另一个服务,我们就把这两个服务放在一个组件中,这样做可以控制服务数量(防止拆分出的服务数量过多),变更和部署也更容易。理想情况下,一个变更只会影响一个团队和一个服务。CCP有效解决分布式单体的反模式法宝。
第一步是确定哪个服务是请求的初始入口点。许多系统操作可以清晰地映射到服务(如创建订单很明显是订单服务),但有时映射会不太明显。例如,考虑使用noteUpdatedLocation()操作来更新送餐员的位置。一方面,因为它与送餐员有关,所以应该将此操作分配给 Courier Service。另一方面,它是需要送餐地点的 Delivery Service。在这种情况下,将操作分配给需要操作所提供信息的服务是更好的选择(说的很绕啊??)。在其他情况下,将操作分配给具有处理它所需信息的服务可能是有意义的。如处理findAvailableRestaurants()这个操作,需要从RestaurantService服务查信息,所以就把这个操作分配到这个服务。
把操作分配给服务后,下一步是确定在处理每一个系统操作时,服务之间如何交互。
某些系统操作完全由单个服务处理。例如,在FTGO应用程序中,ConsumerService完全独立地处理 createconsumer()操作。但是,某些系统操作跨越多个服务,处理这些请求之一所需的数据可能分散在多个服务周围。例如createOrder()操作,orderService必须调用以下服务以验证其前置条件并使后置条件成立:
Consumer Service:验证消费者是否可以下订单并获取其付款信息。
Restaurant Service:验证订单行项目,验证送货地址和时间是否在餐厅的服区域内,验证订单最低要求,并获得订单行项目的价格
Kitchen Service:创建Ticket(后厨工单)
AccountingService:授权消费者的信用卡
为了完整定义服务API,你需要分析每个系统操作并确定所需的协作。其实到这一步,就是具体问题,具体分析了。
1.架构决定了软件的各种非功能性因素,比如可维护性、可测试性、可部署性和可扩展性,它们会直接影响开发速度。这也是软件架构重要的原因
2. 微服务架构是一种架构风格,它给应用程序带来了更高的可维护性、可测试性、可部署性和可扩展性。
3. 微服务中的服务是根据业务需求进行组织的,按照业务能力或者子域,而不是技术上的考量。
4. 有两种分解模式
按业务能力分解,其起源于业务架构
基于领域驱动设计的概念,通过子域进行分解。可以通过应用DDD并为每个服务定义单独的领域模型
5. 可以通过应用DDD并为每个服务定义单独的领域模型来消除上帝类,正是上帝类引起了阻碍分解的交织依赖项。