c# - 在服务类上具有状态代表属性是一种好的设计吗?
问题描述
我有一个带有服务类的应用程序,它从数据库中检索数据库元数据并将其返回给调用类。
为了连接到数据库,服务类方法接受一个详细说明连接凭据的参数。
我正在考虑将凭据存储在服务类中的更改。造成这种情况的原因之一是调用类(例如,负责比较不同服务器上的模式)可能连接到多个不同的数据库/服务器,因此调用类基本上会有这些服务类的集合,而不是而不是连接凭据的集合(例如,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)
{
...
}
}
有几个原因我有点怀疑这种方法:
我
INotifyPropertyChanged
在这个类中实现,以便我可以更新 UI 以向用户显示他们是否已连接(例如,如果对服务器的任何调用失败,我可以将其切换为 false)。由于这个原因,它似乎表现得像一个 ViewModel(而不是一个服务)。我不确定在服务类上具有表示其状态的属性是否是一种好习惯,例如
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 状态的想法,“我的连接有问题”。在上面的实现中,我也会失去这个,尽管我认为它可以通过在返回之前将数据服务标记IsConnected
为false
传入来实现IConnectionCredentials
。
解决方案
最终取决于您要做什么,但听起来这种设计将两个(或更多?)问题合并为一个:
- 用户界面更新 (
INotifyPropertyChanged
) - 数据访问
这给了班级不止一个改变的理由。换句话说,它违反了单一职责原则(SRP)。
现在,没有人说你必须遵守 SRP。这和其他SOLID 原则是处理某些复杂性的指南。如果您没有 SOLID 解决的问题,那么您不必遵循这些原则。
然而,在实践中,很难预测未来的问题。代码库从一开始就很少有问题。它慢慢地从简单的事情发展到更复杂的事情。
虽然提议的设计听起来像是混合了关注点(而不是关注点分离),但实际上它可能是良性的。毕竟,INotifyPropertyChanged
它是一个基类库接口,因此您并没有引入与某些特定技术的耦合。不过,我会警惕扩大该类上与 UI 相关的更新范围。
推荐阅读
- javascript - 有没有办法在Javascript中覆盖`new Date()`,所以它总是返回考虑到一个特定硬编码时区的日期?
- rest - 如何将 HashSet 传递给服务器以测试邮递员的 API?
- amazon-ec2 - 无法通过 ssh 访问 aws 实例
- matlab - Matlab:如何从 4-d 矩阵绘图
- oauth-2.0 - 您如何强制合作伙伴安全存储访问令牌?
- angularjs - 不同的html文件和相同的控制器Angular JS
- perl - 将 Log::Log4perl 与 MCE(多核引擎)Perl 一起使用
- javascript - 如何在 if 失败中使 nightwatch.js 测试失败
- reactjs - 如何使用 webapi Core 在 React 中使用 axios.post 下载文件
- sql - 用多行替换一行形成不同的表