【问题标题】:IoC/SRP design issueIoC/SRP 设计问题
【发布时间】:2012-02-18 00:18:51
【问题描述】:

我正在针对一个系统进行开发,该系统提供访问其数据库的 Web 服务并通过 .NET 类公开该服务。我们通常的工作方式是在需要访问数据库并直接使用该实例时创建 Web 服务类的实例;这当然完全违背了 IoC 并创建了大部分不可测试的代码。我现在正在尝试设计一种使用 IoC 的新标准工作方式,以使我们能够编写(更多)SOLID 代码。

我目前的解决方案是这样的(解释得不是很好):

Web 服务封装在 DatabaseConnection 类中,该类将 Web 服务对象存储为受保护的成员,并提供对许多常用通用数据库调用的访问。

当我需要在实际应用程序中访问数据库时,我从该类派生(调用新类,例如 ApplicationDatabaseConnection)并在能够调用 Web 服务的方法中实现所需的数据库交互。

此类不直接在应用程序中使用,而是为应用程序的不同部分提供“连接器”接口,每个部分由顶层的控制器/视图模型类表示。每当调用其中一个应用程序功能时(例如从 UI 调用),就会创建相应的控制器对象并将我的 ApplicationDatabaseConnection 对象作为相应“连接器”接口的实现传递,因此数据库访问在此时被正确封装和解耦,据我所知。

我的问题是:虽然这是我在自己的代码中发现 ISP(接口隔离原则)实际使用的第一个案例(尽管我不确定这是否真的合理使用该概念),恐怕这个类可能做的太多,违反了 SRP(单一责任原则)。还是“仅提供数据库访问权限,尽管针对许多不同的消费者”是一项单一职责?

为了更清楚一点,以下是相关类的大致样子:

DatabaseConnection
    protected m_webservice
    public OftenUsedDatabaseAccess()

ApplicationDatabaseConnection : DatabaseConnection, IConnectorA, IConnectorB
    public IConnectorA.RetrieveRecords(fieldValue)
    public IConnectorB.WriteStuff(listOfStuff)

FunctionAController
    private m_IConnectorA

FunctionBController
    private m_IConnectorB

我能想到的替代方案对我来说似乎也不理想。

为了拆分数据库访问功能,ApplicationDatabaseConnection 类只能是具有用于不同连接器的Create 方法的工厂类(在IConnectorAFactoryIConnectorBFactory 接口后面)——但实际上并没有什么可做的需要工厂模式;我只有在实例化“控制器”对象时才知道。

此外,实际的连接器类本质上也需要是 DatabaseConnection 的派生类,因为它们需要相同的基本能力,然后(最迟)整个构造变得相当不祥。

我想我的想法在某个时候走错了方向,现在完全走错了路。这种解决方案的结构应该是什么样的?任何朝着正确方向的推动都将不胜感激。

编辑:

@Tobias 的回答让我意识到我忘记了一个重要的细节:有两个不同版本的 Web 服务具有几乎相同的功能,但 API 完全不同,这也是它 具有的原因之一em> 被封装。

另一个问题是,如果我的逻辑类直接(或通过接口)访问 Web 服务,它们还关心构建 Web 服务查询的所有细节,这使得代码耦合更紧密(我们'到目前为止一直在生产)并且违反了 SRP - 因此是连接器接口的想法。

【问题讨论】:

    标签: .net oop dependency-injection inversion-of-control single-responsibility-principle


    【解决方案1】:

    为什么不直接创建一个接口,例如 MyWebService 并在调用您的服务的 MyWebServiceImpl 中实现它?可以公开与您的服务相同的方法,然后委托给它...

    【讨论】:

      【解决方案2】:

      几个月后,我知道“ApplicationDatabaseConnection”方法不仅违反了 SRP,还违反了 OCP,同时还阻碍了模块化。

      我最终采用的路线有点类似于我描述的“工厂”替代方案——“主”DatabaseConnection 对象是一个子类,该子类也有一个“Create”方法,该方法将工厂用于特定的 DatabaseConnection 派生并且不不关心它究竟创造了什么。这样每个控制器都可以请求自己的连接对象,并且可以添加主应用程序不知道的控制器(即通过 MEF)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-05-12
        • 1970-01-01
        • 2011-10-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-28
        • 1970-01-01
        相关资源
        最近更新 更多