当你穿过它们时,你总是会重构哪些类型的编码反模式?

时间:2008-12-23 22:48:02

标签: refactoring anti-patterns

我刚刚重构了一些代码,这些代码位于我正在处理的类的不同部分,因为它是一系列嵌套的条件运算符(?:),它通过一个相当简单的switch语句(C#)变得更加清晰。

您何时会触摸不直接与您合作的代码,以使其更清晰?

18 个答案:

答案 0 :(得分:14)

我曾经进行过重构,并遇到过类似代码的内容:

string strMyString;
try
{
  strMyString = Session["MySessionVar"].ToString();
}
catch
{
  strMyString = "";
}

Resharper指出.ToString()是多余的,所以我把它拿出来了。不幸的是,最终破坏了代码。每当MySessionVar为null时,它都不会导致代码所依赖的NullReferenceException将其向下移动到catch块。我知道,这是一些可悲的代码。但我确实从中学到了很好的教训。不要快速浏览依赖工具的旧代码来帮助您进行重构 - 请自己思考。

我的确最终重构如下:

string strMyString = Session["MySessionVar"] ?? "";

更新:由于这篇文章正在被投票,从技术上讲不包含问题的答案,我想我应该回答这个问题。 (好吧,让我感到困扰的是我实际上在梦想它。)

我个人在重构之前会问自己一些问题。

1)系统是否受源控制?如果是这样,请继续进行重构,因为如果出现问题,您可以随时回滚。

2)是否存在我正在改变的功能的单元测试?如果是这样,太好了!重构。这里存在的危险是单元测试的存在并不表明所述单元测试的准确性和范围。良好的单元测试应该能够发现任何重大变化。

3)我是否完全理解我正在重构的代码?如果没有源代码控制和没有测试,我真的不明白我正在改变的代码,那就是一个红旗。在重构之前,我需要更加熟悉代码。

在#3的情况下,我可能会花时间实际跟踪当前使用我正在重构的方法的所有代码。根据代码的范围,这可能很容易或不可能(即,如果它是公共API)。如果它归结为公共API,那么您真的需要从业务角度理解代码的原始意图。

答案 1 :(得分:7)

如果测试已经到位,我只会重构它。如果没有,通常不值得花时间为重构编写测试工作代码。

答案 2 :(得分:6)

这是一个小而小的反模式,但它让我感到恼火,每当我找到它时,我立即将其删除。在C(或C ++或Java)中

if (p)
    return true;
else
    return false;

变为

return p;

在Scheme中,

(if p #t #f)

变为

p

和ML

if p then true else false

变为

p

我认为这个反模式几乎完全是由本科生编写的代码。我肯定没有做到这一点 !!

答案 3 :(得分:5)

每当我遇到它并且我不认为改变它会导致问题(例如我能够理解它,我知道它做了什么。例如,伏都教的水平很低)。

答案 4 :(得分:3)

对于简单的重构,我尝试清理深层嵌套的控件结构和非常长的函数(超过一个屏幕的文本)。然而,没有充分理由重构代码并不是一个好主意(特别是在一个庞大的开发团队中)。一般来说,除非重构能够在代码中做出重大改进或修复一个令人震惊的罪行,否则我会试着单独留下足够好的东西。

不是每次说重构,而只是作为一般内务管理的问题,当我开始处理模块时,我通常会做这些事情:

  • 删除愚蠢的评论
    • 只是说功能签名已经说过的评论
    • 纯粹白痴的评论,如“看起来像什么”
    • 文件顶部的更改日志(我们有版本控制的原因)
    • 任何与代码明显不同步的API文档
  • 删除已注释掉的代码块
  • 添加版本控制标签,如$ Id $,如果缺少
  • 修复空白问题(这可能会令其他人烦恼,因为即使您所做的只是更改空白,您的名字也会在差异中出现很多行)
    • 删除行尾的空白
    • 更改标签 - >空格(这是我工作的惯例)

答案 5 :(得分:3)

如果还有其他原因我正在修改代码,我只会费心去改变它。

我愿意接受它取决于我有多自信,我不会破坏任何东西以及我自己对代码的更改有多广泛。

答案 6 :(得分:3)

这是一个展示单元测试优势的好方法。

如果有单元测试,开发人员可以勇敢而积极地重构他们可能遇到的奇怪编写的代码。如果它通过了单元测试并且你提高了可读性,那么你已经完成了当天的好事,并且可以继续前进。

如果没有单元测试,简化充满巫术的复杂代码会带来破坏代码的巨大风险,甚至不知道你引入了新的错误!因此,大多数开发人员将采取谨慎的方式并继续前进。

答案 7 :(得分:1)

通常我不会重构代码,如果我只是浏览它,而不是积极地处理它。

但有时ReSharper会指出一些我无法抗拒Alt + Enter的东西。 :)

