【问题标题】:Organizing interconnected objects组织互连的对象
【发布时间】:2011-12-07 16:59:00
【问题描述】:

这是一个笼统的问题,不知道是属于Programming还是StackOverflow。

我正在编写一个小模拟。无需深入了解其细节,请考虑涉及多种身份。它们对应于 Object,因为我使用的是 OOP 语言。

  • 居住在模拟的世界中
  • 地图
  • 一张地图有许多地块,它们是具有某些特征的土地
  • 部落(人属于部落)
  • 有一个名为 Position 的通用类来定位元素
  • 机器人控制着可以移动人的部落
  • 有一个世界代表模拟的世界

等等。

如果将模拟世界设置为数据库,则对象将是具有大量引用的表,但在内存中我必须使用不同的策略。因此,例如,一个部落有一组 Guys 作为属性,世界有一个 Bots、Tribes 和 Maps 数组。 Map 有一个 Dictionary,其键是 Position,值是 Lot。一个人有一个职位,就是他所处的位置。

我建立这种联系的方式非常随意。例如,我可以在世界上拥有一组 Guys,或者 per Lot 一组 Guy(站在一块土地上的人),或者每个 Bot 一组 Guys(由机器人控制的家伙)。

这样做,我还必须传递很多对象。例如,机器人必须拥有关于地图和对手 Guys 的信息才能决定如何移动其 Guys。

如前所述,在数据库中,我有一个 Guys 表连接到lots 表(指示其位置)和 Tribe 表(指示它属于哪个 Tribe),因此查询“All位置 [1, 5] 的人”。 “部落 123 的所有人”。 “所有被 Bot B 控制的人都站在 Lot b34 上,不属于 456 部落”等等。

我使用 API 来获取最简单的信息,您必须创建 CustomerContextCollection 的实例并将其传递给 CustomerQueryFactory 以取回 CustomerInPlaceQuery 以... , 那就是我的意思。我想避免这样的事情,并且不得不依赖深度抽象和(反模式)抽象上下文。

问题是:管理以多种方式深度链接的实体和实体集合的首选、干净的方式是什么?

【问题讨论】:

  • 您使用什么语言? C++?爪哇? C#?在每种语言中,您都必须有所不同
  • 我没有提到任何语言,因为我宁愿让这种讨论语言不可知。顺便说一句,我正在使用 Ruby,但我在使用 Clojure、C#、Java 以及基本上我编写过一些玩具模拟的每种语言时都有相同的想法。

标签: oop language-agnostic simulation


【解决方案1】:

这取决于您对“干净”的定义。就我而言,我将 clean 定义为:我可以以明显、有效的方式实现所需的行为。

构建 OOP 软件不是数据建模练习。我建议退后一点。这些对象中的每一个实际上做什么?你打算实现什么方法?

仅仅因为“人在很多”并不意味着地段对象需要一组人;如果有很多操作会影响其中的所有人员,则它只需要一个。即便如此,它也不一定需要一群人 - 它需要一种让这些人参与其中的方法。这可能是一个内部存储的集合,但它也可能是一个简单的方法,可以回调到世界中以查找符合条件的人。该查找的实现对任何人都应该是透明的。

从您问题的主旨来看,您似乎是从“我如何生成报告”的角度来考虑这个问题的。退后一步,想想你首先要实现的行为。

我发现另一件非常有价值的事情是区分实体和值。实体是身份很重要的对象——你可能有两个人,都叫“克里斯”,但他们是两个不同的对象,尽管有相同的“钥匙”,但它们仍然不同。另一方面,值的行为类似于整数。从上面的列表中,Position 听起来很像一个值 - Position(0,0) 是 Position(0,0),无论这些位存储在哪个内存块(身份)中。这种区别对你的方式有一点影响比较和存储值与实体。例如,您的 Guy 对象(实体)会将其 Position 存储为一个简单的成员变量。

我发现 Eric Evan 的“领域驱动设计”一书是关于如何思考这些事情的一个很好的参考。他专注于业务系统,但这些讨论对于您如何看待我发现的一般构建 OO 系统非常有价值。

【讨论】:

    【解决方案2】:

    我会说没有您的核心问题存在“真实”答案——这是一种管理以多种方式链接的实体集合的最佳方法。这真的取决于应用程序的类型(模拟) - 这里有一些想法:

    执行时间重要吗?

    如果是这种情况,真的没有办法分析你的模拟器会以哪种方式迭代(查询)池中的对象:勾勒出基本的模拟循环并检查什么类型的事件将需要迭代什么样的模型实体(我假设您正在开发离散事件模拟?)。然后,您应该以优化最频繁/最耗时的事件的方式组织数据结构(而不​​是“任意放下连接”)。此外,您可能希望使用特殊数据结构(例如k-d trees)来组织具有您需要经常查询的属性(例如位置数据)的实体。对于一些典型的问题,例如碰撞检测,还有很多方法可以有效地解决它们(所以寻找合适的库/框架,例如multi-agent simulation)。

    您希望它有多灵活?

    如果你真的想让它超级灵活并且真的不想决定模型实体的层次结构,为什么不直接使用in-memory database?正如您已经说过的,数据库很容易适用于您的问题(并且您可以轻松保存模型状态,这可能也很有用)。

    干净到什么程度才算干净?

    如果您想绝对确定模拟器的其余部分不受您在模型表示方面所做的设计选择的影响,请将其隐藏在界面后面(例如,ModelWorld ),它为您的模拟器可能调用的所有类型的查询定义了方法(这与第二点正交,并且可能有助于第一点,即弄清楚您的模拟器展示什么样的访问模式)。这使您可以轻松更改实现,而不会影响模拟器代码的任何其他部分。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-09
      • 2014-03-17
      • 1970-01-01
      • 2021-01-14
      • 1970-01-01
      相关资源
      最近更新 更多