标签: refactoring

何时(如果有的话)废弃生产代码并重新开始?

我被要求进行代码审查并报告在我们的新产品中添加新功能的可行性,这是我迄今尚未亲自处理过的新产品.我知道很容易挑选别人的代码,但我会说它的形状很糟糕(尽量尽可能客观).我的代码审查中的一些亮点:

  • 滥用线程: QueueUserWorkItem和线程一般使用很多,而线程池代表有无信息的名称,如PoolStartPoolStart2.线程之间也缺乏适当的同步,特别是访问除UI线程之外的线程上的UI对象.

  • 幻数和魔术字符串:代码中定义了一些ConstEnum它们,但是大部分代码都依赖于字面值.

  • 全局变量:许多变量被声明为全局变量,可能会也可能不会被初始化,具体取决于所遵循的代码路径以及发生的顺序.当代码也在线程之间跳转时,这会变得非常混乱.

  • 编译器警告:主解决方案文件包含500多个警告,总数不为我所知.我从Visual Studio收到警告,它无法再显示警告.

  • 半完成的课程:代码已经处理并添加到这里和那里,我认为这导致人们忘记了之前所做的事情,所以有一些看似半完成的类和空的存根.

  • 未在此处发明:该产品复制了其他产品使用的公共库中已存在的功能,例如数据访问助手,错误记录助手和用户界面助手.

  • 关注点分离:当我们阅读有关典型的"UI - >业务层 - >数据访问层"3层架构时,我认为有人正在颠覆这本书.在此代码库中,UI层直接访问数据库,因为业务层部分实现但由于未充分充实而被忽略,并且数据访问层控制UI层.大多数低级数据库和网络方法都在对主窗体的全局引用上运行,并直接显示,隐藏和修改窗体.在实际使用相当薄的业务层的情况下,它也倾向于直接控制UI.大多数这种低级代码也使用MessageBox.Show发生异常时显示错误消息,并且大多数吞下原始异常.这当然使得在尝试重构之前开始编写单元测试来验证程序的功能有点复杂.

我只是在这里表面上看,但我的问题很简单:花时间重构现有的代码库,一次关注一个问题,或者你会考虑从头开始重写整个事情是否更有意义?

编辑:为了澄清一点,我们确实有项目的原始要求,这就是为什么重新开始可能是一个选项.另一种表达我的问题的方法是:代码能否达到维持成本的成本大于倾销和重新开始的成本?

refactoring

52
推荐指数
10
解决办法
4589
查看次数

自定义Eclipse重构的预览出错

我正在实施一个新的eclipse重构.这将使开发人员能够将preconditions语句从子方法提取到父方法.

当我在重构向导中选择"完成"时,这一切都很完美,但是当我选择"预览"时,我收到错误"没有提供目标编辑".这似乎是由TextEdit返回的问题引起的ASTRewrite.rewriteAST().但是我无法弄清楚为什么.

我的Refactoring.createChange()代码运行后发生异常的堆栈跟踪,并且更改用于生成预览.

