Questions tagged «refactoring»

重构是一种用于重组现有代码主体,在不更改其外部行为的情况下更改其内部结构的有纪律的技术。

7
如何将代码重构为一些通用代码?
背景 我正在进行中的C#项目。我不是C#程序员,主要不是C ++程序员。因此,我基本上被分配了简单的重构任务。 该代码是一团糟。这是一个巨大的项目。由于我们的客户要求频繁发布具有新功能和错误修复的程序,因此所有其他开发人员在编码时都被迫采取暴力手段。该代码极难维护,所有其他开发人员都同意。 我不是在这里辩论他们是否做对了。在重构时,我想知道我是否以正确的方式进行操作,因为重构后的代码似乎很复杂!这是我作为简单示例的任务。 问题 有六类:A,B,C,D,E和F。所有的类都有一个功能ExecJob()。所有六个实现都非常相似。基本上,起初A::ExecJob()是写的。然后需要一个稍有不同的版本,该版本B::ExecJob()通过对的复制粘贴修改进行实现A::ExecJob()。当需要另一个略有不同的版本时,C::ExecJob()编写此类代码。所有六个实现都有一些通用代码,然后有一些不同的代码行,再有一些通用代码,依此类推。这是实现的一个简单示例: A::ExecJob() { S1; S2; S3; S4; S5; } B::ExecJob() { S1; S3; S4; S5; } C::ExecJob() { S1; S3; S4; } SN一组完全相同的语句在哪里。 为了使它们通用,我创建了另一个类并将通用代码移到函数中。使用参数控制应执行的语句组: Base::CommonTask(param) { S1; if (param.s2) S2; S3; S4; if (param.s5) S5; } A::ExecJob() // A inherits Base { param.s2 = …

7
如果流利的编码员无视良好做法,那么他的流利程度对他不利吗?[关闭]
已关闭。这个问题是基于观点的。它当前不接受答案。 想改善这个问题吗?更新问题,以便通过编辑此帖子以事实和引文回答。 4年前关闭。 我正在开发一个相当大且有错误的应用程序-由于它的编写方式(我将为您提供详细信息,但是在您可以想到的大多数领域中它都违反了规则),如果不进行重大重构就几乎不可能开发它。 该应用程序的重要部分是由实习生,n00bs等创作的;但是在高级开发人员中也有一个程序员,尽管谦卑,但他留下的代码也是可疑的,也许还是以不同的方式。 当然,他的代码往往会在大多数时间完成工作,但通常是很隐秘的,需要重新发明轮子(例如,使用大型自定义方法来完成相当普通的SQL db备份)等。基本上,不必要的混乱以及大量的过度设计 让我想到,如果不是其他素质的陪伴者,作为一名高技能的编码员(我故意不使用“开发人员”一词,假设它表示更多的技能)实际上可能是有毒的。 假设这是真的,我能想到的一些原因是: 如果您轻松编写代码,则感觉(或实际上实际上是短期内)可以更快地就地找到自己的解决方案,而无需使用库,既有功能等。 如果有足够的经验来轻松维护复杂程序的心理形象,则不太倾向于将其拆分为模块,层等。 因此,我的观点是,如果一个流利的编码人员恰好是一个不良的开发人员,那么他们的流利性不仅不能弥补后者的不足,反而会带来更大的危害。 你对那个怎么想的?是真的吗(如果有,程度如何)?

10
如何修复复制/粘贴模式?
在我工作的地方,人们(顾问)感到迫切需要尽快发布功能。因此,不必花太多时间去思考如何正确地做事,或者因为他们不想破坏任何东西,而是从不同的模块复制并修改代码。 要防止这种情况并不容易,因为代码库对整个公司都是开放的。很多人为此工作。 既然现在已经一团糟,那么在不破坏太多冗余的情况下删除这些冗余的最佳方法是什么?

