厚实模型与 业务逻辑,您在哪里区分?


16

今天,我与组织中的另一位开发人员进行了激烈的辩论,讨论在何处以及如何向数据库映射的类中添加方法。我们使用sqlalchemy,并且数据库模型中现有代码库的主要部分不过是一袋带有类名的映射属性,几乎是从数据库表到python对象的机械翻译。

在论点中,我的立场是使用ORM的主要价值是可以将低级行为和算法附加到映射的类。模型首先是类,其次是持久性的(使用文件系统中的xml可以持久性,您无需关心)。他的观点是,任何行为都根本就是“业务逻辑”,并且必然属于持久性模型之外的任何地方,而持久性模型仅用于数据库持久性。

我当然确实认为,什么业务逻辑,应该分开,因为它与实现方法的较低层和域逻辑之间存在一定的区别,我认为这是模型类提供的抽象。在上一段中讨论过,但是我很难理解那是什么。我对API可能有什么更好的理解(在我们的例子中是HTTP“ ReSTful”),因为用户以他们想做的事情调用API,这与他们被允许做的事情以及如何做不同。完成。


tl; dr:使用ORM时,可以或应该在映射类的方法中进行哪些操作,应该忽略哪些内容以驻留在另一层抽象中?


在我看来,这是同时讨论的两个问题,持久性模型的问题首先是类,其次是持久性的(使用文件系统中的xml可以持久化,您无需关心)。以及代码的原因。通常,至少当我问自己为什么编写代码时,事情对我至少是清楚的,什么要求强制执行此代码。是客户对程序如何工作的要求,还是我们选择以哪种方式实施程序。对我来说,第一个是业务逻辑,第二个是域逻辑。这有什么帮助。

Answers:


10

我主要和你在一起;您的同事似乎在争论使用贫血领域模型反模式,还是在“持久性模型”中复制模型而没有明显的好处(我正在做一个Java项目,这样做很麻烦,只要模型发生任何变化,它就意味着工作量的三倍。

使用ORM时,映射类中的方法可以或应该使用哪种类型的东西,而应该将哪些东西遗漏掉,以驻留在另一层抽象中呢?

经验法则:该类应包含描述数据基本事实的逻辑,这些事实在所有情况下都是正确的。用例特有的逻辑应该在其他地方。验证就是一个例子,马丁·福勒(Martin Fowler)的一篇有趣的文章指出,应该将其视为上下文相关。


+1,作为答案的第二部分。对于第一部分,我敢肯定,为什么您说贫血领域模型在发生变化时需要大量的“额外”工作。我的理解是,变更将以任何方式发生,但是会发生在几个不同的类中(这很不好),但变更量几乎相同;我猜?
NoChance 2012年

1
@Emmad Kareem:评论是关于具有持久的持久性和领域模型的。向模型添加属性然后需要将其添加到两个模型类(而不是一个)中,以及它们之间的任何映射(理论上可以是自动的,但通常认为单独拥有一个好主意的傻瓜) “持久性模型”决定通过使它们不同来证明这种分离的合理性,例如,数据类型与DB类型模型更匹配),因此是变化量的2 + X倍,其中X介于0和因模糊而导致的生产力损失小时之间变化映射问题。
Michael Borgwardt 2012年

3

这是一个判断电话,实际上取决于您预期的规模和开发规模。最严格的方法是将ORM类型限制为数据访问组件,并在公共库中使用POCO作为所有层引用和使用的类型。这将允许将来的物理隔离以及逻辑隔离。您还可以决定在UI和业务逻辑层之间应该存在一个附加层。这通常称为外观或业务接口层。这个额外的层是您的“用例代码”所在的位置。各个松散耦合的代码由Facade / BI层调用(例如Facade具有ProcessOrder()函数,该函数以1:M的时间调用业务逻辑以执行实际处理订单所需的所有步骤)。

然而,所有这些都被提及:很多时候,如此多的架构设计根本就是不必要的过大杀伤力。例如,专门为简单的网站编写代码,您无意打包其组件以供重复使用。创建MVC网站并将EF对象用于这种类型的解决方案是完全有效的。如果站点以后需要扩展,则可以查看集群或一个经常丢失竞争的过程,称为“重构”。


3

只是提醒您的同事,您不需要像在Java项目中那样对模型进行过度架构。我的意思是,比较两个持久化对象是行为,但持久层未指定。因此,第6个啤酒问题是:为什么要使用完全不相关的类来描述同一事物?当然,持久性是一个足以单独处理模型的重要方面,但不足以保证将模型与其他所有事物区分开。如果您开车,洗车或破坏车,那么您将一直在操纵汽车。

那么,为什么不将所有这些不同方面组合成一个模型类呢?您需要一堆处理持久对象的类方法-将它们放在一个类中;您有一堆处理验证的实例方法-将它们放入另一个实例方法中。最后,将两者混和在一起!您在那里就获得了一个聪明,自我意识和完全包含的模型表示。


1

除了其他答案外,在将丰富的域模型与ORM一起使用时,请注意隐藏的隐蔽之处。

尝试实现类似以下伪代码的东西时,在持久化模型类中注入多态服务时遇到了问题:

Person john = new Person('John Doe')
Organisation company = organisation_repository.find('some id')
Employee our_collegue_john = company.hire(john)

在这种情况下,组织可能需要HRService作为构造函数依赖项(例如)。使用ORM时,通常无法轻松地控制模型类的实例化。

我正在使用Doctrine ORM和Symfony的服务容器。我不得不以一种不太优雅的方式修补ORM,别无选择,只能将持久性和业务模型分开。我还没有尝试过sqlachemy。在这方面,Python可能比PHP更灵活。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.