• ORM中的Model与DDD中的DomainModel


    0.引言

    在现有的系统开发中,大部分的系统应该都会用到ORM,无论用的是EF还是NHibernate。作为对象和持久化数据的桥梁,ORM确实非常方便,以至于在DDD的时候,我们很自然的将 ORM中的Model(实体)表达成DDD中的 DomainModel(领域对象)。

    但这真的合理吗?我们先引入两个例子来探讨这个问题。

    1.例子1:订单聚合

    下述聚合引自汤神的博客:

    我们看以上的聚合设计非常经典。Order对象作为聚合根,OrderItem建模成实体,只要在当前的订单聚合中不重复即可。

    但在真正的数据存储的时候,我们的OrderItem对象肯定不能是这样子的。

    假如:我们有两个订单A和B,订单A包含了商品1和商品2,订单2包含商品2和商品3。

    那么很明显我们如果以OrderItem这个实体去存储,必然会造成主键重复。在实际存储的时候我们肯定也会为OrderItem增加其他的字段用来存储他自己的主键信息。

    比如我们给他建立一个独立的ID:

     public class OrderItem
        {
            /// <summary>
            /// 订单项ID
            /// </summary>
            public string Id { get; set; }
    
    
            public string ProductId { get; set; }
    
    
            public string ProductName { get; set; }
    
    
            public float Price { get; set; }
    
    
            public int Count { get; set; }
    
        }

    或则采用联合主键:

        public class OrderItem
        {
            /// <summary>
            /// 订单ID
            /// </summary>
            public string OrderId { get; set; }
    
    
            public string ProductId { get; set; }
    
    
            public string ProductName { get; set; }
    
    
            public float Price { get; set; }
    
    
            public int Count { get; set; }
    
        }

    2.例子2:旅馆聚合与房间聚合

    在旅馆信息系统管理里面,对旅馆的操作会有独立的模块,参考聚合的设计原则

    1. 如果领域内的一个对象,我们会在后台有一个独立的模块去管理它,那它基本上也是聚合根了;

    所以我们建立旅馆聚合,代码如下:

        public class Hotel
        {
            /// <summary>
            /// 聚合跟id
            /// </summary>
            public string Id { get; set; }
    
    
            /// <summary>
            /// 值对象
            /// </summary>
            public string Name { get; set; }
    
    
            /// <summary>
            /// 房间列表 此处简单标示        
            /// </summary>
            public IList<string> Rooms { get; set; }
    
            //其他信息略
            //...
        }

    对于旅馆房间的也一样我们会有单独的模块去管理,而且房间有单独的状态标示(房间是否有人入住,是否空房等等)

    房间聚合如下:

      public class Room
        {
    
            /// <summary>
            /// 房间id
            /// </summary>
            public string Id { get; set; }
    
    
            public string Name { get; set; }
    
    
            public string RoomType { get; set; }
    
    
            // 空 已预订,已入住,脏房间等状态
            public RoomStatus Status { get; set; }
    
    
            /// <summary>
            /// 旅馆聚合根ID
            /// </summary>
            public string HotelId { get; set; }
    
        }

    如果是在ORM中上述很可能表达成如下实体:

        public class Hotel
        {
           
            public string Id { get; set; }
           
            public string Name { get; set; }
    
            /// <summary>
            /// 房间列表    
            /// </summary>
            public virtual IList<Room> Rooms { get; set; }
    
            //其他信息略
            //...
        }

    和房间实体

     public class Room
        {
    
            /// <summary>
            /// 房间id
            /// </summary>
            public string Id { get; set; }
    
    
            public string Name { get; set; }
    
    
            public string RoomType { get; set; }
    
    
            // 空 已预订,已入住,脏房间等状态
            public RoomStatus Status { get; set; }
    
    
            /// <summary>
            /// 旅馆
            /// </summary>
            public virtual Hotel Hotel { get; set; }
    
        }

    很明显的可以看出,上述模型不是DDD中的领域对象模型。

    3.结论:ORM中的Model不应该与DDD中的DomainModel等价

    更多的:我们在设计数据库表的时候,为了查询性能考虑,会冗余一些信息等等。

    通过以上的分析,我们可以得出结论:ORM中的Model不应该与DDD中的DomainModel等价。

    我藉著本文来抛砖引玉。

    国外的大牛写的:Just-Stop-It!-The-Domain-Model-Is-Not-The-Persistence-Model.aspx

  • 相关阅读:
    云图小助理
    ping包的checksum校验和
    ftp相关
    初始化字符串
    安全的域名解析
    10进制转62进制
    centos6一键安装WordPress
    CEF3编译
    一次性生产KEY
    linux系统问题排查
  • 原文地址:https://www.cnblogs.com/zhengqzheng/p/5883612.html
Copyright © 2020-2023  润新知