【问题标题】:DDD Modeling questions : student, classroom, seats and a favorite seat for a studentDDD 建模问题:学生、教室、座位和学生最喜欢的座位
【发布时间】:2011-02-01 06:21:21
【问题描述】:

我不确定如何模拟这种关系...

一个教室有很多座位,每个学生都在一个教室里学习,里面有一个最喜欢的座位。

在我看来,我有两个聚合根:教室和学生,座位 a 是由教室聚合的实体...

对于一个学生有一个最喜欢的座位,它必须持有对它的引用(座位不是聚合根)。

有什么建议吗? 提前致谢,埃里克。

【问题讨论】:

    标签: domain-driven-design modeling


    【解决方案1】:

    嗯,这取决于...我可能会有像你这样的座位的教室集合。学生可以是实体,但座位对我来说更像是价值对象。但是,这一切都取决于您的上下文。我不确定什么对你很重要,如果我的建议没有意义,请解释你的上下文。

    【讨论】:

    • 您好,感谢您的回复,座位可能不是价值对象...我可以在两个单独的课堂中拥有完全相同数据的座位...要求是:A.用户可以选择他想学习的教室。 B. 选择教室后,用户可以在教室中选择自己喜欢的座位。我没有找到一种方法来对没有学生参考座位的用例进行建模(这不是聚合根,而是教室中的实体)。提前致谢,埃里克。
    • 如果席位中的数据是相同的,并且当你访问席位时,你使用特定的教室聚合根,你可能知道席位的一切并且你节省了很多数据(享元设计模式) .这也可以简化最喜欢的座位关联,其中将包含课堂参考和座位值。
    • 对不起,我没听懂……你是说座位​​是价值对象吗?学生会直接参考座位等级吗?教室和座位之间是一对多的关系。这怎么可能?
    • 老实说,我做了一些思考,但我不太确定在 DDD 中解决问题的正确方法是什么,所以我会做一些阅读,如果我得到一些真实的东西,我会回答。
    【解决方案2】:

    一个可能的选项是每个座位都有一个该座位最喜欢的学生列表。教室聚合根将负责维持学生在教室中不能拥有多个最喜欢的座位的约束。使用此选项,座位是由教室聚合的实体(不是值对象),并引用学生。

    【讨论】:

    • 感谢您的建议,我已经考虑过这种方法,但是它有缺陷... 1.席位了解学生...可能使用类似的方法:seat.MakeFavoriteByStudent(Student student )。 2. 删除学生时可能存在完整性和一致性问题。总的来说,这非常好,因为当删除一扇门时,它会删除引用它的学生最喜欢的座位分配......
    • 席位是价值对象还是实体?是什么让班级中的座位与同一班级的另一个座位不同?座位只有行、列属性吗?如果它们是值对象,则可能意味着 N 个教室引用了同一个座位(例如:row=1,col=1)。在这种情况下,我将创建座位聚合根并添加来自学生的参考。如果用户可以为每个教室选择不同的座位,我可以添加一个由学生聚合的 FavSeatClassroom 实体,并引用教室和座位。
    • 我想这取决于...我看到它的方式,座位是一个实体(它具有本地身份),两个教室可能都有一个座位在 row=1 和 col=1,但是它不是同一个座位......我可以删除那个教室,座位也会被删除......这就是为什么座位可能不是聚合根......我已经考虑了更多,我猜想那个座位应该被学生引用......违反引用法......这将增加完整性验证(如果学生引用座位,则不能删除教室,反之亦然)......
    【解决方案3】:

    听起来您需要引入一个值对象Location,它描述了教室中的一个地点,然后您可以在学生班中像这样对它们进行建模:

    public IDictionary<Classroom, Location> FavoriteSeats;
    

    教室可以通过位置引用Seat 实体。

    (如果它们真的实体首先 - 您甚至可能会发现您不需要将座椅建模为实体(例如,“闻起来像汉堡包的蓝色塑料椅子)。 )

    【讨论】:

      【解决方案4】:

      手术后几个月,但以防万一。

      @Jeff Sternal 走在正确的轨道上。问题从根本上是关于管理学生、教室和座位之间的三向(三元)关系。既然这是一个关系问题,让我们暂时保留关系概念并将其称为 FavouriteSeat(Student, Classroom, Seat)。

      如上所述,除了唯一标识符之外,该问题不需要任何关于它们的任何知识。现在让我们使用伪类型“ID”(并不重要,只要每个都是唯一的)。

      在伪sql中,我们有:

      create table FavouriteSeat(
         StudentID ID not null,
         ClassroomID ID not null,
         SeatID ID not null)
      

      该表上的标准 CRUD(创建/读取/更新/删除)操作提供了所需的所有操作。但是,它缺少一些约束。现在,一个学生在教室里可能有 2 个或更多最喜欢的座位。尽管没有明确说明,但 OP 暗示学生在任何给定的教室中最多应该有一个(0 或 1)个最喜欢的座位。

      我们可以通过在表上添加一个唯一键来解决这个问题。再次使用伪sql:

      alter table FavouriteSeat add unique key (StudentID, ClassroomID) 
      

      现在,对于任何给定的教室,学生只能拥有一个最喜欢的座位。还有一个问题。该解决方案目前不支持定义哪些教室有哪些座位。我们可以通过以下方式解决:

      1. 添加一个列出每个教室中有效座位的新表格:

        创建表 ClassroomSeat ( ClassroomID ID 不为空, SeatID ID 不为空)

        alter table ClassroomSeat 添加唯一键(ClassroomID、SeatID)

      2. 向 FavouriteSeat 表添加外键,使其只能引用有效的 ClassroomSeats:

        alter table FavouriteSeat add Foreign Key FK_Seat(ClassroomID, SeatID references FavouriteSeat(ClassroomID, SeatID)。

      就是这样。 2 个关系、3 个键和标准 CRUD 操作涵盖了所述的所有要求。

      关系模型可以很容易地转换为 OO/DDD。它需要一个用于 FavouriteSeat 和 ClassroomSeat 的实体以及用于 CRUD 操作的方法。这些方法必须强制执行上面的唯一和外键约束。

      为了满足所述要求,Customer、Classroom 和 Seat 可以是值类型(尽管可能有更广泛的未说明的要求可能会改变这种情况)。无论哪种方式,他们都需要一个可以在 FavouriteSeat 方法中检查的唯一标识符属性。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多