实体之间的抽象参考

时间:2009-01-08 18:40:07

标签: database-design architecture business-objects

我即将开展的一个项目正在考虑涉及(我所称的)“抽象实体参考”的设计。它与更常见的数据模型设计完全不同,但可能需要实现我们想要的灵活性。我想知道其他建筑师是否有类似这样的系统以及注意事项的经验。

项目要求各个人控制对各种实体(逻辑上:业务对象;物理上:数据库行)的访问。例如,我们可能想要创建如下规则:

  • 用户Alice是Z公司的成员
  • 用户Bob是Y组的经理,该组有用户Charlie,Dave和Eve。
  • 用户Frank可以输入[关键业务对象] X的数据,也可以输入[关键业务对象组] U中的[关键业务对象]。
  • 用户George不是T公司的成员,但可以查看公司T的报告。

我们的想法是,我们有许多不同的安全对象,角色,组和权限,我们希望系统能够处理这个问题。理想情况下,一旦启动,这个系统对新情况几乎不需要编码;它应该非常灵活。

在“传统”数据设计中,我们可能有像这样的实体/表:

  • 用户
  • 公司
  • 用户/公司交叉参考
  • 用户组
  • 用户/用户组交叉引用
  • CBO(“关键业务对象”)
  • 用户/ CBO交叉参考
  • CBOGroup
  • 用户/ CBOGroup交叉参考
  • CBO / CBOGroup交叉参考
  • ReportAccess,这是用户和公司之间的交叉引用,专门用于访问报告

请注意大量的交叉引用表。这个系统不是非常灵活,因为我们想要添加一种新的访问方式,我们需要引入一个新的交叉引用表;反过来,这意味着额外的编码。

建议的系统让所有主要实体(User,Company,CBO)在名为Entity的新表中引用一个值。 (在代码中我们可能会使所有这些实体成为Entity超类的子类)。然后还有两个引用实体的附加表  * Group,也是一个实体“子类”。  * EntityRelation,它是任何类型(包括Group)的两个实体之间的关系。这可能还会有某种“关系类型”字段来解释/限定关系。

这个系统,至少乍一看,看起来像是符合我们的许多要求。我们可能会引入新的实体,但是我们永远不需要执行额外的表来处理这些实体之间的分组和关系,因为Group和EntityRelation已经可以处理它了。

然而,我担心这在实践中是否会起作用。实体之间的关系将变得非常复杂,并且人们(用户和开发人员等)可能很难理解它们。而且,他们是非常递归的;这会使我们依赖于SQL的报告编写工作人员变得更加困难。

有没有人有类似系统的经验?

4 个答案:

答案 0 :(得分:3)

我对此有一种奇怪的经历;如下:

建筑师/程序员设计外部对称的通用模型,看起来非常整洁,非常树状和递归。

