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
,并从这个新类继承Address
和CompanyAddress
。虽然这个问题看起来很简单,但我不知道该选哪个解决方案。
orm的问题是人们忘记了业务域是应用程序最重要的方面。它应该按照业务建模,而不是按照如何在数据层中持久化信息。
当你和你的团队或将要使用你的应用程序的人交谈时,他们是如何建模的?他们如何使用提到的信息?
数据层的全部目的是抽象掉持久化数据所涉及的复杂性。这也可能意味着实体框架实体只存在于数据层中,而您必须在数据层中的业务实体<> EF实体之间进行映射。
关于继承,你在技术上是正确的。这是个地址。但说真的,当你使用这些信息时,这个模型有什么好处呢?公司地址是否会在与普通地址相同的控件中呈现?有时,应用程序通过不使用继承来获得更好的结构。
我想说的是,你不应该太关注最佳实践,而应该更多地关注是什么提供了一个易于维护的模型(从而提供了更好的代码质量)。
LSP是一个遵循基类契约的原则,通常只是与方法的行为相耦合。例如,如果基类在某种情况下抛出异常,则子类必须做同样的事情,这是预期的。你的情况不适用LSP