2

我即将进行的一个项目正在考虑涉及(我称之为)“抽象实体引用”的设计。这与更常见的数据模型设计大相径庭,但可能需要实现我们想要的灵活性。我想知道其他架构师是否有类似这样的系统的经验以及需要注意的地方。

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

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

这个想法是我们有很多不同的安全对象、角色、组和权限,我们想要一个系统来处理这些。理想情况下,该系统一旦启动,几乎不需要对新情况进行编码;它应该非常灵活。

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

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

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

提议的系统让所有主要实体(用户、公司、CBO)在一个名为 Entity 的新表中引用一个值。(在代码中,我们可能会将所有这些实体作为 Entity 超类的子类)。然后有两个额外的表引用了Entity * Group,它也是一个Entity“子类”。* EntityRelation,它是任意类型(包括 Group)的两个实体之间的关系。这可能还会有某种“关系类型”字段来解释/限定关系。

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

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

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

4

4 回答 4

3

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

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

当涉及到用户界面设计时,客户用户坚持认为实际使用要简单得多,并且会对这两个简单的屏幕感到满意(用户/客户在您聆听时将它们绘制在黑板上)。

在这个阶段,我一直发现当底层模型支持没有人真正想要或需要的非常通用的用例时,解决方案往往会变得非常臃肿。所以我的基本建议是始终非常密切地倾听客户的意见,并非常接近真正的需求。确保您对整洁结构的个人需求不是这里的驱动力。

是的,我经历过很多次:在我最近的经历中,所有的开发人员都非常肯定我们在谈论的是层次树结构。但客户绝对希望这是在所有方面都是扁平的列表式结构。在我们陷入困境之前,我们必须绕一圈(先实现树,然后是列表)。

我不完全确定您建议的通用模型,但它具有让我开始谈论过度通用模型的所有气味。在选择之前,我至少非常肯定地对这两种选择进行详细建模。

于 2009-01-08T19:07:11.700 回答
3

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

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

例如,您已经知道它会给用户和报表设计者带来困惑。另一个弱点是确保“关系类型”列只包含对关系中涉及的实体有意义的字符串。例如说有道理Bob IsMemberOf UserGroup4,但如果是什么意思CBO CanViewReportsOf Bob?另外,您如何防止相互排斥的条件,例如Bob IsMemberOf Company1and Bob IsMemberOf Company2

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

与无法输入无效关系的数据库设计相比,因为数据库元数据包含阻止它的约束。这将大大简化您的应用程序代码。

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


要回复您的评论:

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

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

自动化比手动操作更难。自动化合理的唯一方法是,如果需要比人类更快或更大数量地跟踪信息。

于 2009-01-08T19:13:22.687 回答
2

您的实体/关系提案是如此“元”,以至于它足够灵活以处理所有疯狂的排列 - 哎呀,您离一个表只有一步之遥,该表只有一个列,其中包含实现其逻辑的类的路径,在那里做过 - 但正如你指出的那样直接管理它会导致疯狂的混乱。您需要从业务对象层(re:单表继承?)在其上放​​置一个漂亮漂亮的包装器以隐藏所有抽象。但在您遇到所有这些麻烦之前,请查看其他已经建立的系统。大多数时候,我发现自己掉进了这个兔子洞,最终实现了Unix 文件系统权限,不出所料,它经受住了时间的考验。

于 2009-01-08T23:15:12.463 回答
2

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

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

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

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

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

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

如果您的应用程序分布在多台机器上,这会导致大量的数据缓存和它自己的一系列问题。

由于这一切,我倾向于同意其他一些海报,您需要非常确定这是业务需要的,否则您可能会发现您正在以一种痛苦的方式浪费您的时间。

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

于 2009-01-08T23:50:33.030 回答