ORM:继承与组合和LSP

时间:2015-08-28 09:53:49

标签: c# oop inheritance orm

关于继承与组合有很多问题,还有很多关于stackoverflow的好答案。但今天我在使用ORM时遇到了一个问题。实际上我正在使用DevExpress XPO,但是下面的简化示例代码使用了Entity Framework语法,因为它不那么冗长:

public class Person
{
  public int Id { get; set; }
  public virtual Address Address { get; set; }
}

public class Address
{
  public int Id { get; set; }
  public string Line1 { get; set; }
}

Address实体用于各种其他实体,例如在Person实体中。这当然工作得很好。

但我也有一个Company实体,而且这个实体不需要简单的Address字段,而是需要具有其他属性的CompanyAddress个实体的集合:

public class CompanyAddress : Address
{
  public virtual Company Company { get; set; }
  public string Line2 { get; set; }
}

public class Company
{
  public Company()
  {
    Addresses = new List<CompanyAddress>();
  }

  public int Id { get; set; }
  public virtual List<CompanyAddress> Addresses { get; set; }
}

在关于stackoverflow的各种讨论之后,我认为CompanyAddress Address,其行为类似于Address。因此,使用继承是一种正确的方法。 但是使用这种方法,也可以为一个人分配CompanyAddress。我认为这并没有违反 LSP (是吗?),但感觉不对。

使用CompanyAddress的组合当然是另一种选择。作为另一种解决方案,我可以添加新的AbstractAddress并从此新类继承AddressCompanyAddress。 虽然问题看起来很简单,但我很困惑哪种解决方案更适合。

1 个答案:

答案 0 :(得分:1)

ORM的问题在于人们忘记了业务领域是应用程序最重要的方面。它应该在 业务 之后建模,而不是在如何在数据层中保留信息之后建模。

当您与您的团队或将使用您的应用程序的人员交谈时,他们如何对其进行建模?他们如何使用上述信息?这是优先事项。

数据层的整个目的是抽象出持久化数据所涉及的复杂性。这也意味着实体框架实体只存在于数据层中,您必须在业务实体之间进行映射&lt;&gt;数据层中的EF实体。

关于继承,您在技术上是正确的。这是一个地址。但实际上,在使用信息时,您通过该模型获得了什么优势?公司地址是否会在与常规地址相同的控件中呈现?有时,应用程序通过不使用继承来获得更好的结构。

我所说的是,你不应该盯着最佳实践,而应该更多地关注什么能够提供易于维护的模型(从而提供更好的代码质量)。

LSP是遵循基类契约的原则,通常只是耦合到方法的行为。例如,如果基类在某种情况下抛出异常,则子类必须与预期的内容相同。 LSP并不适用于您的情况。