为什么Open-Closed Principle如此重要? 如果您有测试,为什么要担心代码修改?
答案 0 :(得分:1)
如果您有测试,为什么要担心代码修改?
在单元测试的上下文中, open-closed 原则是一种设计原则,允许您添加新代码,而对已经预先编写的代码的影响最小。经过测试的内容不会因为新的要求而改变,从而减少了程序员在稳定的代码库上创建的损坏范围。考虑以下伪对象代码示例,它不遵循开放原则:
class NumberOperations {
public void add(Number a,Number b) {
Number result = null;
if(a instanceof Integer && b instanceof Integer) {
Integer aInt = (Integer)a;
Integer bInt = (Integer)a;
result = aInt + bInt;
} else {
//failure/error : only integer operations supported.
}
return result;
}
}
您测试上面的代码,并且所有工作都按预期工作。您现在决定支持小数运算,因此您可以按如下方式修改add
函数:
public void add(Number a,Number b) {
Number result = null;
if(a instanceof Integer && b instanceof Integer) {
Integer aInt = (Integer)a;
Integer bInt = (Integer)a;
result = aInt + bInt;
} else if(a instanceof Double && b instanceof Double) {
Double aDecimal = (Double)a;
Double bDecimal = (Double)b;
result = aDecimal + bDecimal ;
} else {
//failure/error : only integer and double operations supported.
}
return result;
}
只需要一个支持十进制加法的新简单要求,就添加了4行新代码,重新排列了一行代码,并将损坏区域加倍。对于这样一个简单的例子,这看起来微不足道,但现实世界的代码很少是基本的。您可以向现有代码引入副作用,这些代码都不会出现任何测试用例。
如果您遵守 open-closed 原则,您可以从IntegerOperations
扩展名为DoubleOperations
和NumberOperations
的子类(现在可能是抽象的)实现add
方法。上面显示的if
方法中第一个add
内的代码可以移到add
类中的IntegerOperations
方法中,else-if
中的代码可以是移至add
课程中的DoubleOperations
方法。如果您的语言支持泛型,您甚至可以摆脱上面示例所显示的类型检查。
然后,您可以单独测试这两个新类。当您需要添加两个String
时,您将创建一个名为StringOperations
的新类。您不必担心会对IntegerOperations
或DoubleOperations
进行任何不必要的更改,因此无需再次对其进行测试。您只需要测试StringOperations
类。
摘要:OCP不仅可以减少您可能将代码库暴露给损坏的区域,还允许您的API用户添加新功能(例如通过子类化),而无需依赖在你做出这些改变。您可以确保在没有OCP的情况下测试所有关键代码路径。您无法保护代码库的风险是其他人破坏已经过测试过的代码的风险,这些代码会引入您在测试中甚至没有考虑到的错误。
答案 1 :(得分:0)
在一个完美的世界中,您将拥有覆盖100%代码库的测试,您还可以使用工具来测量它。但是,这些都不是真的。获得100%的覆盖率并确保在应用程序五年之后100%覆盖仍然有效是非常困难的。在发布之前,您可能没有足够的时间来实现它。你团队中的其他一些人并不严格。您可能只是有一个必须遵守的截止日期。显示100%的工具通常理解一个执行分支已到达代码行,而另一个执行分支已到达的代码行尚未执行。
在完美的世界中,您的代码也易读且易于理解。在现实世界中,可读性不仅取决于您,而且取决于整个团队。它还取决于您是否真的可以选择在整个应用程序生命周期中获得的每个问题的最佳解决方案。我有20年的经验,我仍然发现自己偶尔编写糟糕的代码。原因是我并不完美,我并不总是有完美的条件,如清晰的要求或对客户想要的描述。
SOLID原则和其他最佳实践和原则可以帮助您,因为世界并不完美。但是通过遵循开放/封闭原则等原则,您可以为未来的自己提供更好的机会来处理您的代码库。这些原则是由经验丰富的人员定义的,他们已经认识到哪些有效,哪些无效。
答案 2 :(得分:0)
当然,如果你真的有非常好的系统测试,你可以确信你的代码仍然能用于大规模的,破坏性的编辑,所以尽管你会想到一些原则上的狂热分子,但这个原则并不是必需的 - 但这是一种实用性。你不必使用它,但如果你这样做,你通常会让事情变得更容易。 O / C原则的有用实用性是能够扩展现有代码以满足新要求,而不会破坏该代码的现有用途。即使您最终不需要花时间修改现有代码,因为编辑没有破坏它,您仍然需要重新测试它。
在考虑现有测试时(我认为这比单元测试更适用于系统测试),您必须考虑与o / c原则的封闭部分相反的编辑是否会破坏现有测试试验。如果您通过更改界面或更改所需的前提条件来破坏现有测试,则无法在旧实现和新实现上使用相同的测试(您的新测试可能基于旧测试但不完全准确相同)。也许更令人担忧的是(仅仅因为它不会像破坏的测试一样显得很明显)编辑可能意味着应该有一些额外的测试已经不存在 - 也许你已经引入了新的特别案例。编辑可能会产生未经测试的意外副作用。
归根结底,O / C原则只是一个目标,我们可以确定一些原则是否能成功地遵循它们。根据O / C原则,我们可能会发现,当我们真正想要扩展它时,原件并不像我们希望的那样开放,如果事实证明原件没有正常工作则需要它即使你认为这违背了封闭性,也会发生变化。
与许多原则一样,它不是必不可少的,一般来说它很有帮助,随之而来的努力会随着时间的推移而得到回报。