有一个名为AbstractAgent
的抽象类,目前有27个类正在扩展这个类。
我已经开始开发一些代理,我的所有5个代理都在扩展AbstractAgent
类。
现在我发现我的所有5个代理都有一个getFilePath()
复制粘贴。然后我意识到在现有的27个班级中也有很多班级都有这种方法。我认为将此方法放在基类AbstractAgent
中并让每个人都使用此方法是个好主意。但我不希望所有现有的类都改变他们的代码我已经改变了方法名称,以便前进任何人都可以使用它。
进行我的代码审核的人建议我不要触摸AbstractAgent
类,因为它已经被现有客户端使用,并且这个方法是一些实用程序类。
我不相信他的论点。任何人都想表达他们的想法。
答案 0 :(得分:5)
在这种情况下,因为AbstractAgent
类已被其他类使用,并且正如您自己提到的那样 NOT 所有类都实现了此方法,那么您确实不应该更改{{ 1}}。但是,您可以在名为AbstractAgent
的另一个抽象子类中扩展AbstractAgent
,该子类声明您需要的其他方法,然后让这些类扩展AbstractAgentWithFilePath
类。
答案 1 :(得分:3)
向父类添加公共逻辑是抽象类的强大方面之一,这种添加是向前兼容的更改。当然,除非您不了解此类的某些用法,否则您新添加的方法具有相同的名称。但即便如此,如果子类覆盖这样的方法,它将调用自己的方法,因此它仍然是向前兼容的变化。
答案 2 :(得分:3)
如果getFilePath()
方法对于所有AbstractAgent
的子类完全相同,那么请务必将其拉到抽象类(使用IDE的重构工具),删除它从子类然后运行单元测试(你做有单元测试,对吧?)并检查一切是否正常。
如果getFilePath()
的某些实现之间存在差异,但大多数都是相同的,那么将最常见的实现拉到抽象类仍然是个好主意,删除它来自使用它的子类,并在实现不同的情况下覆盖子类中的方法。
现在,如果方法的不同实现之间存在太多差异,请保持代码库不受影响。
在实用程序类中定义静态方法(例如,FileUtil
)只有在方法与Agent类的功能没有直接关系时才有意义,或者该方法可能在其他部分中使用对象层次结构,与代理没有直接关系。
答案 3 :(得分:0)
如果该方法与Agent类紧密相关,则将它放在abstract中是一个不错的选择,但如果不是,则将其放在另一个处理所有与File相关的操作的实用程序类中。
答案 4 :(得分:0)
这里没有正确答案。只有您,您的同事和您的公司知道AbstractAgent的使用方式和位置,以及它如何影响各种不同的团队,部门或客户。关于在何处定位代码的决定通常比“洁净室”设计选择更具政治性和社会性。
从纯粹的代码角度来看,我支持激进的重构:去除AbstractAgent的所有子类中的所有重复代码,并将每个人移动到AbstractAgent中的新getFilePath()。
但你可能没有权力这样做,你可能会受到阻碍。或者也许getFilePath()有时略有不同(你不清楚这一点。)在这种情况下,你做出的任何选择似乎都是妥协。您的代码审阅者可能会反对AbstractAgent中的'getFilePath2()',因为它揭示了不完整代码重用的问题,并感觉它正在通过临时解决方案“污染”超类,通过让每个人都能真正解决的问题迄今为止,在超类中使用真正常见的共享代码。谁知道。
在完成重构之前,静态实用程序方法可能是更好的选择。