2016-02-25 46 views
0

最近我一直在研究软件架构的一些想法。我所看到的是,他们中的很多人都将用例/交互器(干净架构)或应用服务(DDD)作为我们应用程序的切入点。在交互器/使用案例/应用服务中违反德米特法律

我真的很喜欢这个想法,但有些事情一直困扰着我。

用户注入存储库的两种方式,您用它来获取域实体并对其执行操作。就像这样:

class Interactor 
    def initialize(repository) 
    @repository = repository 
    end 

    def call(entity_id) 
    entity = @repository.find(entity_id) 
    entity.do_something 
    end 
end 

如果我想在隔离测试这一点,我需要从@repository.find返回模拟,这已经是一个模拟。这不好,并告诉我,我违反了德米特法(这是案件)。

此外,这是过程性,这困扰我。

有没有更好的方法来做到这一点?

+0

我想补充一点,从目前的例子中你已经显示,你只是违反[单一责任原则](https://en.wikipedia.org/wiki/Single_responsibility_principle)通过让这个类做多个事情。我也会借此机会将这个类重写为Query,并且有一个可以调用'do_something()'函数的其他命令,所以您遵守[Command-Query Separation](https:// en .wikipedia.org/wiki/ Command%E2%80%93query_separation)模式和两个SRP。后来你可以将其他装饰器组合成这个实现.. – kayess

+0

..但它实际上只是在黑暗中拍摄而没有看到更多细节。 – kayess

+0

我读过一次,这并不违反SRP,因为此类更改的原因只是业务规则的更改。我其实同意这一点。我故意留下了足够的例子摘要,因为这发生了很多次。 – Thiago

回答

4

这不好,并告诉我,我违反了德米特法(这是案件)。

是怎么回事?

迪米特法则进行了总结,并以多种方式转述,但为了简单起见,让我们只看看小名单on Wikipedia

  • 每个单元有关于其他单位只有有限的知识:只与当前单位“密切”相关的单位。
  • 每个单位只能跟朋友交谈;不要与陌生人交谈。
  • 只与您的直接朋友交谈。

那么代码显示方式违反了这个规律? Interactor完全知道两件事情,一个特定的存储库和一个特定的实体。它对存储库的了解是一个技术问题,它使用该交互来获取实体的实例。而且它对实体的知识是一个商业关注点,它使用该交互来执行业务操作。

在任何域图或图表或白板图上,Interactor预计将与这两个单元有直接连接。确实如此。它没有达到这些单位有他们的邻居知识,它只是有自己的邻居的知识,并只与他们互动。

那么...究竟是什么问题?

作为一个纯技术问题,您可能可以直接注入实体而不是注入存储库。没有足够的关于问题中所表示的系统的信息来真正列出那里的优点和缺点。但这不是德米特法的问题,这只是依赖管理的实施问题。

单元测试需要你创建两个模拟,当然。但是这个单位与两个单位互动。这真是一个给定的。

+0

'Interactor'没有实体的知识。我不是直接在实体上注入实体。我可以很容易地将我的代码替换为'@ repository.find(entity_id).do_something',这种方式变得更清楚我违反了Demeter。我做了一个抽象的例子,因为这样的事情总是发生(除了当我创建实体时)。 – Thiago

+0

模拟测试返回模拟也让我清楚地认为。 – Thiago

+0

编辑后的评论:)与两个组件交互没有问题。问题是你正在与另一个返回的组件交互。 – Thiago

相关问题