7
我应该重构主要由一个正则表达式组成的大型函数吗?[关闭]
已关闭。这个问题是基于观点的。它当前不接受答案。 想改善这个问题吗?更新问题,以便通过编辑此帖子以事实和引用的形式回答。 5年前关闭。 我刚刚编写了一个跨越约100行的函数。听到这个消息,您可能很想告诉我有关单一责任的事,并敦促我进行重构。这也是我的直觉,但这是问题所在:函数做一件事。它执行复杂的字符串操作,并且函数主体主要由一个详细的正则表达式组成,分为许多行,并记录在案。如果我将正则表达式分解为多个功能,我会感觉实际上会失去可读性,因为我正在有效地切换语言,并且无法利用正则表达式提供的某些功能。现在是我的问题: 在使用正则表达式进行字符串操作时,大型函数体是否仍然是反模式?似乎命名捕获组的作用与功能非常相似。顺便说一下,我对通过正则表达式的每个流进行测试。

5
为什么要为将要重构的代码编写测试?
我正在重构一个巨大的遗留代码类。重构(我认为)主张: 为遗留类编写测试 摆脱困境 问题:一旦我重构了类,就需要更改步骤1中的测试。例如,以前是旧方法中的东西,现在可能是一个单独的类。一种方法现在可能是几种方法。遗留类的整个景观可能被抹杀为新的东西,因此我在步骤1中编写的测试几乎是无效的。本质上,我将添加步骤3。大量重写我的测试 那么重构之前编写测试的目的是什么?这听起来更像是为自己创造更多工作的学术活动。我现在正在为该方法编写测试,并且正在学习有关如何测试事物以及旧方法如何工作的更多信息。可以通过阅读旧代码本身来学习这一点,但是编写测试几乎就像在摸摸我的鼻子,并且在单独的测试中记录这种临时知识。因此,以这种方式,我几乎别无选择,只能学习代码在做什么。我在这里说的是暂时的,因为我会从代码中重构出乱七八糟的东西,并且我的所有文档和测试在很大程度上都是无效的,除非我的知识会留下来并使我对重构更加新鲜。 这是重构之前编写测试的真正原因-帮助我更好地理解代码吗?还有另一个原因! 请解释! 注意: 有一篇文章:没有时间进行完全重构时,为遗留代码编写测试是否有意义?但是它说“重构之前先写测试”,但没有说“为什么”,或者说“写测试”看起来像“很快就会被销毁的繁忙工作”该怎么办。

