帮助我连接继承和关系概念

时间:2009-08-26 21:59:15

标签: inheritance rdbms

我正在与我的程序员谈论继承及其在设计模型中的用法。他是一个很大的支持者,我有点不温不火。主要是因为我倾向于自下而上设计系统:数据库 - >申请 - >演示文稿(老实说,我不是一个前端人员,因此我经常将演示文稿完全留给其他人)。我发现关系数据库系统不支持继承而没有与其他表有很多一对一的关系。

如果我从概念角度进行设计,则管理员是用户是个人。从数据库开始,管理员是UserType =“Administrator”的用户。协调这些方法对我来说似乎很难,因此我只使用非持久化对象的继承。

我的想法有什么问题?如果它与传统的关系结构具有这些固有的不兼容性,为什么继承这样一个着名的OO方面呢?或者,是不是我没有正确地将继承映射到关系数据?那里有一些指导可能会为我解决这个问题吗?

抱歉这个漫无边际的问题,并提前感谢您的回答。如果您在回复中包含代码,则C#是我的“母语”。

11 个答案:

答案 0 :(得分:5)

这通常被称为 Object-Relational Impedance Mismatch

  

架构继承 - 大多数关系数据库不支持架构继承。尽管可以在理论上添加这样的特征以减少与OOP的冲突,但是关系支持者不太可能相信分层分类法和子分类的效用,因为它们倾向于将基于集合的分类法或分类系统视为更强大和灵活的比树。 OO倡导者指出,继承/子类型模型不必局限于树(尽管这是许多流行的OO语言(例如Java)的限制),但非树OO解决方案被认为比基于集合的变体更难以制定 - 关系型首选的主题管理技术。至少,它们与关系代数中常用的技术不同。

另请参阅:Agile DataC2 Wiki

答案 1 :(得分:3)

您应该阅读Patterns of Enterprise Application Architecture。它将向您展示继承模式如何能够并且应该表达为关系结构。

要记住的重要一点是继承是概念建模的事情。关系结构和面向对象代码只是这些概念模型的物化方法,不应被视为对象的全部和最终结果。

这种类型的东西有tutorial

答案 2 :(得分:3)

经常讨论关系范式和OO范式之间的鸿沟。

基本上,要提供RDBMS和OO之间的映射,必须牺牲两个系统的一些功能。你必须决定你的妥协哪一方更重要。

两种范式都非常强大和有用。但试图无缝地在它们之间进行映射是一个尚未解决的问题。

答案 3 :(得分:3)

我认为问题中的继承模型存在缺陷。它太字面化,或者基于现实世界。是的,可以说我是现实世界中的管理员,因此管理员人。但是,对象设计和继承应该更多地基于代码空间中的表达和共享行为。我会更多地了解用户具有角色的路线。管理员是角色,或者是设置为特定状态的角色的实例。用户不是人(例如,您的批处理作业可能需要用户帐户)。

我建议阅读David West的Object Thinking,以获得对象设计的优秀介绍。然而,他没有涉及对象关系不匹配,但人们已经提供了许多关于该主题资源的链接。

答案 4 :(得分:1)

有很多方法可以在C#中表达这种关系。关系数据库只是更有限(这可能是一个好处,也是一个缺点)。当你设计一个将在数据库中持久保存的对象层次结构时,我发现首先从数据库模式开始通常更容易,因为几乎任何数据库模式都可以很容易地映射到对象关系,而相反的情况则不一定案件。

在这种特殊情况下,您可以使用合成为管理员建模。您的Administrators表将提供任何其他管理员状态以及相应用户的密钥。用户FK也将是您的管理员PK。

答案 5 :(得分:1)

有各种各样的继承。开发人员可能会考虑接口和行为。

在您的世界中,拥有管理员的“userType”是什么意思?

你所暗示的语义是某些代码在某处看到userType并为具有该类型的用户授权操作。那么管理员是否可以创建其他用户?

在这种情况下,开发人员可能拥有类User

class User() { viewData(){ ...} ; signReport() {...} }

以及具有额外功能的类Adminstrator

class Administrator()  extends User {  createUser() {...}; approvePurchase() {...} }

管理员类型的对象可以在用户可以使用的任何地方使用。这种多态行为在实施时很有用。现在你的数据库非常合理地支持这种情况。但是,当管理员需要一些额外的数据来执行他们的特定任务时,您会做什么?例如,purchaseApproval()达到一定限度,我们需要将该限制作为新字段,但它仅适用于管理员。

我认为你的“类型”概念所暗示的行为方面往往与额外的数据有关。

答案 6 :(得分:1)

  

为什么继承就是这样的   OO的着名方面,如果有的话   这些固有的不兼容性   传统的关系结构?

这是一个奇怪的引用 - 为什么你说关系结构是“传统的”?它们本质上是RDBMS中的标准,但我在非DB语言的上下文中看到很少的关系库。

OO受欢迎的原因是因为它比主导程序模型有了显着的改进。通过使用继承,可以使代码更可靠(通过类型检查),更容易修改(通过方法特化)和更可测试(通过简单的覆盖行为)。与程序模型相比,OO更容易 更容易开发高质量的软件。

当然,在OO和关系模型之间进行映射存在困难。这称为“对象 - 关系不匹配”,并命名为"the Vietnam of computer science"。将OO数据存储在关系数据库中有各种策略,但没有一种是完美的 - 现代最流行的是基于active record pattern的框架。

答案 7 :(得分:0)

是的,当您与数据库进行映射时,继承可能不是正确的工具。

继承在构建框架时更有用,在框架中,您有不同类型的对象,这些对象的行为不同,但它们仍然有共同的部分。

例如,您可以在一台服务器和另一台服务器之间传递不同的“消息”。每个消息都有自己的逻辑,所以你需要不同的类(以避免一个巨大的switch()语句),但是有一些共同的部分,比如每个消息都需要知道如何将自身序列化/反序列化为流(这是一个方法的所有子类都必须覆盖)。 此外,让所有消息继承Message将允许您拥有List,并逐个进行并调用其Serialize方法,例如。

但如果您所做的只是典型的业务/数据库逻辑,继承很可能会阻碍您。

答案 8 :(得分:0)

规范化的关系数据库模式实际上不支持多态,除非你超出了DBA世界中通常被认为是“最佳实践”的范围。这不是一个新问题,问题本身已经以几种不同的方式解决了一千次。

当您开始使用数据时,真正的问题就出现了 - 如果您正在使用数据集,那么您将继续面临尝试实施任何类型的多态性的挑战。但是,如果要将一组域实体映射到关系模型,您会发现有许多工具可以帮助您克服关系数据库模式的限制。

由于您是C#开发人员,因此您应该从查看以下2个项目开始,其中一个项目附带最新的.NET服务包。

ADO.NET实体框架:

http://msdn.microsoft.com/en-us/library/bb386876.aspx

NHibernate的:

http://nhforge.org/Default.aspx

答案 9 :(得分:0)

作为UserType为“Administrator”的用户的Admininstrator的具体示例是"Single Table Inheritance"模式的主要示例。这是在一些主要的ORM中实现的。特别是“Rails ActiveRecord”和Hibernate。

答案 10 :(得分:0)

Hibernate简化了继承。 Example