ORM:继承vs.组合和LSP

本文关键字:LSP 组合 vs 继承 ORM | 更新日期: 2023-09-27 18:10:08

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

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分配给Person。我认为这并不违反LSP(是吗?),但是感觉不对。

CompanyAddress使用合成当然是另一种选择。作为另一种解决方案,我可以添加一个新的AbstractAddress,并从这个新类继承AddressCompanyAddress。虽然这个问题看起来很简单,但我不知道该选哪个解决方案。

ORM:继承vs.组合和LSP

orm的问题是人们忘记了业务域是应用程序最重要的方面。它应该按照业务建模,而不是按照如何在数据层中持久化信息。

当你和你的团队或将要使用你的应用程序的人交谈时,他们是如何建模的?他们如何使用提到的信息?

数据层的全部目的是抽象掉持久化数据所涉及的复杂性。这也可能意味着实体框架实体只存在于数据层中,而您必须在数据层中的业务实体<> EF实体之间进行映射。

关于继承,你在技术上是正确的。这是个地址。但说真的,当你使用这些信息时,这个模型有什么好处呢?公司地址是否会在与普通地址相同的控件中呈现?有时,应用程序通过不使用继承来获得更好的结构。

我想说的是,你不应该太关注最佳实践,而应该更多地关注是什么提供了一个易于维护的模型(从而提供了更好的代码质量)。

LSP是一个遵循基类契约的原则,通常只是与方法的行为相耦合。例如,如果基类在某种情况下抛出异常,则子类必须做同样的事情,这是预期的。你的情况不适用LSP