糟糕系统设计的代码重构

我是一名初级软件工程师,他接受了接管旧系统的任务。 根据我的初步评估,该系统存在一些问题。

  1. 意大利面条代码
  2. 重复的代码
  3. 10k及以上的课程
  4. 使用log4j进行滥用和过度记录
  5. 糟糕的数据库表设计
  6. 缺少源代码控制 – >我为此设置了Subversion
  7. 缺少文档 – >除了阅读代码之外,我不知道业务规则

我该怎么做才能提高系统质量并解决这些问题? 我可以考虑使用静态代码分析软件来解决任何不良编码实践。

但是,它无法检测到任何不良的设计问题或问题。 我该如何逐步解决这些问题?

首先关注稳定性。 在应用程序周围存在某种稳定的环境之前,您无法增强或重构。

一些想法:

  1. 修订控制 。 你已经开始设置颠覆了。 现在确保您的数据库模式,存储过程,脚本,第三方组件等也在版本控制之下。 有一个版本标签系统,请确保标记版本,并可以在将来准确访问旧版本。
  2. 构建和发布 。 有办法在dev机器以外的机器上构建稳定版本。 您可能希望使用ant / nant,make,msbuild,甚至是批处理文件或shell脚本。 如果不存在,您可能还需要部署脚本/安装程序。
  3. 得到它的测试 。 在您有办法知道您的更改是否已破坏之前,请勿更改应用程序。 为此你需要测试。 您应该希望能够为一些更简单的独立类编写xunitunit testing,但是尝试构建一些系统/集成测试来整体运行应用程序。 没有高代码覆盖率(您不必开始)集成测试是您最好的选择。 养成尽可能经常运行测试的习惯。 抓住一切机会扩展它们。
  4. 进行小的,专注的变化 。 尝试识别应用程序中的系统/子系统,并改善它们之间的界限。 这可以减少您可能进行的更改的连锁效应。 要注意通过重新格式化或强加最新的时尚设计模式来“漂亮”代码的诱惑。 扭转这样的系统需要时间
  5. 文档 。 它是必要的,但不要太担心它。 在我的经验中很少使用系统文档。 好的测试通常比良好的文档更好。 专注于记录应用程序与其运行的系统上下文(输入,输出,文件结构,数据库模式等)之间的接口。
  6. 管理期望 。 如果它处于糟糕的状态,那么它可能会抵制你做出改变的努力,而且时间尺度可能比平常更难估计。 确保管理层和利益相关者理解这一点

不惜一切代价,要注意重写整件事的诱惑。 在这种情况下,它几乎从来不是正确的事情。 如果它有效,请集中精力保持其正常工作。

作为初级开发人员,不要害怕寻求帮助。 正如其他人所说, 有效地使用遗留代码是一本很好的书,正如Martin Fowler的Refactoring一样

祝你好运!

获取并阅读有效使用旧版代码的工作 。 它完全处理这种情况。

正如其他人也建议的那样,对于重构,你需要一套可靠的unit testing。 但是,遗留代码通常很难进行unit testing,因为它尚未编写为可unit testing的。 因此,您需要首先重构以允许unit testing,这将允许您开始重构…一个糟糕的捕获。

这本书将帮助您。 它提供了许多关于如何使用最小和最安全的代码更改来设计设计糟糕的代码单元的实用建议。 自动重构也可以帮助你,但书中描述的技巧只能手工完成。 然后,一旦第一组unit testing到位,您就可以开始逐步重构更好,更易于维护的代码。

更新:有关如何接管遗留代码的提示,您可能会发现我之前的这个答案很有用。

正如@Alex所指出的,unit testing对于理解和记录代码的实际行为也非常有用。 当关于系统的文档不存在或过时时,这尤其有用。

首先,不要修复未破坏的东西。 只要您要接管的系统工作,只留下function。

然而,在可维护性方面,系统显然被打破了,所以这就是你要解决的问题。 如上所述,首先编写一些测试,然后在cvs中备份源代码,然后首先清理小块,然后是较大的块,依此类推。 在您充分了解系统的工作原理之前,请不要攻击更大的架构问题。 只要您不自己深入研究代码,工具就无法帮助您,但是当您这样做时,它们会帮助很多。

记住,没有什么是“完美的”。 不要过度工程。 遵守KISS和YAGNI原则。

EDIT:添加了直接链接到YAGNI文章

你的问题#7是迄今为止最重要的问题。 只要您不知道系统应该如何表现 ,所有技术考虑都是次要的。 每个人都在建议进行unit testing – 但如果你无法区分有用和无用的行为,你如何编写有用的测试?

因此,在开始触摸代码之前,您必须从用户的角度理解系统:与用户交谈,使用系统观察它们,在用例级别编写文档。

是的,我认真地建议你花几天时间,更可能是几周,而不需要改变一行代码。 因为现在,你做出的任何改变很可能会在没有你意识到的情况下破坏它。

一旦了解了应用程序,您至少会知道哪些function对测试很重要(手动或自动)。