org.eclipse.text.edits.MalformedTreeException: No target edit provided.
at org.eclipse.text.edits.MoveSourceEdit.performConsistencyCheck(MoveSourceEdit.java:208)
at org.eclipse.text.edits.TextEdit.traverseConsistencyCheck(TextEdit.java:873)
at org.eclipse.text.edits.MoveSourceEdit.traverseConsistencyCheck(MoveSourceEdit.java:183)
at org.eclipse.text.edits.TextEdit.traverseConsistencyCheck(TextEdit.java:869)
at org.eclipse.text.edits.TextEdit.traverseConsistencyCheck(TextEdit.java:869)
at org.eclipse.text.edits.TextEditProcessor.checkIntegrityDo(TextEditProcessor.java:176)
at org.eclipse.text.edits.TextEdit.dispatchCheckIntegrity(TextEdit.java:743)
at org.eclipse.text.edits.TextEditProcessor.performEdits(TextEditProcessor.java:151)
at org.eclipse.ltk.core.refactoring.TextChange.getPreviewDocument(TextChange.java:534)
at org.eclipse.ltk.core.refactoring.TextChange.getPreviewDocument(TextChange.java:403)
at org.eclipse.ltk.core.refactoring.TextChange.getPreviewContent(TextChange.java:411)
at org.eclipse.ltk.internal.ui.refactoring.TextEditChangePreviewViewer.setInput(TextEditChangePreviewViewer.java:209)
at org.eclipse.ltk.internal.ui.refactoring.AbstractChangeNode.feedInput(AbstractChangeNode.java:99)
at org.eclipse.ltk.internal.ui.refactoring.PreviewWizardPage.showPreview(PreviewWizardPage.java:598)
at org.eclipse.ltk.internal.ui.refactoring.PreviewWizardPage.access$6(PreviewWizardPage.java:583)
at org.eclipse.ltk.internal.ui.refactoring.PreviewWizardPage$7.selectionChanged(PreviewWizardPage.java:574)
at org.eclipse.jface.viewers.Viewer$2.run(Viewer.java:162)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
at org.eclipse.core.runtime.Platform.run(Platform.java:888)
at org.eclipse.ui.internal.JFaceUtil$1.run(JFaceUtil.java:48)
at org.eclipse.jface.util.SafeRunnable.run(SafeRunnable.java:175)
at org.eclipse.jface.viewers.Viewer.fireSelectionChanged(Viewer.java:160)
at org.eclipse.jface.viewers.StructuredViewer.updateSelection(StructuredViewer.java:2132)
at org.eclipse.jface.viewers.StructuredViewer.setSelection(StructuredViewer.java:1669)
at org.eclipse.jface.viewers.TreeViewer.setSelection(TreeViewer.java:1124)
at org.eclipse.jface.viewers.Viewer.setSelection(Viewer.java:392)
at org.eclipse.ltk.internal.ui.refactoring.PreviewWizardPage.setVisible(PreviewWizardPage.java:505)
at org.eclipse.ltk.internal.ui.refactoring.RefactoringWizardDialog2.makeVisible(RefactoringWizardDialog2.java:762)
at org.eclipse.ltk.internal.ui.refactoring.RefactoringWizardDialog2.showCurrentPage(RefactoringWizardDialog2.java:477)
at org.eclipse.ltk.internal.ui.refactoring.RefactoringWizardDialog2.nextOrPreviewPressed(RefactoringWizardDialog2.java:507)
at org.eclipse.ltk.internal.ui.refactoring.RefactoringWizardDialog2.access$2(RefactoringWizardDialog2.java:492)
at org.eclipse.ltk.internal.ui.refactoring.RefactoringWizardDialog2$1.widgetSelected(RefactoringWizardDialog2.java:691)
at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:228) …
Run Code Online (Sandbox Code Playgroud)

java eclipse refactoring eclipse-plugin

52
推荐指数
1
解决办法
2205
查看次数

如何在Python代码中找到未使用的函数?

所以你在一个相当沉重的项目中有一些遗留代码.如何查找和删除死函数?

我已经看到了这两个引用:查找未使用的代码工具来查找php项目中未使用的函数,但它们似乎分别特定于C#和PHP.

是否有一个Python工具可以帮助您找到源代码中其他地方未引用的函数(尽管有反射/等)?

python refactoring dead-code

51
推荐指数
3
解决办法
1万
查看次数

Mongoose - 如果不存在则创建文档,否则,在任何一种情况下都更新 - 返回文档

我正在寻找一种方法来重构我的部分代码,使其更短更简单,但我不太了解Mongoose,我不知道如何继续.

我正在尝试检查一个集合是否存在文档,如果它不存在,则创建它.如果确实存在,我需要更新它.在任何一种情况下,我都需要访问文档的内容.

到目前为止我设法做的是查询特定文档的集合,如果找不到,则创建一个新文档.如果找到它,我会更新它(当前使用日期作为虚拟数据).从那里我可以访问我的初始find操作中找到的文档或新保存的文档,这可行,但必须有一个更好的方法来完成我所追求的.

这是我的工作代码,没有分散注意力.

var query = Model.find({
    /* query */
}).lean().limit(1);

