关于继承与组合有很多问题,还有很多关于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
并从此新类继承Address
和CompanyAddress
。
虽然问题看起来很简单,但我很困惑哪种解决方案更适合。
答案 0 :(得分:1)
ORM的问题在于人们忘记了业务领域是应用程序最重要的方面。它应该在 业务 之后建模,而不是在如何在数据层中保留信息之后建模。
当您与您的团队或将使用您的应用程序的人员交谈时,他们如何对其进行建模?他们如何使用上述信息?这是优先事项。
数据层的整个目的是抽象出持久化数据所涉及的复杂性。这也意味着实体框架实体只存在于数据层中,您必须在业务实体之间进行映射&lt;&gt;数据层中的EF实体。
关于继承,您在技术上是正确的。这是一个地址。但实际上,在使用信息时,您通过该模型获得了什么优势?公司地址是否会在与常规地址相同的控件中呈现?有时,应用程序通过不使用继承来获得更好的结构。
我所说的是,你不应该盯着最佳实践,而应该更多地关注什么能够提供易于维护的模型(从而提供更好的代码质量)。
LSP是遵循基类契约的原则,通常只是耦合到方法的行为。例如,如果基类在某种情况下抛出异常,则子类必须与预期的内容相同。 LSP并不适用于您的情况。