答案 8 :(得分:1)

我几乎总是将> 2个类似的条件分解成一个开关...最常见的是关于枚举。我会缩短回报而不是长篇陈述。

例如:

if (condition) {
  //lots of code
  //returns value
} else {
  return null;
}

变为:

if (!condition)
  return null;

//lots of code..
//return value
早期分解会减少额外的缩进,并减少长代码...同样作为一般规则我不喜欢超过10-15行代码的方法。我喜欢具有单一目的的方法,即使在内部创建更多私有方法。

答案 9 :(得分:1)

超过(可以说)三到四行重复代码总是让我想到重构。此外,我倾向于大量移动代码,将我预测更频繁使用的代码提取到一个单独的位置 - 一个具有明确目的和责任的类,或一个静态类的静态方法(通常放在my Utils。* namespace)。

但是,要回答你的问题,是的,很多情况下,使代码更短并不一定意味着使它具有良好的结构和可读性。在C#中使用 ?? 运算符是另一个例子。您还需要考虑的是您选择的语言中的新功能 - 例如LINQ可以用来以非常优雅的方式做一些事情,但也可以使一个非常简单的事情非常难以理解并且过于复杂。你需要非常仔细地权衡这两件事,最后归结为你的个人品味,主要是体验。

嗯,这是另一个“它取决于”的答案,但我担心它必须是。

答案 10 :(得分:1)

如果重构使代码很多更容易阅读,对我来说最常见的是重复代码,例如if / else只有第一个/最后一个命令不同。

if($something) {
  load_data($something);
} else {
  load_data($something);
  echo "Loaded";
  do_something_else();
}

答案 11 :(得分:0)

为了它而进行重构是所有邪恶的根源之一。请不要这样做。 (单元测试确实可以缓解这个问题。)

答案 12 :(得分:0)

我只会重构我遇到的代码,并且在执行以下步骤后我没有积极处理:

  • 与代码的作者交谈(并不总是可能)来弄清楚那段代码的作用。即使我对这段代码的作用很明显,但总是有助于理解作者为什么决定以某种方式做某事的理由。花几分钟谈论它不仅有助于原作者理解你的观点,还可以在团队中建立信任。
  • 知道或找出这段代码正在做什么,以便在重新分解后进行测试(单元测试的构建过程在这里非常有用。它使整个过程快速而简单)。在更改之前和之后运行单元测试,确保没有因为您的更改而中断。
  • 向团队发送消息(如果与他人合作)让他们知道即将发生的变化,以便在实际发生变更时没有人感到惊讶

答案 13 :(得分:0)

如果我理解了一组块的输入和输出,我倾向于重构很长的函数和方法。

这有助于提高可读性。

答案 14 :(得分:0)

大量注释掉的代码是反模式吗?虽然不是具体的代码,(它的评论)我看到很多这种行为与那些不了解如何使用源代码控制的人,以及谁想要保留旧代码以便以后,以便他们可以更容易回去,如果一个bug被引入。每当我看到被注释掉的大量代码时,我几乎总是将它们全部删除。

答案 15 :(得分:0)

我尝试根据以下因素进行重构:

  1. 我是否了解足以了解最新情况?
  2. 如果此更改破坏了代码,我是否可以轻松恢复。
  3. 如果它破坏了构建,我是否有足够的时间来恢复更改。
  4. 有时,如果我有足够的时间,我会重构学习。因为,我知道我的改变可能会破坏代码,但我不知道在哪里以及如何。所以我无论如何都要改变它,以找出其破裂的原因和原因。这样我就可以了解有关代码的更多信息。

    我的域名一直是移动软件(手机),其中大部分代码都驻留在我的电脑上,不会影响其他人。由于我还为我的公司维护CI构建系统,我可以在重构的代码上运行完整的产品构建(针对所有手机),以确保它不会破坏其他任何东西。但这就是我个人的奢侈品,你可能没有。

答案 16 :(得分:0)

如果它们被视为低重构风险,我倾向于重构全局常量和枚举。也许它只是,但像ClientAccountStatus枚举这样的东西应该在ClientAccount类中或接近ClientAccount类,而不是在GlobalConstAndEnum类中。

答案 17 :(得分:0)

删除/更新明显错误或明显毫无意义的评论 删除它们是:

  1. 安全
  2. 版本控制意味着您可以再次找到它们
  3. 提高了他人和您自己的代码质量
  4. 这是我所知道的唯一100%无风险重构。

    请注意,在结构化注释中执行此操作(如javadoc注释)是另一回事。更改这些不是无风险的,因此它们很可能可能被修复/删除,但不会因为标准的错误代码注释而死亡。