// Find the document
query.exec(function(error, result) {
    if (error) { throw error; }
    // If the document doesn't exist
    if (!result.length) {
        // Create a new one
        var model = new Model(); //use the defaults in the schema
        model.save(function(error) {
            if (error) { throw error; }
            // do something with the document here
        });
    }
    // If the document does exist
    else {
        // Update it …
Run Code Online (Sandbox Code Playgroud)

javascript refactoring mongoose node.js

50
推荐指数
2
解决办法
5万
查看次数

标记所有不修改const的变量是否有任何缺点?

经过大量的谷歌搜索后,我发现了很多关于标记函数及其参数的内容const,但没有关于标记变量的指南const.

这是一个非常简单的例子:

#include <string>
#include <iostream>

void example(const std::string& x) {
  size_t length = x.length();
  for (size_t i = 0; i < length; ++i) {
    std::cout << x.at(i) << std::endl;
  }
}

int main() {
  example("hello");
}
Run Code Online (Sandbox Code Playgroud)

为什么不做

size_t length = x.length();
Run Code Online (Sandbox Code Playgroud)

const喜欢

const size_t length = x.length();
Run Code Online (Sandbox Code Playgroud)

按照惯例?

我知道这么小的一个简单的例子确实没有给这个带来任何巨大的好处,但它似乎对于一个更大的代码库有帮助,你可能会意外地改变你不应该变异的变量.

尽管有这样的好处,但我并没有真正看到它使用那么多(在我见过的C++代码库中)或者提到的几乎和函数及其参数一样多const.

除了必须输入5个额外字符外,还有一些缺点吗?我在这个话题上找不到太多东西,如果这是一个有这么多争议的问题,我不想在脚下射击.

c++ refactoring const

50
推荐指数
4
解决办法
1957
查看次数

你容忍多少重复的代码?

在最近的一次代码审查中,我在一个类中发现了几行重复​​逻辑(少于15行).当我建议作者重构代码时,他认为代码更容易理解.在再次阅读代码后,我不得不同意提取重复的逻辑会稍微损害可读性.

我知道DRY是指南,而不是绝对的规则.但总的来说,你是否愿意以DRY的名义伤害可读性?

refactoring coding-style dry code-duplication

49
推荐指数
5
解决办法
1万
查看次数

Intellij Extract Inner Class

如何使用IntelliJ或Android Studio提取公共静态内部类来创建新的顶级类?

谢谢.

refactoring intellij-idea inner-classes android-studio

49
推荐指数
1
解决办法
7917
查看次数

函数/过程/方法应该有多少行代码?

可能重复:
函数何时太长?

我最近得到了一个不值得羡慕的任务,即审查另一个开发人员编写的糟糕代码并记录不良做法.(当然,这都是出于为开发人员的工作付出代价而不是任何无私的理由!)

经过审核的代码有几行代码,其中包含多行代码 - 最长的代码是600行.我想到的几个问题是可维护性和可读性.

诀窍在于我需要为一个外行人辩护,为什么这是一个不好的做法,如果可能的话,用一本备受好评的当前参考书备份它.类比也很好.

有任何想法吗?

重复: 函数何时太长?
重复: 最大功能大小的最佳规则?

refactoring coding-style function code-metrics

48
推荐指数
4
解决办法
4万
查看次数

如何应对不良代码

作为开发人员,我在一整天的生活中遇到的最令人不快(也是最不常见的)情况之一就是我必须修复错误或在设计糟糕的代码中添加功能.现在作为一个优秀的工匠,我想让代码保持比我发现的更好的状态.如果我不重构设计,通常无法实现新功能.嗯 - 他们可以,但这会使代码更糟糕.

不幸的是,这正是我经常遇到的困难.我觉得如果有一件事情很难,那就是重构坏代码,尤其是在你有最后期限的情况下.触及或多或少工作的糟糕而复杂的代码是可怕的.因此,当我在代码中修改新功能而不修改现有代码时,我会引入更多的混乱.

现在我的问题是我如何学会应对不良代码?我怎样才能学会理解巨大的代码库,然后在不破坏已经工作且不超过截止日期的情况下重构其中的部分代码?你有没有可以推荐的文献?你有什么一般的提示吗?

refactoring

47
推荐指数
5
解决办法
5913
查看次数

我如何重构这个循环?

我有一个应用程序,我使用原始数组和列表称为Item.由于遗留原因,这些可以互换使用(我也希望这只是一种类型,但它就是这样).

现在我必须添加一个像这样的新方法,通过for-each循环:

public void something(Item... items) {
    for (Item i : items) {
        doStuff();
    }
}

public void something(List<Item> items) {
    for (Item i : items) {
        doStuff();
    }
}
Run Code Online (Sandbox Code Playgroud)

换句话说,对于原始数组和列表,两次完全相同的方法.有没有办法很好地将它重构为一个方法?

java refactoring

47
推荐指数
2
解决办法
4025
查看次数