单一责任原则如何与贫富/富域模型相关联?

目前正在对从另一个团队接管的内容进行一些代码审查,并对使用SRP及其与贫血或富域模型(由Martin Fowler定义)的关系存在疑问。 丰富的域模型概念是拥有智能对象,不仅可以设置/获取其属性,还可以执行更复杂的业务逻辑。 我喜欢它如何融入SRP?

假设我的模型类有一些属性可以暴露这些道具并提供一些简单的计算。 下一个要求是有可能将此对象数据存储在一些不受我控制的存储对象中,如下所示:

class MyObject { // get set // parse sth } 

存储方法存储

  storage.store(key, object); 

如果MyObject具有这样的存储方法,它是否违反了SRP

 public void store(Storage storage) { storage.store('keyOne', fieldOne); storage.store('keyTwo', fieldTwo); } 

从这个对象的pov来看,能够存储其状态是一个很好的想法。 其他方式可能是在这里介绍一种服务,并这样做:

 public StorageService { private Storage; // constructor here .... public void store(MyObject myobj); } 

你能指点一下我能读到的关于这个问题的链接吗? 我在这里找到了一个关于SO的post,但它没有完全回答我的问题。

如何在DDD中解决? 根据定义,DDD中的模型很丰富,可以看作具有太多责任。

富域模型( RDM )意味着控制模型行为逻辑属于模型,而不是像使用getter / setter一样处理模型。 这并不意味着包括持久性,安全性,如何在GUI中显示模型等所有内容都需要在模型中。

RDM和SRP是相辅相成的,它们不会相互冲突。

违反SRP / RDM:

 Car { // possibly violates SRP storeInDatabase(); // smells like anemic domain model getEngineState(); } 

遵循SRP / RDM:

 // usings aspects to remove cross-cutting concerns from the model and follow SRP @DatabaseSerializable Car { // rich domain model encapsulates engine state and exposes behavior drive(); } 

“根据定义,DDD中的模型很丰富,可以被视为具有太多责任”是对DDD的简单解释。 总是取决于你的模型有多好。 您可以使用DDD创建不良模型(例如,创建具有过多响应性的对象或创建贫血模型)。 DDD和SRP是两个很好的做法,如重构,TDD等等,但你应该用你的经验和判断(或其他人的)来补充它们的使用。 一切都有其优点和缺点,不要在应用任何练习时教条。

@Garrett Hall

我有点不同意你的说法“RDM和SRP齐头并进,它们不会相互冲突。” 根据我的经验,当过度强调SRP时,它会导致贫血的领域模型。 “不,我们不能做甚至帮助支持任何持久性,不,我们不能做21-CFR11,不,我们甚至不知道GUI是什么……”并且你的class级最终什么都不做只有一个贫血领域模型。

如果RDM被过分强调(这是我倾向于落入的方向/错误),那么SRP完全落在了路边,你最终会注意到你的class级有100多种方法而且显然做得太多了。

你需要找到一个平衡点,这是RDM和SRP正在发生的快乐媒介。 找到这种平衡是很困难的,并且通常涉及到团队内部更多的直觉和政治,而不是技术娴熟或规则。

“了解你自己”。 如果你像我一样,并倾向于过于复杂的课程,请注意。 当你看到别人的class级看起来太复杂了,甚至对你来说,那是一个大红旗。 同样地,如果你知道你对SRP非常苛刻,并且你看到一个甚至按照你的标准看起来很贫穷的课程,这是一个主要的代码味道。

现在,在某种程度上回答OP关于存储的问题,我认为很大程度上取决于存储的稳定性,标准性和抽象性。 如果存储是一些标准的XML,CSV或RDB抽象,那么对于知道如何存储自身的对象我完全没有问题。

Interesting Posts