目前,正在对另一个团队接管的东西进行一些代码审查,并对应用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);
}

您能指出我可以读到这个问题的任何链接吗?我在这里找到了一个线程,但这并不能完全回答我的问题。

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

有帮助吗?

解决方案

丰富的域模型(RDM)意味着 逻辑 管理模型的 行为 属于模型中,而不是用getters/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是什么...”,您的班级最终做了 没有什么 并且只有一个贫血的域模型。

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

您需要找到平衡,即RDM和SRP都发生的快乐媒介。并且发现这种平衡是艰难的,并且通常涉及团队中比技术精通或规则更多的肠道和政治。

“知道自己”。如果您像我一样,并且倾向于过于复杂的课程,请注意。而且,当您看到别人的班级甚至对您来说太复杂了,那是一个大的危险信号。同样,如果您知道自己对SRP非常核心,并且看到一堂课,即使按照您的标准,也是贫血的,那是一种主要的代码气味。

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top