API 模块解耦 – CodesCode
软件更改或维护的成本主要高昂,因为级联引起的耦合软件系统的重大变化
软件的成本主要包括软件的维护成本。更改或维护软件的成本主要是由于级联引起的,级联是一个耦合软件系统的重大变化。因此,将软件系统解耦几乎总是会导致设计更好、更低的变更成本的系统。让我们通过一个例子来看看这个问题。
举例说明
假设你经营一家兽医诊所,你需要一个软件系统来管理诊所的来访:记录来访、分配来访流程并创建来访发票。
你可能会有三个服务,分别处理上述功能:
现在,我们来添加模块之间的交互:
- 来访服务接受顾客、宠物、来访日期和时间作为输入,并创建一次来访。
- 流程服务接受一次来访并为其添加一个或多个流程。
- 发票服务接受一次来访并为其创建发票。
假设来访实体如下所示:
visit { visitId customerName petName visitDate procedures [] }
流程实体可能如下所示:
procedure { procedureId procedureType price }
为了创建发票,发票服务需要的是来访详细信息和已完成的流程:
invoice { visitDetails proceduresDone [] amountDue }
我们有几种选择可以传递给发票服务的数据:
- 它可以接受来访对象和流程对象数组。然后,它会根据来访对象和流程数组创建可打印的详细信息,并计算流程数组中每个流程的价格总和。
或者
- 它可以接受
visitId
,并调用来访服务以获取打印的来访详细信息,并调用发票服务以获取在访问期间完成的流程的名称列表和价格。
耦合访问
以上两种选项中哪个是更好的设计选择?让我们看看这个简单软件系统在这两个选项上是多么解耦或耦合。
选项1:传递整个对象
在这里,如果我们更改访问模式,比如添加客户电话号码,将需要更改来访服务以及发票服务。发票服务接受来访对象并创建可打印的来访详细信息放在发票上。
此外,如果更改流程,比如添加新的流程类型,将不仅需要更改流程服务,还需要更改发票服务,因为发票服务接受流程对象。它需要创建新流程类型的可打印版本。
选项2:仅发送不变数据
在这种情况下,发票服务仅接受visitId
并调用来访服务,因为它需要在发票上打印来访信息。这样,来访模式可以根据需要更改,只需更改来访服务。发票服务和来访服务之间的契约如下所示:
GetVisitDetails(visitId) → string
同样,发票服务会调用流程服务获取visitId
的流程名称和价格数组,如下所示。然后,如果添加新流程,它们只会影响流程服务,不需要更改发票服务。
GetVisitProceduresWithPrices(visitId) → Dict<string, decimal>
结论
在设计软件时,如果我们减少模块之间的耦合,我们会使设计更加模块化,并确保对一个模块的更改不会影响其他模块,或者至少变更的级联效应是有限的,从而降低了更改的成本。
谢谢阅读!请分享您的想法。
Leave a Reply