aet*_*eus 10 architecture clean-architecture
我可以在网上找到它的任何实现方法,实际上并没有为您提供一种与该方法无关的实用框架。
我已经看到一些解决问题的建议:
使存储库方法原子化
使用例原子化
它们都不是理想的。
案例1:大多数用例不仅仅依靠一种存储库方法来完成工作。当您“下订单”时,您可能必须调用“订单存储库”的“插入”方法和“用户存储库”的“更新”方法(例如:扣除商店信用额)。如果“插入”和“更新”是原子的,那将是灾难性的-您可以下订单,但实际上无法使用户为此付费。或让用户付款,但订单失败。都不是理想的。
情况#2:没有更好。如果每个用例都生活在一个筒仓中,则可以使用它,但是除非您要重复代码,否则您常常会发现自己拥有取决于其他用例操作的用例。
假设您有一个“下订单”用例和一个“给予奖励积分”用例。两种用例均可独立使用。例如,当老板在系统发布日周年纪念日登录时,老板可能希望向系统中的每个用户“提供奖励积分”。当然,每当用户进行购买时,您当然都会使用“下订单”用例。
现在,系统启动十周年了。您的老板决定-“好的Jimbo-对于2018年7月,每当有人下订单时,我都想给我奖励积分”。
为了避免直接更改此一次性想法的“下订单”用例(可能在明年被放弃),您决定创建另一个用例(“促销中的下订单”),该用例仅称为“下订单”和“赠送积分”。精彩。
只有...你不能。我的意思是,你可以。但是你回到正题。您可以保证“下订单”是否成功,因为它是原子的。并且您可以保证“给与奖励积分”是否由于相同的原因而成功。但是,如果其中一个失败,则您将无法扮演另一个角色。它们不共享相同的事务上下文(因为它们在内部“开始”和“提交” /“回滚”事务)。
上面的场景有几种可能的解决方案,但是它们都不是很“干净”的(想到工作单元-在用例之间共享工作单元将解决此问题,但是UoW是一个丑陋的模式,仍然存在知道哪个用例负责打开/提交/回滚事务的问题)。
我把交易放在控制器上。控制器知道较大的框架,因为它可能至少具有诸如框架注释之类的元数据。
关于工作单元,这是一个好主意。您可以使每个用例都开始事务。在内部,工作单元或者启动实际事务,或者增加被调用启动的计数器。然后,每个用例将调用提交或拒绝。当提交计数等于0时,调用实际的提交。Reject跳过所有这些,回滚,然后出错(异常或返回码)。
在您的示例中,包装用例调用开始(c = 1),下订单调用开始(c = 2),下订单提交(c = 1),奖励调用开始(c = 2),奖励调用提交(c = 1),包装提交(c = 0),以便实际提交。
我将子事务留给您。