因此,当编写原始代码时,只需要说LabTest类 . 但现在说我们有新的要求添加说RadiologyTest,EKGTest等 .
这些类有很多共同之处,因此有一个基类是有意义的 .
但这意味着必须修改LabTest类,让我们说它的界面将保持原样,换句话说,LabTest类的消费者不需要改变 .
这违反了开放封闭原则吗? (正在修改LabTest) .
我想你可以从两个角度看待它: existing requirements 和 new requirements .
如果现有的要求没有涵盖这些变化的需要,那么我会说,基于这些要求,LabTest没有违反OCP .
根据新要求,您需要添加不适合LabTest实现的功能 . 将其添加到OCP会违反SRP . 这些要求现在会创建一个新的更改向量,这将迫使您重构LabTest以使其保持OCP . 如果您未能重构LabTest,则会违反SRP和OCP . 重构时,请记住您创建或修改的任何类中的新更改向量 .
我想你可能违反了SRP . 毕竟,如果每个 class 完成一项任务,两个或两个以上的课程如何相似?如果有任务他们都做同样的事情,那么这是一个单独的任务,应该由另一个类完成 .
所以我会说,首先重构 LabTest 进入它's constituent parts (hope you'已经进行了单元测试!) . 然后当你来写 RadiologyTest , EKGTest 时,他们可以重用对它们有意义的部分 . 这也称为继承的组合 .
LabTest
RadiologyTest
EKGTest
但无论你做什么,都要在客户端使用这些类的接口 . 不要强迫关注者使用您的基类添加扩展名 .
我可能会因为这个答案而被烧伤,但无论如何都会陷入困境 . 在我看来(IMO),OCP不能像纯粹主义者那样遵循其他原则,如SRP,DIP或ISP .
如果需求发生变化,您必须将类的职责更改为对其域模型的表示形式为真,那么我们必须更改该类 .
IMO,OCP阻止我们重新分解代码以跟随系统的发展 .
Update: 经过进一步的研究,这就是我的想法:让我们说,我已经在单元级别和集成级别进行了自动化测试,然后我们应该重新设计整个系统以适应新模型,OCP就在这里 . IMO,系统演化的目标始终是避免黑客攻击(不改变LabTest类和相应的DB表,以免破坏旧代码[不违反OCP],并使用LabTest存储EKGTest的常用数据并在EKGTest中使用LabTest或继承自LabTest的EKGTest将是一个黑客,IMO将会并且使系统尽可能准确地表示其模型 .
我认为开放封闭原则(无论如何,鲍勃叔叔和Bertrand Meyers所描述的)并不是永远不会修改类(如果软件永远不会改变它也可能是硬件) .
在你自己的情况下,我不会违反OCP,因为你已经提到过你所有的类使用取决于 LabTest 的抽象而不是 RadiologyTest 的实现 .
从Uncle Bob's introductory paper开始,他有一个 DrawAllShapes 类的示例,如果设计为OCP,则每次将 Shape 的新子类添加到系统时都不需要更改 . 关于你应用它的级别,鲍勃叔叔说 -
DrawAllShapes
Shape
应该清楚的是,没有重要的计划可以100%关闭 . 例如,如果我们决定在任何Square之前绘制所有Circles,请考虑清单2中的DrawAllShapes函数会发生什么 . DrawAllShapes函数未针对此类更改关闭 . 一般来说,无论一个模块是多么“封闭”,总会有一些变化,它不会被关闭 . 由于关闭不能完成,它必须是战略性的 . 也就是说,设计师必须选择各种变化来关闭他的设计 .
我不会将“关闭修改”视为“不要重构”,更多的是你应该设计你的类,使其他类不能进行会影响你的修改 - 例如应用基本的OO东西 - 通过getter / setter和私有成员封装变量 .
4 回答
我想你可以从两个角度看待它: existing requirements 和 new requirements .
如果现有的要求没有涵盖这些变化的需要,那么我会说,基于这些要求,LabTest没有违反OCP .
根据新要求,您需要添加不适合LabTest实现的功能 . 将其添加到OCP会违反SRP . 这些要求现在会创建一个新的更改向量,这将迫使您重构LabTest以使其保持OCP . 如果您未能重构LabTest,则会违反SRP和OCP . 重构时,请记住您创建或修改的任何类中的新更改向量 .
我想你可能违反了SRP . 毕竟,如果每个 class 完成一项任务,两个或两个以上的课程如何相似?如果有任务他们都做同样的事情,那么这是一个单独的任务,应该由另一个类完成 .
所以我会说,首先重构
LabTest
进入它's constituent parts (hope you'已经进行了单元测试!) . 然后当你来写RadiologyTest
,EKGTest
时,他们可以重用对它们有意义的部分 . 这也称为继承的组合 .但无论你做什么,都要在客户端使用这些类的接口 . 不要强迫关注者使用您的基类添加扩展名 .
我可能会因为这个答案而被烧伤,但无论如何都会陷入困境 . 在我看来(IMO),OCP不能像纯粹主义者那样遵循其他原则,如SRP,DIP或ISP .
如果需求发生变化,您必须将类的职责更改为对其域模型的表示形式为真,那么我们必须更改该类 .
IMO,OCP阻止我们重新分解代码以跟随系统的发展 .
如果我错了,请纠正我 .
Update: 经过进一步的研究,这就是我的想法:让我们说,我已经在单元级别和集成级别进行了自动化测试,然后我们应该重新设计整个系统以适应新模型,OCP就在这里 . IMO,系统演化的目标始终是避免黑客攻击(不改变LabTest类和相应的DB表,以免破坏旧代码[不违反OCP],并使用LabTest存储EKGTest的常用数据并在EKGTest中使用LabTest或继承自LabTest的EKGTest将是一个黑客,IMO将会并且使系统尽可能准确地表示其模型 .
我认为开放封闭原则(无论如何,鲍勃叔叔和Bertrand Meyers所描述的)并不是永远不会修改类(如果软件永远不会改变它也可能是硬件) .
在你自己的情况下,我不会违反OCP,因为你已经提到过你所有的类使用取决于
LabTest
的抽象而不是RadiologyTest
的实现 .从Uncle Bob's introductory paper开始,他有一个
DrawAllShapes
类的示例,如果设计为OCP,则每次将Shape
的新子类添加到系统时都不需要更改 . 关于你应用它的级别,鲍勃叔叔说 -我不会将“关闭修改”视为“不要重构”,更多的是你应该设计你的类,使其他类不能进行会影响你的修改 - 例如应用基本的OO东西 - 通过getter / setter和私有成员封装变量 .