【问题标题】:Liskov Substitution Principle and Redundant MethodsLiskov 替换原理和冗余方法
【发布时间】:2013-07-31 09:01:23
【问题描述】:

我有一个名为 IRepository 的接口。该接口定义了一组通用方法,例如:

 IQueryable<T> Get<T>() where T : class;
 void Add<T>(T obj) where T : class;
 void Update<T>(T obj) where T : class;
 void SaveChanges();

然后我有一个实现这个接口的类。这个类实际上使用实体框架来实现这些方法。然而,方法更新是多余的,因为实体框架会跟踪对检索到的实体所做的更改,所以我只需获取我想要的实体,更新它然后调用 SaveChanges。但是,将来我可能想用其他东西替换 IRepository 的这个具体实现。这可能不会像实体框架那样跟踪变化。所以我想我想把更新方法留在接口中,但是在我这个接口的具体实现中,只是把方法留在里面,但什么也不做。例如

public void Update<T>(T obj) where T : class
{
}

这似乎符合 Liskov 替换原则,我可以将接口的实现替换为其他东西。只是有些东西可能不需要真正实现接口上定义的所有方法。

这是一个好方法吗?我在想这没关系,甚至可能在 IRepository 的实现中将该方法标记为已过时,说明为什么它在此实现中已过时。

拥有一个什么都不做的更新方法并在整个应用程序中调用它似乎有点奇怪,即使它实际上并没有做任何事情。但是,如果我们将 IRepository 的实现更改为确实需要更新方法的实现,那么我们可以将其替换为不需要更改代码。

【问题讨论】:

  • 这与问题有点正交,但是通过抽象出抽象(EF 已经是),您几乎会自动失去很多随之而来的功能(缓存,第一和第二如果您介绍一个级别,更改跟踪等)...
  • 读起来很有趣,它准确地描述了我想出的界面。我想像这样的接口确实会做出错误的保证。如果我替换实现,并非所有查询都能正常工作。
  • Patryk 我同意我正在抽象出一个抽象,但我想将所有对 EF 的依赖项保留在一个地方,这样它就更加解耦了。这样,如果我从 EF 进行更改,我只需要更改一个类,而不是需要数据库访问的任何地方。我仍然受益于变更跟踪等,因为实际实施是 EF?如果我不对此进行抽象,我会将 EF 特定的代码分散在应用程序中吗?

标签: c# design-patterns solid-principles liskov-substitution-principle


【解决方案1】:

恕我直言,在大多数情况下未实现的接口上有一个方法告诉我该接口的范围太宽了。

您可以从基础存储库接口中删除更新方法,并将其单独添加到从基础接口继承的 IUpdatableRepository。然后,您需要更新的具体类可以实现 IUpdatableRepository 接口。

这可能不是您想要的,但您明白了...

【讨论】:

  • 关于界面范围的好点。我喜欢你的建议。
  • 鉴于许多框架类型系统的限制,界面细分的最佳水平往往与没有这些限制的情况不同。如果不同的对象执行 X、Y 和 Z 的不同组合,即使很少有人全部完成,使用“厨房水槽”界面,以及报告详细实例支持哪些功能的属性, 可能比必须为可能实现的每个组合功能定义不同的接口类型、在所有地方使用运行时类型检查和向下转换,或两者兼而有之更干净。
【解决方案2】:

如果我对您的理解正确,那么您有一个已包装在接口中的实现。 LSP 并不是设计中唯一需要担心的事情:我认为KISSYAGNI 更为基础,而 LSP 只是在面向对象设计中保持简单和可预测的一种方式。尝试为您的系统中任何可以想象的未来变化进行设计实际上会使您的系统由于复杂性增加而更难改变。您是否有可能用需要 Update 方法的替代实现替换您的存储库?然后无论如何,保留它。如果这只是一种可能,请立即将其删除(并且可能考虑直接使用 EF)。

毕竟,“你可以通过添加另一层抽象来解决所有问题,除了太多的抽象层。”

【讨论】:

  • 我完全同意 KISS 和 YAGNI 的基本观点。但是我确实担心直接调用 EF。系统的 EF 组件很容易通过抽象来解耦。然后,如果该区域有任何更改,代码更改将仅限于一个区域,而不是整个应用程序。我不认为这会为这样的收益增加太多复杂性?还有单元测试我需要抽象这个数据访问组件,以便我可以单独测试我的代码吗?
猜你喜欢
  • 2013-10-15
  • 2013-12-15
  • 2017-10-18
  • 1970-01-01
  • 2013-08-23
  • 2019-06-26
  • 1970-01-01
  • 2014-06-05
  • 2010-12-03
相关资源
最近更新 更多