域模型类是否应该始终依赖于基元?

2024-04-26 13:16:23 发布

您现在位置:Python中文网/ 问答频道 /正文

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概念可能不正确。请发表评论,让我知道如何改进这个问题,而不是投反对票


Tags: from模型selfmapreturndefnpfloat
3条回答

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

您可以在域模型中使用除原语(str、int、boolean等)以外的东西。通常,尽管我们无法在书中展示,但您的模型类将包含对象的整个层次结构

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

为此,您可以使用一个DepthMap类来公开一些行为,并且碰巧有一个Numpy数组作为其内部存储。这与使用库中的任何其他数据结构没有任何区别

如果您以平面文件或其他形式获取数据,并且创建Numpy数组涉及复杂的逻辑,那么我认为工厂是合适的。这样,您就可以保留在系统边缘生成DepthMap的枯燥、难看的代码,并将其排除在模型之外

如果从字符串创建DepthMap实际上是一个单行程序,那么classmethod可能更好,因为它更容易找到和理解

我认为完全可以依赖纯语言扩展的库,否则您将不得不定义大量的“接口契约”(Python没有作为语言构造的接口,但这些接口可以是概念性的)要抽象掉这些数据结构,最终那些新引入的契约可能是糟糕的抽象,只会导致额外的复杂性

这意味着您的域对象通常可以依赖于这些纯类型。另一方面,我也认为这些类型应该被视为语言“原语”(母语可能更准确),就像datetime一样,并且您希望避免primitive obsession

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

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

someOperation(Numpy: depthMap);

如果这可能更好:

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

And regarding the second question, from a DDD perspective if the DepthMap class has a Numpy array as it's internal structure but has to be constructed from other sources (string or list for example) would the best approach be a repository pattern? Or is this just for handling databases and a Factory is a better approach?

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

Should Domain Model classes rely only on Python primitives

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

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

  • 外观后面的底层数据结构是完成工作所需的一切

领域驱动设计中没有任何东西要求您放弃经过良好测试的高度优化的Bazzlefraz现成实现,而是从头开始编写自己的

领域驱动设计的一部分要点是,我们希望将我们的投资投入到帮助业务的代码中,而不是管道

相关问题 更多 >