先写一些unit testing,并确保它们通过。 然后,随着每次重构更改,只需继续确保测试不断通过。 然后,您可以确信您对外界的应用程序行为没有改变。

这还有一个额外的好处,即测试将始终存在,因此对于任何未来的更改,测试仍应通过,以防止新更改中的任何回归。

首先,确保安装源代码控制系统,并且所有源代码都已经过版本化并且可以构建。

接下来,您可以尝试为系统的核心部分编写unit testing。 从那里,当你有一个或多或少坚实的回归测试体,你可以实际进行重构。

当我遇到凌乱的代码库时,我通常会首先重命名命名不佳的类型和方法,以更好地反映其初始意图。 接下来,您可以尝试将大型方法拆分为较小的方法。

请记住,这个遗留系统及其所有的意大利面条代码目前都可以使用。 不要因为看起来不那么美观而改变事物。 在将旧代码从左右中心翻录出来之前,请注重稳定性,新function和熟悉程度。

首先,请允许我说, 有效地使用遗留代码可能是一本非常好的书,可以在一分钟之内通过三个答案来判断。

  1. 糟糕的数据库表设计

这一个,你可能会被困住。 如果您尝试更改现有数据库设计,则可能需要重新设计整个系统为现有数据编写迁移工具。 别管。

我对这个问题的标准答案是: 重构低调的果实 。 在这种情况下,我倾向于选择其中一个10K线课程并寻找Sprout Class的机会,但这只是我自己的倾向; 你可能更愿意首先改变其他东西(设置源代码控制是一个很好的第一步!)测试你能做什么; 重构无法测试的东西,一步一步,让它变得更好。

请记住,随着你的进步,你做得更好; 如果你只专注于有多糟糕的事情,你可能会变得气馁。

正如其他人所指出的那样,不要改变那些只是为了让它更漂亮的东西。 您将引入错误的风险很大。

我的理念是:由于我必须进行更改以满足新的要求或修复报告的错误,我尝试使我必须更改的代码更清洁一些。 无论如何,我将不得不测试更改的代码,所以现在是以较小的额外成本进行一些清理的好时机。

基本的设计变更是最难的,必须保存在必须进行足够大的更改以至于无论如何都要测试所有更改的代码的情况下。

改变糟糕的数据库设计是最难的,因为许多程序可能会使用设计不佳的表。 对数据库的任何更改都需要更改每个读取或写入它的程序。 实现此目的的最佳方法通常是尝试减少访问数据库任何给定部分的位置数。 举一个简单的例子:假设有20个地方可以读取客户记录并计算客户账户余额。 将此替换为一个读取数据库并返回总数的函数,以及对该函数的二十次调用。 现在您可以更改客户记录的模式,只需要更改一段代码而不是20。原理很简单,但实际上访问给定记录的每个函数都不太可能做同样的事情。 即使原来的程序员笨拙地写了相同的代码20次(不是不可能 – 我已经看到了很多),真实的情况可能不是他写了20次函数,期间,但他写了函数A 20次,functionB 12次,functionC 4次等。

有效地使用旧版代码可能会有所帮助。

设计问题很难掌握。 首先要了解应用程序的设计。 我发现使用UML或流程图对图表有用,任何可以传达设计和为应用程序工作的工作。

从那里我进入更多的细节,并问自己问题“我会这样做”,还有其他选择。 很容易看到代码债务,即我们从做出错误选择中得到的债务,总是很糟糕,但有时还会涉及其他因素,如预算,时间,资源的可用性等。他们你必须提出问题,如果它值得重构一个有效但设计糟糕的应用程序。

如果有许多即将推出的新function,更改,错误修复等,我会说重构很好,但如果应用程序很少更改并且稳定,那么可能将其保留为更好的方法。

需要注意的另一个方面是,如果代码被另一个应用程序用作服务或模块,那么重构可能首先意味着在服务器作为接口的代码周围创建一个存根,一旦明确定义并具有unit testing来certificate它工作。 您可以选择任何技术来填写详细信息。

关于这一主题的好书是有效地使用遗产代码作者Michael Feathers(2004)。 它经历了一个小的变化过程,同时努力进行更大的清理。

  1. 编写unit testing并查找并删除重复的代码。
  2. 将unit testing和断开长方法写入一系列简短方法。
  3. 写unit testing和查找并删除重复的方法。
  4. 编写unit testing和分解课程,以遵循单一责任原则 。

首先尝试创建一些可以触发代码中某些操作的unit testing。

提交SVN和TAG中的每一个(如果出现问题,你将有一个逃生舱)。

使用inCode Eclipse插件http://www.intooitus.com/inCode.html并查看它提出的重构。 检查建议的重构是否适合您的问题。 试着去理解它们。

使用之前创建的单位重新测试。

现在,您可以使用FindBugs和/或PMD来检查其他细微问题。

如果一切都是oka,您可能需要再次办理登机手续。

我还尝试阅读源代码,以便检测可以应用模式的一些情况。