清洁架构 - 罗伯特马丁 - 用例粒度

时间:2016-01-29 15:51:46

标签: oop architecture software-design

我正在考虑在一个项目中实施Robert Martin的Clean Architecture,我正在努力找出如何处理非平凡的用例。

我发现很难将体系结构扩展到复杂/组合的用例,尤其是使用者是系统而不是用户的情况,就像系统执行某种批处理一样。

为了便于说明,我们假设用例如"系统更新所有帐户余额"以伪代码实现,如

class UpdateAllAccountBalancesInteraction {
    function Execute() {
        Get a list of all accounts
        For each account
            Get a list of all new transactions for account
            For each transaction
                Perform some specific calculation on the transaction
            Update account balance
    }
}

此外,"获取所有帐户的列表","获取帐户的所有新交易列表","对交易进行一些特定计算" ;,"更新帐户余额"都是他们自己的有效用例,每个用例都已经在自己的交互类中实现。

出现了一些问题:

  • 用例"系统更新所有帐户余额"即使是有效的 用例或应将其分解为较小的用例(尽管如此) 从商业角度看它似乎有道理,它是一个 合法的商业场景)?
  • 是UpdateAllAccountBalancesInteraction 合法的互动?
  • 是否允许交互/应该协调其他交互?
  • 是编排其他代码的代码 互动真的属于其他地方吗?
  • 是否可以 UpdateAllAccountBalancesInteraction作为交互,但拥有它 调用其他交互者共享的函数而不是作为一个 其他互动者的协调者?

2 个答案:

答案 0 :(得分:1)

显然,您有一个新的高级别互动,与较低级别的互动共享一些(或许多)常见功能。没关系。

如果业务需要一个名为UpdateAllAccountBalances的用例,那么它就是一个有效的用例,并且以反映业务逻辑的方式命名它是件好事。 / p>

它是o.k.如果这可以准确反映您的业务逻辑,则可以进行一次交互以调用其他交互问自己以下问题:如果UpdateAccountBalance的要求发生变化,这是否也会以完全相同的方式影响UpdateAllAccountBalances?如果答案是肯定的,那么实现此目标的最佳方法是UpdateAllAccountBalances调用UpdateAccountBalance,否则,您需要在两个地方进行更改才能保持一致。如果答案是否定的,那么你想要解耦两个交互,这可以通过让它们调用共享函数来完成。

答案 1 :(得分:0)

我的建议是以不同方式解决问题。在域模型中表示问题本身,而不是使用过程方法。您看到了用例的一些问题,其中之一就是它们的粒度通常是不确定的。

在域模型中,表示特定事物(即“帐户”)的标准方式是使用两个对象。一个代表特定帐户,一个代表所有帐户共有的相关对象。

AccountCatalog (1) ---- (*) SpecificAccount

在您的示例中,SpecificAccount将具有服务(方法)“UpdateBalance”。 AccountCatalog有一个服务(方法)“UpdateAllBalances”,它将UpdateBalance消息发送到其集合中的所有SpecificAccounts。

现在任何东西都可以发送UpdateAllBalances消息。另一个对象,人际互动或其他系统。

我应该注意,一个帐户“知道”(即维持)自己的余额,而不是被告知要更新,这是很常见的。