2
我应该使用工厂方法而不是构造函数。我可以更改它并且仍然向后兼容吗?
问题 假设我有一个名为的类DataSource,它提供了ReadData一种从.mdb文件中读取数据的方法(也许还有其他方法,但为了简单起见): var source = new DataSource("myFile.mdb"); var data = source.ReadData(); 几年后,我决定.xml除了.mdb文件作为数据源之外,还希望能够支持文件。.xml和.mdb文件的“读取数据”实现完全不同。因此,如果我要从头开始设计系统,则可以这样定义: abstract class DataSource { abstract Data ReadData(); static DataSource OpenDataSource(string fileName) { // return MdbDataSource or XmlDataSource, as appropriate } } class MdbDataSource : DataSource { override Data ReadData() { /* implementation 1 */ } } class XmlDataSource …

6
如何确定“代码改进”的优先级和严重性?
我们的错误跟踪系统中有“优先级”和“严重性”字段。我们将严重性定义为“它如何影响用户”,将优先级定义为“它如何影响产品”。 我的问题是关于如何按照严重性和优先级对“代码改进”任务进行分类。假设改进不会改变任何行为,而是使其成为“更好的代码”。我们预计总体上将获得长期的维护改进,但是很难量化。 当我们将定义用于优先级和严重性时,除非您在图片中引入一些难以预测的长期收益,否则代码改进将使这两个值均达到最低值。因此,这意味着代码改进是一项艰巨的任务,切勿尝试。 但是,我认为不断改进和重构代码至关重要,因为: 软件开发本身就是一个持续的学习过程,如果不对代码进行改进,就无法做得更好。 团队应该为自己的代码感到自豪。 未来的维护将花费更少的时间,从长远来看,节省的费用将是可观的。 还是您认为不应创建此类任务,而只能在“按需”,“与错误关联时”执行此类改进?即使它与错误相关联,这也不是代码审查的讨论重点,例如“为什么您要在结构上进行如此大的改变?”。

10
建议进行大的更改/将其重写为实习生[关闭]
关闭。这个问题是题外话。它当前不接受答案。 想改善这个问题吗? 更新问题,以使它成为软件工程堆栈交换的主题。 4年前关闭。 上下文: 这是一个内部项目(我认为很多人都不会使用) 很老了 我们正在更新 问题: 它滥用了mvc框架(不使用模型,视图中的业务逻辑等) 我们被要求做的事情很小,但是由于凝聚力低,我们有两种选择: 继续捣蛋 移动大量代码或重写事物 解决方案(我看到): 继续使用它,忽略最佳实践,而希望尽快完成,并且不通过重构/重写来引入新的错误 重构/重写 我想我的问题确实是:如果我想对该项目进行较大的更改,该如何提出建议而不侮辱任何人?还是对我来说简单地顺应潮流,即使有时意味着(隐喻)导管胶带?

11
在进行其他操作时,是否应该修复先前存在的缺陷?
难题:在使用新功能或修复缺陷的过程中,您会在代码中发现遗留问题。你该怎么办?对其进行修复,并有可能改变代码的行为。直到现在为止,由于某种偶然原因,它一直在工作,或者还没有发现缺陷,或者值得任何人报告。您是否应该不理会它,并允许该问题使以后的代码难以使用?解决问题只会增加原始任务的时间,并迫使您进行回归测试。很少有人会欣赏这项工作。但是,以某种方式修复它似乎正确。问题较少的代码更易于重构和构建。 当我们致力于使Web应用程序现代化时,我一次又一次地发现自己处于这种情况。当我不切实际地处理这些旧错误时,我无法分辨自己是痴迷还是光荣。您如何处理这些情况? 谢谢,科里

3
大量构建一种实现。DI无望吗?使用服务定位器?
假设我们有1001个客户端,它们直接构造其依赖关系,而不接受注入。根据我们的老板,重构1001不是一个选择。实际上,甚至不允许我们访问其源代码,而只能访问类文件。 我们应该做的是“现代化”这1001个客户所经历的系统。我们可以重构自己喜欢的一切。依赖关系是该系统的一部分。还有一些依赖关系我们应该更改为具有新的实现。 我们想要做的是能够配置依赖关系的不同实现,以满足众多客户的需求。可悲的是,DI似乎不是一个选择,因为客户端不接受构造函数或setter的注入。 选项: 1)重构客户端使用的服务的实现,以使其执行客户端现在需要的功能。砰,我们完成了。不灵活。不复杂。 2)重构实现,以便将其工作委托给它通过工厂获取的另一个依赖项。现在,我们可以通过重构工厂来控制它们都使用哪种实现。 3)重构实现,以便将其工作委托给它通过服务定位器获取的另一个依赖项。现在,我们可以通过配置服务定位器来控制它们都使用哪种实现,该服务定位器可能只是hashmap对象的字符串,并且需要进行一些强制转换。 4)我什至没有想到的东西。 目标: 在不增加毫无意义的复杂性的情况下,将因设计欠佳的旧客户端代码拖到将来而导致的设计损失最小化。 客户不应该了解或控制其依赖项的实现,但是他们坚持使用来构建它们new。我们无法控制,new但可以控制他们正在构建的类。 我的问题: 我没有考虑什么? Doc Brown的问题 您是否真的需要在不同的实现之间进行配置?出于什么目的? 敏捷。很多未知数。管理层希望变革的潜力。只失去对外界的依赖。还测试。 您是否需要运行时机制或只是编译时机制来在不同的实现之间进行切换?为什么? 编译时间机制可能就足够了。除测试外。 您需要在实现之间切换哪种粒度?一次全部?每个模块(每个模块包含一组类)?每堂课? 在1001中,任何一次都只能运行一次。一次更改所有客户端使用的内容可能很好。但是,对依赖项的单独控制可能很重要。 谁需要控制开关?只有您/您的开发人员团队?管理员?每个客户自己吗?还是客户的代码的维护开发人员?那么,机械师需要多么容易/稳健/万无一失? 开发测试。管理员随着外部硬件依赖性的变化而变化。它需要易于测试和配置。 我们的目标是证明该系统可以快速重建和现代化。 实施开关的实际用例? 一种是,在硬件解决方案准备就绪之前,一些数据将由软件提供。

