领域对象、POCO 和实体之间有什么区别?

99

我原本以为它们基本上都是相同的。那么模型对象也一样吗?

目前,在我的架构中,我有:

class Person 
{

    public string PersonId;        
    public string Name;
    public string Email;

    public static bool IsValidName() { /* logic here */ }
    public static bool IsValidEmail() { /* logic here */ }
}


class PersonService
{
    private PersonRepository pRepository;

    PersonService()
    {
        pRepository = new PersonRepository();
    }

    public bool IsExistingEmail(string email)
    {
        //calls repo method to see if email is in db
    }


    public Person GetPerson(email)
    {
        return pRepository.Get(email);
    }


    public void SavePerson(Person p)
    {
        if (Person.IsValidEmail(p.Email) && !IsExistingEmail(p.Email)
        {
            pRepository.Save(p);
        }
    }

}


class PersonRepository
{
    public void Save(Person p)
    {
        //save to db
    }

    public Person Get(string email)
    {
        //get from db
    }

    public bool IsExistingEmail(string email)
    {
        //see if email in db
    }

}

那么上述的类中,哪些是POCODomain ObjectModel objectentity

5个回答

133

我的(非标准)通俗易懂的定义

  • POCO - 简单老式的 %Insert_Your_Language% 对象。它是一个没有逻辑的类型,仅在内存中存储数据。通常只会看到自动属性,有时会包含字段和构造函数。
  • 领域对象 是与您的领域相关的类的实例。我可能会将任何卫星或实用程序对象从领域对象中排除,例如,在大多数情况下,领域对象不包括日志记录、格式化、序列化、加密等内容-除非您专门构建一个产品来记录、序列化、格式化或加密。
  • 模型对象 我认为与领域对象相同。人们往往可以互换使用(我可能错了)
  • 实体 一个具有id的类
  • 存储库 一个类,从一侧与数据存储交互(例如数据库、数据服务或ORM),并向服务、UI、业务层或任何其他请求主体发出请求。它通常隐藏所有与数据相关的内容(如复制、连接池、键约束、事务等),使其简单地处理数据
  • 服务 通常通过公共API提供某些功能的软件。根据层,它可以是例如RESTful自包含容器,或允许您查找所需类型的特定实例的类。

原始答案

这些terms在(分布式)领域驱动设计中被广泛使用,但它们并不相同。术语模型对象可以用作领域对象的同义词。

领域对象。业务特定领域中代表某个含义的对象。领域对象主要由实体和值对象表示。一般来说,生存在领域层的大多数对象都有助于模型,并且是领域对象。

实体。一个对象基本上不是由其属性定义的,而是由连续性和身份线程定义的。(意味着它必须有Id

POCO。一个没有复杂逻辑的简单对象,通常只有很少的属性,并与ORM一起使用或作为数据传输对象

class Person - 实体和POCO,此类的实例是领域对象
class PersonService - 服务
class PersonRepository - 存储库


4
请看我上面的代码示例,让我知道您将如何应用这些术语。 - jpshook
1
如果一个POCO不需要被识别,那么它怎么能被ORM加载呢?这是不合逻辑的! - Pascal
4
为什么这个明显错误的信息却获得了最多的赞同和接受。POJO不是一个没有逻辑的类型。事实上,Martin Fowler特别创造了POJO这个词来对比Entity Beans(“我们指出将业务逻辑编码到常规java对象中而不是使用Entity Beans的许多好处。”)。https://www.martinfowler.com/bliki/POJO.html - THIS USER NEEDS HELP
2
如果我的评论措辞强烈了一些,我很抱歉,但是无论如何,当术语的创造者明确将POJO定义为包含业务逻辑时,你的个人经验并不重要。实际上,他会将你的做法归类为贫血领域模型(https://martinfowler.com/bliki/AnemicDomainModel.html),他认为这是一种反模式,并建议您改用POJO。是否是反模式超出了该定义的范围,但有一件事是清楚的:POJO并**不意味着**没有任何业务逻辑的对象。 - THIS USER NEEDS HELP
2
@JohnPancoast 一个只有setter/getter方法的对象就是数据传输对象(DTO)。有时它也是一个完整的JavaBean。POJO/POCO是对这种试图让你相信你不能在不继承其神奇力量的情况下使用普通对象解决问题的框架性废话的拒绝。当你编写一个好的POJO时,你甚至无法判断是否正在使用框架。 - candied_orange
显示剩余14条评论

21

基本上这归结于内部逻辑

  1. 领域对象具有用于验证等的内部领域逻辑。
  2. 模型基本上是一个轻量级的领域对象,它们知道它们持有的数据,但实际上并不知道它将如何被使用。
  3. 实体保存数据,并且对其来自何处以及将在何处保存、更新等有一些内部了解。
  4. POCO保存数据,可能对其本身有一些内部了解,例如属性集合中所有项的总值是多少。
  5. DTO是最简单的项目,它只保存数据,没有逻辑。

它们基本上都是用于相同的目的,只是你想让它们变得多聪明。

根据您的代码示例,Person类可以是领域对象或模型,其他两个是服务和存储库。领域对象、Pocos、模型、dtos等都像消息一样被传递,从一个层传递到另一个层,像PersonService这样的服务类是应用程序中的一层,PersonRepository也是如此。要获取良好的概述,请查看http://bob-the-janitor.blogspot.com/2009/07/n-tier-design-revisit-part-1-over-view.html,在这种情况下,它谈论的是使用数据实体,这基本上是一个dto。


18

“domain object”更多地是指功能的内涵;领域对象是特定于您的逻辑实现的东西,可能比简单的POCO(Plain Old CLR Object)更加复杂;“entity”则表示代表某个东西(通常是与持久性媒介相关),而POCO仅仅是一个类的快速标识符。模型只是用于表示对象的术语(通常包含状态,并且通常处理UI或DB)。

并不存在任何功能上的差异,它们只是不同的术语,更贴切地描述了某些东西。这就像赛车、卡车和家用轿车之间的区别一样,它们都是汽车,但每个术语都更具描述性。


我更新了内容,包括了代码示例,请您能否评论一下?我只是想确保在提问时使用正确的术语。 - jpshook

13

以上答案中已经有关于域和模型的好解释了。

在数据库上下文中,实体意味着实体关系模型ERD中的项目(即表中的行)。

Microsoft-Dotnet-EntityFramework-World中,实体意味着可以使用数据(库)上下文从数据库加载并保存的对象。通常情况下,实体不能没有其数据(库)上下文而存在。测试这些类的业务功能是困难的。

Pocos(普通旧常见运行时对象)可以在没有持久化框架(EntityFramework或NHibernate)的情况下存在,因此它们更容易进行测试。

poco一词是pojo(普通旧Java对象)的改编,它们是为了同样的原因在Java世界中创建的。


为什么要给负评?问题是“领域对象、POCO和实体之间有什么区别?”我解释了实体和Poco之间的区别。 - k3b
以上答案已经对领域和模型进行了很好的解释。我如何将依赖于其他答案的答案选择为有效答案? - jpshook
回顾过去,我应该只是评论要求您提供完整的答案。下次会多想两次。 - jpshook

3

域对象是应用程序的领域层中的实体,例如地址类。"模型"的意思相同 - 是"领域模型"中的实体。

POCO (普通的 CLR 对象) 是一个没有行为(方法)定义,只包含数据(属性)的对象。POCO 通常用作 DTO (数据传输对象),以在层之间传递数据,并且该数据通常用于填充域对象/实体。


POCO不能成为实体吗?我认为POCO可以具有行为,但必须是持久性无知的吗? - jpshook
@Developr 是的,你的领域模型/实体确实可以是POCO - 这被称为“贫血”领域模型 - 参见http://www.martinfowler.com/bliki/AnemicDomainModel.html - MattDavey
你认为这个设计是贫血的吗?你如何定义“富领域对象”?如果领域对象不能直接或间接地与数据库交互,它们可以拥有什么样的丰富功能呢? - jpshook
@Developr 我认为由POCO对象组成的领域模型是贫血的,因为传统上POCO类没有任何丰富的功能,只有数据。遵循关注点分离原则(http://en.wikipedia.org/wiki/Separation_of_concerns),领域模型中的对象不应该关心数据库访问(因此流行的术语“持久化无知”)。领域模型中的实体应该具有业务逻辑的功能 - 它们应该捕获和封装问题/领域的逻辑规则和工作流程。 - MattDavey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接