域模型类应该始终依赖于基元吗



Architecture Patterns with Python进行到一半时,我有两个关于域模型类应该如何结构化和实例化的问题。假设在我的域模型上,我有类DepthMap:

class DepthMap:
def __init__(self, map: np.ndarray):
self.map = map

根据我在书中的理解,这个类是不正确的,因为它依赖于Numpy,并且它应该只依赖于Python基元,因此问题是:域模型类应该只依赖Python基元吗

假设上一个问题的答案是类应该只依赖于基元,那么从Numpy数组创建DepthMap的正确方法是什么?假设现在我有更多的格式,可以从中创建DepthMap对象。

class DepthMap:
def __init__(self, map: List):
self.map = map

@classmethod
def from_numpy(cls, map: np.ndarray):
return cls(map.tolist())
@classmethod
def from_str(cls, map: str):
return cls([float(i) for i in s.split(',')])

或工厂:

class DepthMapFactory:
@staticmethod
def from_numpy(map: np.ndarray):
return DepthMap(map.tolist())
@staticmethod
def from_str(map: str):
return DepthMap([float(i) for i in s.split(',')])

我认为即使是他们在书中提到的Repository Pattern也可以放在这里:

class StrRepository:
def get(map: str):
return DepthMap([float(i) for i in s.split(',')])
class NumpyRepository:
def get(map: np.ndarray):
return DepthMap(map.tolist())

第二个问题:从不同来源创建域模型对象时,正确的方法是什么

注意:我的背景不是软件;因此一些OOP概念可能是不正确的。不要投反对票,请评论并让我知道如何改进这个问题。

这本书是我写的,所以我至少可以回答你的问题。

您可以在域模型中使用除基元(str、int、boolean等)之外的东西。一般来说,尽管我们无法在书中展示它,但您的模型类将包含对象的整个层次结构。

您希望避免的是,您的技术实现以一种难以表达您的意图的方式泄漏到代码中。除非你的域是Numpy,否则在你的代码库中传递Numpy数组的实例可能是不合适的。我们试图通过将有趣的东西从胶水中分离出来,使代码更容易阅读和测试。

为此,您可以拥有一个DepthMap类,该类公开一些行为,并且恰好有一个Numpy数组作为其内部存储。这与使用库中的任何其他数据结构没有任何不同。

如果您将数据作为平面文件或其他文件,并且在创建Numpy数组时涉及到复杂的逻辑,那么我认为Factory是合适的。这样,您就可以将生成DepthMap的无聊、丑陋的代码保留在系统的边缘,并排除在模型之外。

如果从字符串创建DepthMap真的是一行代码,那么类方法可能更好,因为它更容易找到和理解。

我认为依赖纯语言扩展的库是完全可以的,否则你将不得不定义大量的";接口合同";(Python没有作为语言结构的接口,但这些接口可以是概念性的)来抽象掉这些数据结构,最终那些新引入的合同可能无论如何都是糟糕的抽象,只会导致额外的复杂性。

这意味着您的域对象通常可以依赖于这些纯类型。另一方面,我也认为这些类型应该被视为"语言";基元";(native可能更准确)就像datetime一样,并且你希望避免原始的痴迷。

换句话说,作为域概念的DepthMap可以依赖于Numpy进行构建(这里不需要抽象),但Numpy不一定可以深入到域中(除非它是适当的抽象)。

或者在伪代码中,这可能很糟糕:

someOperation(Numpy: depthMap);

这可能更好的地方:

class DepthMap(Numpy: data);
someOperation(DepthMap depthMap);

关于第二个问题,从DDD的角度来看DepthMap类有一个Numpy数组作为其内部结构,但必须从其他来源构建(例如字符串或列表)最好的方法是存储库模式?或者这只是为了处理数据库和工厂是更好的方法吗?

Repository模式专门用于存储/检索,因此不合适。现在,您可以直接在DepthMap上有一个接受Numpy的工厂方法,也可以有一个专用的工厂。如果您想将DepthMapNumpy解耦,那么引入一个专用工厂是有意义的,但乍一看似乎没有必要。

域模型类是否只依赖于Python基元

纯粹从领域驱动的设计角度来看,这绝对没有理由是真正的

  • 您的域动态通常将使用域的语言来描述,即实体和值对象的操作(Evans,2003),它们是将域语义置于数据结构之上的外观。

  • 表面背后的底层数据结构是完成工作所需的一切。

在领域驱动的设计中,没有什么要求您放弃经过充分测试的高度优化的Bazzlefraz的现成实现,而是从头开始编写自己的实现。

领域驱动设计的一部分要点是,我们希望对有助于业务的代码进行投资,而不是对管道进行投资。

最新更新