我有一堂课计算工人的年净收入。它有一个代表税率百分比的常数。但是有一天,税率发生了变化,因此我需要修复代码。
固定该常数的行为是否表示违反了“ 开放-封闭原则”,因为它假定应该关闭类进行修改?
我有一堂课计算工人的年净收入。它有一个代表税率百分比的常数。但是有一天,税率发生了变化,因此我需要修复代码。
固定该常数的行为是否表示违反了“ 开放-封闭原则”,因为它假定应该关闭类进行修改?
Answers:
考虑供应商A在某种黑盒库中供用户B,C和D使用的类或组件时,可以更好地理解OCP(请注意,这只是我为了清楚起见而使用的一种思维模型,实际上,该类的唯一用户是否是A自己都没有关系。
如果B,C和D可以在不同用例中使用或重用提供的类,而无需修改库的源代码,则该组件将满足OCP(就用例类别而言)。有多种方法可以实现这一目标,例如
使类可继承(通常与模板方法模式或策略模式结合使用)
通过为依赖项注入提供“注入点”
通过为类或组件提供配置参数(例如,根据您的情况,使用构造函数参数“ tax percent”,或使用其他配置机制)
可能还有其他方法,具体取决于编程语言或生态系统
您在教科书中找到的典型示例通常是第一类或第二类(我想是因为在那些书的作者看来,第三类太过琐碎,值得一提)。
如您所见,这与供应商A禁止对源代码进行任何更改(例如,错误修复,优化或以向后兼容的方式添加新功能)无关,这与OCP完全无关。OCP是关于A如何设计库中组件的接口和粒度的,因此不同的重用场景(例如使用不同税率的重用)不会自动引起变更需求。
因此,尽管这里有人告诉您,答案显然是“是”,但这违反了OCP。
编辑:似乎在某人之间写了一篇关于该主题的详细博客文章。尽管它的某些部分本来可以用更好的措词来表达(如Derek Elkins所指出的那样),但似乎作者通常同意我的观点,即“实现OCP”不是绝对的,而是只能在某些情况下进行评估。需求变更的类别。
就像其他人说的那样,理想情况下,工人收入类别应允许常数的参数化,使该类别独立于该值。
最终,调用应用程序还可能允许根据外部配置(例如文件)进行参数化。进行外部配置后,我们可以更改税率-尽管请注意,如果在启动时仅读取配置文件一次,则必须重新启动应用程序才能使更新的税率生效,因此请注意心神。我们可以提供一种应用程序功能,可以在需要时重新读取配置,或者可以提供一种更复杂的机制来通知配置文件何时更改...
从长远来看,您可能会发现税收问题不仅需要一个百分比,例如,一天的税法更加复杂,并且需要几个百分比和一些常数(例如,不足1万美元的金额应按X%征税,而其余部分按Y%征税)。
基本上,这建议使用一种策略模式,其中此处涉及的主类接受用于计算税金的策略对象。
可以从配置文件中选择各种策略(以及%和$常量),现在,添加新策略需要添加一些新代码,但不一定要更新现有代码。
每个策略都可能知道如何解析/解释自己的外部配置参数,以及如何计算实际税金。
从动态上讲,税收可能进一步取决于管理区域设置,因此您可能将区域设置与收入或与雇员(或两者)相关联。在外部配置中,我们可能会将语言环境与税收策略相关联。
另请参阅依赖注入,在这里我们明确地管理这些事情。
如果您需要修改类别以更改税额,则其设计确实违反了OCP。到目前为止,您所描述的适当设计是使计算器类将税金值作为参数。
如果您的类是实例化的(意味着它不是静态类),则通过使tax变量class属性(其值是通过构造函数注入)来改善类的内聚性的。
简而言之,您当前的设计使您的类依赖于不是真正常数的常数值(将常数定义为无论如何都不会改变的值,例如PI的值)。它违反了OCP。更改设计以将税额作为构造函数参数接收。
完全同意@Becuzz,我只想总结一下:OCP是关于查找注入到类中的重用(因此有用)抽象的。因此,该类的行为不是通过更改其代码而是通过为其提供不同的实现来修改的。罗伯特·马丁(Robert Martin)的书“ 敏捷软件开发,原理,模式和实践 ”中明确指出了这一点,并选中了相应的章节“开放式原则”,“抽象是关键”子章节。它澄清了另一个误解,即只能通过继承来修改行为。是Bertrand Meyer在1988年的《面向对象的软件构造》一书中提出了这一建议,而不是Robert Martin。