如何在请求新功能时不违反开闭原则?
How to not violate Open-Close Principle when new feature is requested?
我需要在项目中添加一个新功能,我正在尝试以最佳方式进行。
所以新特性 => 开闭原则。我应该不会更改现有代码,对吗?
界面如下:
public interface IEcuStatisticsExportManager
{
void ExportStatistics(string datasource, bool modifiedOnly, string userName);
}
有一个 class 已经实现了这个接口:
public class EcuStatisticsExportManager : IEcuStatisticsExportManager
{
public void ExportStatistics(string datasource, bool includeAll, string userName)
{
//Actual behavior of this method allow us to export statistics for
//only one data source. We need to extend this by allowing the user
//to export statistics for multiple data sources.
//Another new feature will be an option to export statistics for
//all data sources we have in the database
}
}
考虑到这些,之后界面必须如下所示:
public interface IEcuStatisticsExportManager
{
void ExportStatistics(string datasource[], bool exportAll, bool modifiedOnly, string userName);
}
我正在为以下事情绞尽脑汁:
由于我无法在需要新行为的地方重写方法,我该如何遵守打开关闭原则?
我将如何遵守原则,因为我必须在界面上进行更改?
请帮助我以最好的方式做到这一点。
此致。
您提议的更改将运行 违反open/closed 原则。对扩展开放,对修改关闭。您正在修改接口中方法的签名,这是一个重大更改。 None 实施该接口的现有项目将在您部署该更改后工作。
根据您的需要,您可以创建第二个界面,例如IEcuStatisticsExportManagerExtended
并将您的新方法放在那里。然后 类 可以根据需要实现一个或两个接口。
这不是一个包罗万象的答案,但在这种情况下,您可以创建一个重载方法。
public interface IEcuStatisticsExportManager
{
void ExportStatistics(string datasource, bool modifiedOnly, string userName);
void ExportStatistics(string[] datasource, bool exportAll, bool modifiedOnly, string userName);
}
单源方法最有可能调用多源方法,将单个输入转换为一个数组。
但为了避免进一步更改签名,我会为新方法使用输入 class,例如
public class ExportStatisticsInput
{
public string[] DataSources {get; set;}
public bool ExportAll {get; set;}
public bool ModifiedOnly {get; set;}
public string UserName {get; set;}
}
public interface IEcuStatisticsExportManager
{
void ExportStatistics(string datasource, bool modifiedOnly, string userName);
void ExportStatistics(ExportStatisticsInput input);
}
这仍然可以解释为对 open/closed 原则的轻微违反,但还算不错。您可能只是将一个方法的内容原封不动地移动到一个从两个 public 方法调用的私有方法中。
Open Closed Principle是你在设计项目架构时应该考虑的,至少从我的拙见来看,它永远不会涵盖100%的情况。当你需要添加一个特性时,设计总是有可能不支持这个特性,因此必须打破原则。通常大约 30% 的工作是设计,其余的工作是修改设计。总的来说,我会说只有在可能和合理的情况下才应该保留这个原则。 SOLID 和设计模式等概念的主要问题是人们总是在寻找经验法则,如果不理解为什么要按照特定规则工作,那么遵循它弊大于利。
Tmho,您应该问自己的是,在给定业务案例的给定系统中的给定案例中保留该规则是否有意义。在这种情况下,除了您的旧方法之外,将 void ExportStatistics(string datasource[], bool exportAll, bool modifiedOnly, string userName);
添加到现有对象并使用重载可能是有意义的,因此新方法将使用旧方法而不修改它,如果可能的话,可能是通过获取所有如果需要,来自数据库的数据源,运行 数据源上的 foreach 循环并在每个数据源上调用旧方法,然后根据 modifiedOnly 参数对数据应用必要的更改。这将使您免于许多潜在的错误和测试,因为没有触及实际测试的导出方法。另一方面,在许多情况下,它会导致性能下降,或者可能会阻止您使流程成为事务性的。在那种情况下,性能在这里很重要吗?您所有的出口业务都必须是交易性的吗?与另一种方式相比,如果您采用一种方式,则必须添加和维护多少代码,您是否有人力来维护它?它比将您从错误和测试中节省的时间更重要吗?您可以根据自己的情况调整这些问题。只有您知道答案,并且只有根据这些答案您才能做出决定。 SOLID 不是圣经(因此不应该完全忽略),当且仅当它对您的情况有效时才应该使用它。
正如@rory.ap 提到的,同样重要的是不要更改不同对象在不同解决方案中实现的接口,因为这将是一个重大更改 - 这些解决方案将无法构建。如果是这种情况,您应该:
- 按照@roy.ap的建议创建一个新界面
- 在没有接口的对象中添加你需要的方法
- 与您组织中的所有团队协调重大变更,以确保所有其他项目都得到相应更新。
然后检查你的构建服务器,看看所有的构建场景都能构建成功
同样,在这种情况下正确的选择完全取决于您所在的具体情况和组织。
我需要在项目中添加一个新功能,我正在尝试以最佳方式进行。
所以新特性 => 开闭原则。我应该不会更改现有代码,对吗?
界面如下:
public interface IEcuStatisticsExportManager
{
void ExportStatistics(string datasource, bool modifiedOnly, string userName);
}
有一个 class 已经实现了这个接口:
public class EcuStatisticsExportManager : IEcuStatisticsExportManager
{
public void ExportStatistics(string datasource, bool includeAll, string userName)
{
//Actual behavior of this method allow us to export statistics for
//only one data source. We need to extend this by allowing the user
//to export statistics for multiple data sources.
//Another new feature will be an option to export statistics for
//all data sources we have in the database
}
}
考虑到这些,之后界面必须如下所示:
public interface IEcuStatisticsExportManager
{
void ExportStatistics(string datasource[], bool exportAll, bool modifiedOnly, string userName);
}
我正在为以下事情绞尽脑汁:
由于我无法在需要新行为的地方重写方法,我该如何遵守打开关闭原则?
我将如何遵守原则,因为我必须在界面上进行更改?
请帮助我以最好的方式做到这一点。
此致。
您提议的更改将运行 违反open/closed 原则。对扩展开放,对修改关闭。您正在修改接口中方法的签名,这是一个重大更改。 None 实施该接口的现有项目将在您部署该更改后工作。
根据您的需要,您可以创建第二个界面,例如IEcuStatisticsExportManagerExtended
并将您的新方法放在那里。然后 类 可以根据需要实现一个或两个接口。
这不是一个包罗万象的答案,但在这种情况下,您可以创建一个重载方法。
public interface IEcuStatisticsExportManager
{
void ExportStatistics(string datasource, bool modifiedOnly, string userName);
void ExportStatistics(string[] datasource, bool exportAll, bool modifiedOnly, string userName);
}
单源方法最有可能调用多源方法,将单个输入转换为一个数组。
但为了避免进一步更改签名,我会为新方法使用输入 class,例如
public class ExportStatisticsInput
{
public string[] DataSources {get; set;}
public bool ExportAll {get; set;}
public bool ModifiedOnly {get; set;}
public string UserName {get; set;}
}
public interface IEcuStatisticsExportManager
{
void ExportStatistics(string datasource, bool modifiedOnly, string userName);
void ExportStatistics(ExportStatisticsInput input);
}
这仍然可以解释为对 open/closed 原则的轻微违反,但还算不错。您可能只是将一个方法的内容原封不动地移动到一个从两个 public 方法调用的私有方法中。
Open Closed Principle是你在设计项目架构时应该考虑的,至少从我的拙见来看,它永远不会涵盖100%的情况。当你需要添加一个特性时,设计总是有可能不支持这个特性,因此必须打破原则。通常大约 30% 的工作是设计,其余的工作是修改设计。总的来说,我会说只有在可能和合理的情况下才应该保留这个原则。 SOLID 和设计模式等概念的主要问题是人们总是在寻找经验法则,如果不理解为什么要按照特定规则工作,那么遵循它弊大于利。
Tmho,您应该问自己的是,在给定业务案例的给定系统中的给定案例中保留该规则是否有意义。在这种情况下,除了您的旧方法之外,将 void ExportStatistics(string datasource[], bool exportAll, bool modifiedOnly, string userName);
添加到现有对象并使用重载可能是有意义的,因此新方法将使用旧方法而不修改它,如果可能的话,可能是通过获取所有如果需要,来自数据库的数据源,运行 数据源上的 foreach 循环并在每个数据源上调用旧方法,然后根据 modifiedOnly 参数对数据应用必要的更改。这将使您免于许多潜在的错误和测试,因为没有触及实际测试的导出方法。另一方面,在许多情况下,它会导致性能下降,或者可能会阻止您使流程成为事务性的。在那种情况下,性能在这里很重要吗?您所有的出口业务都必须是交易性的吗?与另一种方式相比,如果您采用一种方式,则必须添加和维护多少代码,您是否有人力来维护它?它比将您从错误和测试中节省的时间更重要吗?您可以根据自己的情况调整这些问题。只有您知道答案,并且只有根据这些答案您才能做出决定。 SOLID 不是圣经(因此不应该完全忽略),当且仅当它对您的情况有效时才应该使用它。
正如@rory.ap 提到的,同样重要的是不要更改不同对象在不同解决方案中实现的接口,因为这将是一个重大更改 - 这些解决方案将无法构建。如果是这种情况,您应该:
- 按照@roy.ap的建议创建一个新界面
- 在没有接口的对象中添加你需要的方法
- 与您组织中的所有团队协调重大变更,以确保所有其他项目都得到相应更新。 然后检查你的构建服务器,看看所有的构建场景都能构建成功