在用户界面设计方面,客户用户坚持认为真正的使用要简单得多,并且对这两个简单的屏幕感到满意(用户/客户绘制这些在你听的时候在黑板上给你。

在这个阶段,我一直发现解决方案在底层模型支持非人们真正想要或不需要的非常一般的用例时会变得非常臃肿。因此,我的基本建议是始终非常认真地倾听客户的意见,并且非常接近真正的要求。确保你对整洁结构的个人欲望不是这里的驱动力。

是的,我经历了很多次:在我最近的经历中,所有开发人员都非常确定我们正在讨论分层树结构。但客户肯定希望这在所有方面都是扁平列表式结构。在我们屈服之前,我们必须完全循环(首先实现树,然后列出)。

我不完全确定你建议的通用模型,但它有所有气味让我不再谈论过于通用的模型。在选择之前,我至少总是非常确定在两个备选项中详细建模。

答案 1 :(得分:3)

您在现实世界中对一组本身很复杂的业务规则进行建模。因此,无论您如何操作,您的模型都会变得复杂并不奇怪。

我建议您选择更准确地描述关系的数据库设计,而不是试图变得聪明。你聪明的设计可能会导致更少的表(虽然实际上不是一个数量级),但是你需要权衡更多的应用程序代码来管理它。

例如,您已经知道它会给用户和报表设计者造成混淆。另一个缺点是确保“关系类型”列仅包含关系中涉及的实体的有意义的字符串。例如。说Bob IsMemberOf UserGroup4是有意义的,但是CBO CanViewReportsOf Bob是什么意思?另外,您如何防止互斥条件,例如Bob IsMemberOf Company1Bob IsMemberOf Company2

您必须编写应用程序代码以在插入数据之前验证数据,并在获取数据之后(因为您的代码永远无法确定代码的其他部分未引入数据完整性错误)。您可能还需要编写应用程序代码以对整个数据库执行质量控制检查,并在发生异常时清除它们。

与数据库设计进行比较,其中不可能输入无效关系,因为数据库元数据包含阻止它的约束。这将大大简化您的应用程序代码。

您还可以识别分层访问权限,例如Bob CanViewReportsOf Company1,那么他是否应该能够查看属于该公司成员的任何UserGroup或CBO的报告?或者,您是否需要为Bob可以阅读的每个实体报告单独输入一行?这些是政策问题,无论您使用哪种设计,都会存在这些问题。


回复你的意见:

我当然可以理解拜占庭异常案例和不断变化的要求,这使得设计简单的解决方案变得困难。

我研究的系统试图模拟真实世界的政策,这些政策变得如此复杂,以至于试图在软件中编写它们似乎是愚蠢的。最终,雇用我的客户会更有效地利用他们的钱聘请一两名全职行政助理,用纸和铅笔跟踪他们的项目。我花了数周时间在软件中实施的新例外情况需要几分钟才能向AA描述。

自动化比手动操作更难。自动化是唯一合理的方式是,如果需要比人类更快或更高的数量跟踪信息,那么这就是人们可以做到的。

答案 2 :(得分:2)

你的实体/关系提议是如此“元”,它足够灵活,可以处理所有疯狂的排列 - 哎呀你离一个单一的表只有一个列,其中包含实现类的路径的单个列这是逻辑,在那里做了 - 但正如你指出直接管理它会导致疯狂的混乱。你需要从业务对象层(re:单表继承?)上放一个漂亮的漂亮包装来隐藏所有的抽象。但在您解决所有这些问题之前,请查看其他已经建立的系统。大多数时候,我发现自己陷入了这个兔子洞,我最终实施了Unix file system permissions,这不足为奇地经受住了时间的考验。

答案 3 :(得分:2)

在之前的工作中,我们走了类似的路径,最终有效地为数据实体实现了活动目录类型权限。

每个需要权限的表都有一个SecurityObject表的foriegn键。 UserPermission和GroupPermission表中的行指示了各个用户对该SecurityObject行的权限类型。 SecurityObject表中的数据是分层的 - 默认情况下,每行都从其父级继承权限(如果有的话)。

相应的数据实体类实现了一个通用接口,这样安全api就可以处理任何“安全”数据而无需确切知道它是什么。

用于控制组和用户权限的UI组件提供了一个用于管理实体权限的通用接口。

这用于为内部数据库驱动的CMS设置权限,用于构建合作伙伴公司内部和外部使用的许多站点,以及其他类型的数据,例如访问客户端记录。

构建它时遇到的主要问题之一是最大限度地减少数据库命中数。这是有问题的,因为SecurityObject和Group表中的分层数据使得高效的查询变得困难 - 当您对许多数据实体进行权限检查时,这是一个很大的问题。

如果您的应用程序分布在多台计算机上,这会导致数据缓存非常繁重。

由于所有这一切,我倾向于同意其他一些海报,你需要非常确保这是业务需要的,或者你可能会发现你在浪费你的时间痛苦地。

如果我再次这样做,我肯定会使用存储过程来检查和管理安全对象和权限 - 坚持使用ORM实体很可能使我的工作变得更加困难:]