IoC / SRP设计问题

时间:2012-02-18 00:18:51

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

我正在开发一个系统,该系统提供访问其数据库的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 - 因此是连接器接口的想法。

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

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

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