这是一个具有现实意义的抽象问题。
我有两个微服务;我们称它们为CreditCardsService
和SubscriptionsService
。
我还有一个SPA,应该使用SubscriptionsService
,以便客户可以订阅。为此,SubscriptionsService
有一个终结点,您可以在其中POST
订阅模型来创建订阅,并且该模型中有一个creditCardId
指向应付款的信用卡订阅。有某些业务规则说明您是否可以使用该信用卡进行订阅(有效期超过12个月,这是VISA等)。这些特定的业务规则与SubscriptionsService
问题是,从事SPA的团队需要/CreditCards
中的SubscriptonsService
端点,该端点返回可以在订阅模型中使用的用户的所有有效信用卡。他们不想在SPA中实现与SubscriptionsService
本身相同的业务验证规则。
在我看来,这似乎违反了微服务设计至关重要的SOLID原则;特别是关注点分离。我也问自己,这将树立什么先例?我们是否必须向OrdersService或可能使用/CreditCards
作为其模型属性的任何其他服务中添加一个creditCardId
端点?
所以主要问题是:设计此的最佳方法是什么?是否应该在前端和后端之间复制业务验证逻辑?是否应将此新端点添加到SubscriptionsService
?我们应该尝试简化业务逻辑吗?
答案 0 :(得分:3)
这是一个完全公平的请求,您应该提供该端点。如果您定义了什么CC适用于您的服务的规则,那么您也应该提供处理它的所有帮助。
不应重复逻辑。这会使系统无法维护。
这与SOLID无关,尽管SRP也会说,如果您负责某件事,那么任何相关逻辑也都属于您。由于已在此处定义此关注点,因此无法将其与您的服务分开。
作为一种解决方案,我可能要研究是否可以摆脱与CC Service的链接,因为您已经拥有CC Service。我是否可以将带有构造查询的客户端重定向到CC服务,以获取所有相关CC,而实际上在Subscription Service中不知道它们。
答案 1 :(得分:2)
设计此内容的最佳方法是什么?应该进行业务验证 逻辑在前端和后端之间重复?应该这样吗 是否将新的端点添加到SubscriptionsService?我们应该尝试 简化业务逻辑?
从我的角度来看,我会将“ Subscription BC”(S-BC)与“ CreditCards BC”(CC-BC)集成在一起。 CC-BC在上游,S-BC在下游。您可以使用CC-BC中的REST API或消息队列来完成它。
但是我验证的是使用CC进行的操作,而不是CC本身,即验证“此CC是否对订阅有效”。验证在S-BC中进行。
如果SPA要检索“他/她可用于订阅的用户的CC”,则这是S-BC的功能。
客户端(SPA)应该调用S-BC API以使用该功能,然后S-BC执行该功能以从CC-BC获取CC并进行验证。
答案 2 :(得分:1)
在微服务和DDD中,如果订阅服务的数据与订阅的受限制上下文有关,则订阅服务应具有信用卡终结点。
信用卡端点提供的数据模型可能与您在信用卡服务本身中发现的数据模型稍有不同,因为在订阅的上下文中,信用卡的外观或行为可能有所不同。订阅服务可能具有信用卡表或后备存储,以支持存储其自己的信用卡架构并引用一些真实来源以使数据保持良好状态(例如,有关公交车卡事件的消息或其他信息)机制)。
这可以实现三件事:首先,如果卡掉了一段时间,订阅服务将不会被完全淘汰,它可以引用自己的表并正常工作。其次,您的域代码将更加集中,因为它只需要处理对解决当前问题真正重要的信用卡属性。最后,如果您的卡商店甚至可以具有在商店中计算并具体化的额外领域特定属性。
强制性福勒链接:Bounded Context Pattern
答案 3 :(得分:0)
即使真理的来源是领域模型,最终您也必须在 在域模型级别,验证仍可以在域模型级别(服务器端)和 UI(客户端)。 客户端验证为用户带来了极大的便利。节省了他们原本会花费的时间 等待往返服务器,可能返回验证错误。从业务上讲,甚至有几个 每天几分之一秒乘以数百次,这会增加很多时间,费用和 挫折。简单直接的验证使用户可以更有效地工作, 产生更高质量的输入和输出。 正如视图模型和域模型不同,视图模型验证和域模型 验证可能相似,但用途不同。如果您担心DRY(请勿 重复自己的原则),请考虑在这种情况下,代码重用也可能意味着耦合,并且在企业应用程序中,重要的是不要将服务器端耦合到客户端,而不是将服务器端耦合到客户端。 遵循DRY原则。 (面向容器的NET应用程序的NET-微服务体系结构)