Questions tagged «open-close»

8
LSP vs OCP / Liskov换人VS开盘关闭
我试图理解OOP的SOLID原则,并且得出的结论是LSP和OCP有一些相似之处(如果不多说的话)。 开放/封闭原则指出“软件实体(类,模块,功能等)应为扩展而开放,但为修改而封闭”。 LSP在简单的话指出,任何情况下Foo可以用的任何实例来代替Bar它源自Foo并计划将工作同样非常的方式。 我不是专业的OOP程序员,但在我看来,只有在Bar派生自LSP Foo不会更改其中任何内容而只能扩展它的情况下,LSP才是可能的。这意味着特别是程序LSP仅在OCP为true时才为true,而OCP仅在LSP为true时才为true。那意味着他们是平等的。 如果我错了纠正我。我真的很想了解这些想法。非常感谢您的回答。

8
重写Object.finalize()真的不好吗?
反对重写的两个主要论点Object.finalize()是: 您不必决定何时调用它。 它可能根本不会被调用。 如果我正确理解了这一点,我认为这些理由不足以令人讨厌Object.finalize()。 由VM实施和GC决定何时分配对象的正确时间,而不是开发人员。为什么决定何时Object.finalize()打电话很重要? 通常,如果我错了,请纠正我,唯一的一次Object.finalize()调用是在GC有机会运行之前终止应用程序的时间。但是,无论如何,当应用程序的进程终止时,对象都会被释放。因此Object.finalize()没有被调用,因为它不需要被调用。开发人员为什么要关心? 每次我使用必须手动关闭的对象(例如文件句柄和连接)时,我都会感到非常沮丧。我必须不断检查对象是否具有的实现close(),并且我肯定在过去的某些时候错过了对它的一些调用。为什么不把它放到VM和GC中,而是通过将close()实现放入其中来处置这些对象,这将变得更加简单,安全Object.finalize()呢?

1
为什么(/ did)Bertrand Meyer认为子类化是扩展“封闭式”模块的唯一方法?
在Meyer的“ 面向对象的软件构造”(1988)中,他将开放/封闭原则定义如下: 如果模块仍可扩展,则称其为打开状态。例如,应该可以向其包含的数据结构添加字段,或者向其执行的功能集添加新元素。 如果某个模块可供其他模块使用,则将其称为已关闭。假设已为模块提供了良好定义的稳定描述(信息隐藏的界面)。 他接着说: 如果重新打开模块,则还必须重新打开其所有客户端以对其进行更新,因为它们依赖于旧版本。…[此问题]每当模块必须由新功能或数据元素扩展时触发,从而触发直接和间接客户端中的更改。...使用经典的设计和编程方法,无法编写打开和关闭的模块。 Meyer解决这个难题的方法是:永远不要通过修改现有的类来扩展库模块;而是编写一个新模块来对现有类进行子类化,并使新客户端依赖于该新模块。 现在,在1988年,我正在用Turbo Pascal和Blankenship Basic编写玩具(程序)程序,而我在21世纪的专业经验是使用JVM,CLR和动态语言,所以我不知道Meyer的意思。通过“经典的设计和编程方法”。 Meyer的一个具体示例说明了为什么必须重新打开客户端模块(枚举上的switch语句,现在有更多的成员,需要更多的情况)似乎很合理,但是他几乎没有断言每次向库添加功能时都会断言模块,您需要更新其所有客户端。 是否有历史原因使该主张在1988年显得不言而喻?例如,向C静态库添加函数或数据结构是否更改了布局,以至于即使使用向后兼容的API,也必须重新编译客户端?还是Meyer真的只是在谈论一种用于强制API向后兼容的机制?

4
模拟是否违反开放/封闭原则?
前段时间,我在找不到的Stack Overflow答案上读了一句话,该句子解释您应该测试公共API,而作者说您应该测试接口。作者还解释说,如果更改了方法实现,则无需修改测试用例,因为这样做会破坏确保被测系统正常工作的契约。换句话说,如果方法不起作用,则测试应该失败,但这不是因为实现发生了变化。 当我们谈论嘲笑时,这引起了我的注意。由于模拟在很大程度上依赖于被测系统依赖项的期望调用,因此模拟与实现紧密相关,而不是与接口紧密相关。 在研究模拟与存根时,有几篇文章认为应该使用存根而不是模拟,因为它们不依赖于依赖项的期望,这意味着测试不需要了解测试实施中的基础系统。 我的问题是: 模拟是否违反开放/封闭原则? 在上一段中支持存根的论点中是否缺少某些内容,使存根与模拟不那么好? 如果是这样,什么时候可以模拟一个好用例,什么时候可以使用存根?

5
重载了开放/封闭原则的例子吗?
维基百科说 “软件实体(类,模块,功能等)应打开以进行扩展,但应关闭以进行修改” 函数一词引起了我的注意,现在我想知道是否可以假定为方法创建重载可以视为“打开/关闭”原理的示例吗? 让我解释一个例子。考虑一下您的服务层中有一个方法,该方法在将近1000个地方中使用。该方法获取userId并确定用户是否为admin: bool IsAdmin(userId) 现在考虑在某个地方,有必要根据用户名而不是userId来确定用户是否为admin。如果我们更改上述方法的签名,那么我们已经在1000个地方破坏了代码(功能应禁止修改)。因此,我们可以创建一个重载来获取用户名,基于用户名找到userId以及原始方法: public bool IsAdmin(string username) { int userId = UserManager.GetUser(username).Id; return IsAdmin(userId); } 这样,我们通过为其创建重载扩展了功能(功能应可扩展)。 它是一个开放/封闭原则的例子吗?

7
重构和开放/封闭原则
我最近正在阅读一个有关干净代码开发的网站(我不在此处放置链接,因为它不是英语)。 本网站宣传的原则之一是开放式封闭原则:每个软件组件都应开放以进行扩展,而封闭则可以进行修改。例如,当我们实现并测试了一个类时,我们仅应对其进行修改以修复错误或添加新功能(例如,不影响现有方法的新方法)。现有功能和实现不应更改。 我通常通过定义接口I和相应的实现类来应用此原理A。当类A变得稳定(实现并经过测试)后,我通常不会对其进行过多修改(可能根本没有修改),即 如果新的要求到达需要的代码大的变化(如性能,还是一个全新的接口的实现),我写了一个新的实现B,并使用保持A,只要B还没有成熟。当B成熟时,所需要做的就是更改I实例化方式。 如果新的要求也建议更改接口,那么我将定义一个新的接口I'和一个新的实现A'。所以I,A被冻结并保持实施生产系统,只要I'和A'不够稳定,以取代他们。 因此,鉴于这些观察,令我感到惊讶的是该网页随后建议使用复杂的重构,“……因为不可能直接以其最终形式编写代码。” 在执行“开放/封闭原则”与建议使用复杂重构作为最佳实践之间是否存在矛盾/冲突?还是这里的想法是,在开发一个类的过程中可以使用复杂的重构A,但是当成功测试了该类后,应该冻结它吗?
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.