7
防御样板?
对我来说,样板代码显然是不好的。但是我遇到了一个开发人员,他在减少样板方面表现出了抵制。我意识到,随着时间的流逝,我对这种厌恶情绪还没有形成,经过深思熟虑的论点。 为了使我能够形成一个令人信服的理由,即主张减少样板,有哪些反对意见?换句话说,支持样板的论点是什么(如果有)? (我的意思是我通常认为是样板程序,但是一个很好的例子是Java中的getter和setter方法。)

10
解决已知错误后,其他地方可能会出现新错误的原因是什么?
在讨论中,我的一位同事告诉他,在尝试解决错误时,他目前的项目有些困难。他说:“当我解决一个错误时,其他地方就会停止工作。” 我开始考虑如何发生,但无法弄清楚。 当我太累/困得无法正确执行工作并无法全面了解正在处理的代码部分时,有时会遇到类似的问题。在这里,问题似乎持续了几天或几周,与我同事的关注点无关。 我也可以想象这个问题是在一个非常大的项目,一个管理不善的项目中引起的,在这个项目中,队友不知道谁在做什么,而对其他人的工作有什么影响可以改变他们正在做的事情。这里也不是这样:这是一个只有一个开发人员的相当小的项目。 对于旧的,维护不善且从未记录过的代码库,这也可能是一个问题,只有真正能够想象变更后果的开发人员才在几年前离开了公司。在这里,该项目才刚刚开始,开发人员不使用任何人的代码库。 那么,由一个专注于自己的工作的开发人员编写的全新的,小型代码库中的此类问题可能是什么原因呢? 有什么帮助? 单元测试(没有)? 正确的体系结构(我很确定代码库根本没有体系结构,并且编写时没有任何初步思考),需要整个重构吗? 配对编程? 还有吗

3
您如何导航和重构以动态语言编写的代码?
我喜欢编写Python,Ruby或Javascript所需的模板很少。我喜欢简单的功能构造。我喜欢简洁的语法。 但是,在使用动态语言开发大型软件时,我确实很不擅长三件事: 浏览代码 识别我正在使用的对象的接口 有效重构 我一直在尝试使用简单的编辑器(例如Vim)以及IDE(Eclipse + PyDev),但在两种情况下,我都觉得我必须对内存进行更多的投入和/或不断地“ grep”并仔细阅读代码以识别接口。当使用具有多个依赖项的大型代码库时,尤其如此。 至于重构,例如更改方法名称,它在很大程度上取决于我的单元测试的质量。而且,如果我尝试通过“切断”应用程序的其余部分来隔离我的单元测试,则不能保证存根的接口与存根的对象保持最新。 我确定有解决这些问题的方法。您如何在Python,Ruby或Javascript中高效地工作?

4
没有明显抽象的代码重复
您是否曾经遇到过代码重复的案例,在这种情况下,在查看代码行时,您无法对其进行专题描述以忠实地描述其在逻辑中的作用?您做了什么处理呢? 这是代码重复,因此理想情况下,我们需要进行一些折光处理,例如使其具有自己的功能。但是由于代码没有一个很好的抽象来描述它,所以结果将是一个奇怪的函数,我们甚至无法为其找到一个好名字,而且从逻辑上看,它在逻辑中的作用并不明显。对我来说,这损害了代码的清晰度。我们可以保留清晰度并保持原样,但随后会损害可维护性。 您认为解决此类问题的最佳方法是什么?

3
您如何安全地重构具有动态范围的语言?
对于那些有幸不使用动态范围内的语言的人,让我稍微介绍一下它的工作原理。想象一下一种伪语言,称为“ RUBELLA”,其行为如下: function foo() { print(x); // not defined locally => uses whatever value `x` has in the calling context y = "tetanus"; } function bar() { x = "measles"; foo(); print(y); // not defined locally, but set by the call to `foo()` } bar(); // prints "measles" followed by …

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.