【发布时间】:2023-03-19 08:50:01
【问题描述】:
我一直在尝试在我的新项目中遵循领域驱动的设计方法。我一直通常使用 Spring 进行依赖注入,它很好地将我的应用程序代码与构造代码分开,但是,使用 DDD,我似乎总是有一个域对象想要创建另一个域对象,它们都有状态和行为。
例如,给定一个媒体文件,我们希望将其编码为不同的格式 - 媒体资产调用转码服务并接收回调:
class MediaAsset implements TranscodingResultListener {
private NetworkLocation permanentStorage;
private Transcoder transcoder;
public void transcodeTo(Format format){
transcoder.transcode(this,format);
}
public void onSuccessfulTranscode(TranscodeResult result){
Rendition rendition = new Rendition(this, result.getPath(), result.getFormat());
rendition.moveTo(permanentStorage);
}
}
这会引发两个问题:
- 如果再现需要一些依赖项(例如 MediaAsset 需要“转码器”)并且我想使用 Spring 之类的东西来注入它们,那么我必须使用 AOP 才能运行我的程序,但我不会喜欢。
- 如果我想对 MediaAsset 进行单元测试,以测试新格式是否已移至临时存储,那么我该怎么做?我无法模拟再现类来验证它是否调用了它的方法...将创建真正的再现类。
我考虑过用工厂来创建这个类,但是仅仅包含导致问题的“new”关键字就需要很多代码开销。
这里是否有我遗漏的方法,或者我只是做错了?
【问题讨论】:
-
注入依赖不需要使用AOP。
@Autowired之类的东西需要 AOP。但是要实现注入,一个构造函数参数或一个 setter 方法就足够了。关键是摆脱对象内部包含逻辑的任何新语句,而是在外部创建所需的依赖项。即使我使用 Autowire 魔术,我也经常定义至少一个包可见构造函数,它接受所有必需的依赖项作为参数,并且可以用来单独测试一个 bean。 -
“关键是摆脱对象内部包含逻辑的任何新语句,而是在外部创建所需的依赖项。” - 这就是问题 - 怎么做?工厂?
-
正如已经建议的答案,如果您的对象需要创建新对象,那么工厂就是要走的路。因此,您可以将 new 转换为对工厂的静态依赖,并且可以使用构造函数、setter 或魔法注入。
标签: java spring unit-testing domain-driven-design