首页 > 解决方案 > 在服务类上具有状态代表属性是一种好的设计吗?

问题描述

我有一个带有服务类的应用程序,它从数据库中检索数据库元数据并将其返回给调用类。

为了连接到数据库,服务类方法接受一个详细说明连接凭据的参数。

我正在考虑将凭据存储在服务类中的更改。造成这种情况的原因之一是调用类(例如,负责比较不同服务器上的模式)可能连接到多个不同的数据库/服务器,因此调用类基本上会有这些服务类的集合,而不是而不是连接凭据的集合(例如,IConnectionInfo在以下示例中)。

我可能希望在应用程序中做的另一件事是IDatabaseService为不同类型的 RDBMS(例如 SQL Server、Oracle 等)实现此服务类(在以下示例中),这似乎是离开的最佳方式它对此开放(从服务返回的信息将非常通用,适用于所有受支持的 RDBMS 类型)。

服务类的示例代码如下:

public class DatabaseService : IDatabaseService
{
    private readonly IConnectionInfo ConnectionInfo;
    
    public bool IsConnected; // INotifyPropertyChanged
    
    public string ServerName => IConnectionInfo.ServerName;
    public string DatabaseName => IConnectionInfo.DatabaseName;
    
    public DatabaseService(IConnectionInfo connectionInfo)
    {
        ConnectionInfo = connectionInfo;
    }
    
    public IEnumerable<Table> GetTables()
    {
        ...
    }
    
    public IEnumerable<Column> GetTableColumns(Table table)
    {
        ...
    }
}

有几个原因我有点怀疑这种方法:

  1. INotifyPropertyChanged在这个类中实现,以便我可以更新 UI 以向用户显示他们是否已连接(例如,如果对服务器的任何调用失败,我可以将其切换为 false)。由于这个原因,它似乎表现得像一个 ViewModel(而不是一个服务)。

  2. 我不确定在服务类上具有表示其状态的属性是否是一种好习惯,例如ConnectionInfo, IsConnected

以上看起来是可以接受的设计吗?

更新:进一步的想法和解释

我想我要解决的特定编程问题是,例如,我可能有一个用于 SQL Server 凭据的类和一个用于 Oracle 凭据的类,两者都是IConnectionCredentials. 然后,我将有几个相应的实现IDataService,它们将接受IConnectionCredentials作为参数。问题是并非所有的实现IDataService都适用于所有的实现IConnectionCredentials,这对我来说似乎有缺陷,所以我认为将数据访问层和“数据访问器”对象组合到一个类中是有意义的。我想IDataService包含逻辑来确定使用哪个版本的“真实”数据访问接口可能是可行的。例如:

public class DataService : IDataService
{
    private readonly RealDataServiceFactory RealDataServiceFactory;
    
    public IEnumerable<Table> GetTables(IConnectionCredentials connectionCredentials)
    {
        return RealDataServiceFactory.Create(connectionCredentials).GetTables(connectionCredentials);
    }
}

public class RealDataServiceFactory
{
    public IRealDataService Create(IConnectionCredentials connectionCredentials)
    {
        if (connectionCredentials is SqlServerConnectionCredentials)
        {
            return new SqlServerDataService();
        }
        else if ...
    }
}

我想要IsConnected数据访问类中的属性的另一个原因是,除了连接不工作之外,服务可能不会返回数据,而且我没有感觉到确定属于调用类的逻辑,所以喜欢数据服务可以同时向某些调用返回 null 并且还向应用程序和 UI 状态的想法,“我的连接有问题”。在上面的实现中,我也会失去这个,尽管我认为它可以通过在返回之前将数据服务标记IsConnectedfalse传入来实现IConnectionCredentials

标签: c#wpfdesign-patternsmvvm

解决方案


最终取决于您要做什么,但听起来这种设计将两个(或更多?)问题合并为一个:

  • 用户界面更新 ( INotifyPropertyChanged)
  • 数据访问

这给了班级不止一个改变的理由。换句话说,它违反了单一职责原则(SRP)。

现在,没有人说你必须遵守 SRP。这和其他SOLID 原则是处理某些复杂性的指南。如果您没有 SOLID 解决的问题,那么您不必遵循这些原则。

然而,在实践中,很难预测未来的问题。代码库从一开始就很少有问题。它慢慢地从简单的事情发展到更复杂的事情。

虽然提议的设计听起来像是混合了关注点(而不是关注点分离),但实际上它可能是良性的。毕竟,INotifyPropertyChanged它是一个基类库接口,因此您并没有引入与某些特定技术的耦合。不过,我会警惕扩大该类上与 UI 相关的更新范围。


推荐阅读