您是否曾经遇到过代码重复的情况,在查看代码行后,您无法符合主题抽象,以忠实地描述其在逻辑中的作用?您做了什么来解决它?

它是代码重复,因此理想情况下,我们需要进行一些折射,例如制作自己的功能。但是,由于该代码没有很好的抽象来描述它,因此结果将是一个奇怪的功能,我们甚至无法找到一个好名字,并且在逻辑中的作用并不明显,而仅仅看着它。对我来说,这损害了法规的清晰度。我们可以保持清晰度并保持原样,但随后我们损害了可维护性。

您认为解决此类问题的最佳方法是什么?

有帮助吗?

解决方案

有时代码重复是“双关语”的结果:两件事看起来相同,但事实并非如此。

超抽取可能会破坏系统的真实模块。在模块化制度下,您必须决定“可能会改变什么?”和“什么是稳定?”。无论是稳定的什么都放在界面中,而不稳定的东西都会封装在模块的实现中。然后,当事情发生变化时,您需要做出的更改将隔离到该模块。

当您认为稳定的内容(例如,此API呼叫将始终需要两个参数)需要更改时,重构是必要的。

因此,对于这两个重复的代码片段,我会问: 一个人所需的更改一定意味着另一个也必须更改?

您如何回答这个问题可能会使您更好地了解一个良好的抽象。

设计模式也是有用的工具。也许您的重复代码正在采用某种形式的遍历,应应用迭代器模式。

如果您的重复代码具有多个返回值(这就是为什么您不能执行简单的提取方法),那么也许您应该做一个可以保留返回值的类。该类可以为每个点调用一个抽象方法,该方法在两个代码片段之间有所不同。然后,您将对班级进行两个具体的实现:每个片段。 [这实际上是模板方法设计模式,不要与C ++中模板的概念相混淆。另外,您正在考虑的策略模式可以更好地解决您的看法。

考虑它的另一种自然和有用的方法是具有高阶功能。例如,制作lambdas或使用匿名内部类使代码传递给抽象。通常,您可以删除重复,但是除非它们之间确实存在关系(如果一个更改,那么另一个都可以更改),那么您可能会伤害模块化,而无济于事。

其他提示

当您遇到这种情况时,最好考虑“非传统”抽象。也许您在功能中有很多重复,并且考虑到普通的旧功能不太合适,因为您必须传递太多变量。在这里,D/Python样式的嵌套功能(具有外部范围的访问)可以很好地工作。 (是的,您可以上课以保持所有状态,但是如果您仅在两个功能中使用它,这是一个丑陋而冗长的解决方法。)也许继承不太合适,但是Mixin可以很好地工作。也许您真正需要的是宏。也许您应该考虑一些模板元编程或反射/内省,甚至是生成编程。

当然,从务实的角度来看,如果您的语言不支持它们,并且没有足够的元编程功能来在语言中干净地实现它们,那么这些都很难即使不是不可能。如果是这种情况,我不知道该告诉您什么,除了“获得更好的语言”。同样,学习具有许多抽象功能的高级语言(例如Ruby,Python,LISP或D)可能会帮助您在低级语言中更好地编程,在低级语言中,某些技术仍然可以使用,但不太明显。

我个人忽略了它并继续前进。很可能是奇怪的情况,最好重复它,您可以花费很长时间进行重构,而下一个开发人员会看一眼并撤消您的更改!

没有代码样本,很难说为什么您的代码没有容易识别的抽象。有了警告,这里有几个想法:

  • 与其创建一个新功能来保存通用代码,不如将功能分解为几个不同的部分。
  • 根据常见数据类型或抽象行为将小块组合在一起;
  • 重写给定新作品的重复代码;
  • 如果新代码仍然违反明确的抽象,请将其分解为小并重复该过程。

这项练习中最大的困难是,您的功能可能在给定的抽象水平上融合了太多无关的行为,并且您需要在较低级别上处理其中的一些行为。您正确地推测清晰度是维护代码的关键,但是使代码的行为清晰(其当前条件)与使代码的意图明确。

通过使其功能签名识别什么,将较小的代码件抽象的方法抽象化,较大的零件应该更容易进行分类。

许可以下: CC-BY-SA归因
scroll top