【问题标题】:Interface segregation principle for a framework interface with optional features具有可选功能的框架接口的接口隔离原则
【发布时间】:2021-01-12 01:11:36
【问题描述】:

我正在设计一个身份验证框架。我需要框架的用户来实现数据访问逻辑,因为它不是框架的主要目的,我希望允许多种数据访问方法(SQL、NoSQL、缓存等)。我不在我的框架内实现它。我的框架通过一个名为 IUserStore 的接口使用此逻辑,但问题是,我的接口中有某些方法仅在某些功能处于活动状态时才使用,否则不会使用。例如,只有在启用双因素身份验证时,框架才会尝试通过 GetTwoFactorInfo 方法访问两个因素信息。

我的问题是关于接口隔离原则。是否可以保留界面原样并在文档中解释用户需要实现 GetTwoFactorInfo 只有当用户想要使用双因素身份验证并抛出 NotImplementedException 否则?或者我应该为每个可选功能分离接口并在文档中解释用户应该实现该接口并将其注册给服务提供商以便能够使用该功能?第二种方法的一个问题是,当将实现这些接口的服务注入到构造函数时,我需要检查这些功能是否处于活动状态,否则我会收到错误,因为服务未注册并且我正在尝试从服务提供商访问这些服务。这导致我的框架类更加复杂。

解决这个问题的最佳方法是什么?

【问题讨论】:

  • 这是一个很好的问题,但您使用了不适当的语言标签将其关闭
  • 你认为我应该怎么做?我认为这是一个很好的设计问题,每个设计问题都是基于意见的,所以我无法改变这一事实。
  • 您有 2 张重新投票,因此可以保存
  • 感谢大家的努力,我现在希望 stackoverflow 社区可以对新人非常温和:D

标签: oop design-patterns interface frameworks


【解决方案1】:

您建议的两种方法都存在实际问题,但让客户抛出NotImplementedException 的计划要糟糕得多。

让我们来看看它们:

选项 1

保持界面不变,并在文档中说明用户需要实现 GetTwoFactorInfo 仅当用户想要使用双因素身份验证时,否则抛出 NotImplementedException

嗯,这可能适用于您今天遇到的问题,但软件设计是关于您明天将遇到的问题。如果您在框架的未来版本中添加对不同身份验证方法的支持,会发生什么情况?如果您遵循此模式,那么您将向 IUserStore... 添加新方法...但这会破坏现有客户端,因为他们不会实现它们!

在某些语言中,您可以通过为抛出异常的新方法提供默认实现来解决这个特定问题,但这违背了首先定义接口的大部分目的——类型系统不再告诉客户端什么是他必须执行。

此外,此模式仅适用于 预先存在的 接口。如果您添加一个新的身份验证方法,要求客户端实现 new 接口,那么您将重新考虑类似于您的第二个选项,那么如果版本控制策略,您将有不一致的组合。艾克。

选项 2

每个可选功能的单独接口并在文档中解释用户应实现此接口并将其注册给服务提供商以便能够使用该功能

这要好得多,但也不是很好,因为它引入了框架的客户端必须遵循的隐藏规则。找出这些规则的所有方法都令人沮丧——阅读文档、解决错误等等。

这在很多依赖注入系统中是一个常见问题,而且很多人似乎并不介意,但随着隐藏规则交互系统的积累,事情变得非常复杂。

选项 3

我不知道您现在如何启用此 2 因素功能,但我建议您让您的客户通过调用将隐含依赖项作为参数的方法来启用此功能,例如

void enable2FactorAuth(I2FactorInfoStore store)

然后所有隐藏的规则都消失了。您的系统确保您无法启用该功能,除非您已实现所需的接口。很简单。

如果您认为您将失去在不进行编程的情况下配置产品的能力,那么我想提醒您,您确实没有拥有该功能。正如您所说,客户端必须编写一些代码才能使用 2 因素身份验证。他们必须实施商店。要求他们调用一个方法来启用它只会改进这段代码,因为现在很明显为什么他们必须首先实现那个商店。

【讨论】:

  • 关于第二个选项慢慢变成配置地狱的说法是正确的。这正是我不喜欢微软默认身份验证实现的原因。当我想做一个小改动时,我必须翻阅几页文档。关于选项 3:我计划通过配置文件启用该功能。如果启用了该功能,框架将尝试从服务提供商处获取存储并调用该方法。您的解决方案有点道理,我正在考虑如何实施您的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-17
  • 2022-11-09
  • 2016-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多