我是一名初级软件工程师,我的任务是接管旧系统。根据我的初步评估,这个系统有几个问题。
- 意大利面条代码
- 重复代码
- 10k 行及以上的类
- 使用 log4j 的误用和过度记录
- 糟糕的数据库表设计
- 缺少源代码控制 -> 我为此设置了 Subversion
- 缺少文件 -> 我不知道业务规则,除了阅读代码
我应该如何去提高系统的质量并解决这些问题?我可以考虑使用静态代码分析软件来解决任何不良的编码实践。
但是,它无法检测到任何不良的设计问题或问题。我应该如何逐步解决这些问题?
我是一名初级软件工程师,我的任务是接管旧系统。根据我的初步评估,这个系统有几个问题。
我应该如何去提高系统的质量并解决这些问题?我可以考虑使用静态代码分析软件来解决任何不良的编码实践。
但是,它无法检测到任何不良的设计问题或问题。我应该如何逐步解决这些问题?
获取并阅读使用旧代码有效地工作。它正好处理这种情况。
正如其他人也建议的那样,对于重构,您需要一组可靠的单元测试。然而,遗留代码通常很难按原样进行单元测试,因为它还没有被编写成可单元测试的。因此,您需要首先进行重构以允许单元测试,这将允许您开始重构……这是一个不好的问题。
这就是本书将帮助你的地方。它提供了许多实用建议,说明如何通过最少且最安全的代码更改使设计不佳的代码单元可测试。自动重构在这里也可以为您提供帮助,但是书中描述的一些技巧只能手动完成。然后,一旦第一组单元测试到位,您就可以开始逐步重构,以获得更好、更易维护的代码。
更新:有关如何接管遗留代码的提示,您可能会发现我的这个较早的答案很有用。
正如@Alex 所指出的,单元测试对于理解和记录代码的实际行为也非常有用。当有关系统的文档不存在或过时时,这尤其有用。
首先关注稳定性。在应用程序周围有某种稳定的环境之前,您无法增强或重构。
一些想法:
不惜一切代价,谨防重写整个内容的诱惑。在这种情况下,它几乎从来都不是正确的做法。如果它有效,请集中精力使其正常工作。
作为初级开发人员,不要害怕寻求帮助。正如其他人所说,《有效地使用遗留代码》是一本好书,就像 Martin Fowler 的《重构》一样。
祝你好运!
您的问题 #7 是迄今为止最重要的。只要您不知道系统应该如何运行,所有技术考虑都是次要的。每个人都在建议进行单元测试——但是如果你不能区分想要的行为和不需要的行为,你怎么能写出有用的测试呢?
所以在你开始接触代码之前,你必须从用户的角度来理解系统:与用户交谈,观察他们使用系统,编写用例级别的文档。
是的,我认真地建议你花几天,甚至几周,而不改变一行代码。因为现在,您所做的任何更改都可能在您没有意识到的情况下破坏事情。
了解应用程序后,您至少会知道哪些功能对测试很重要(手动或自动)。
首先编写一些单元测试,并确保它们通过。然后,随着您所做的每一次重构更改,只要继续确保测试继续通过即可。这样您就可以确信您的应用程序对外界的行为没有改变。
这还有一个额外的好处,即测试将始终存在,因此对于未来的任何更改,测试仍应通过,以防止新更改中的任何回归。
首先,确保您安装了源代码控制系统,并且所有源代码都已版本化并且可以构建。
接下来,您可以尝试为系统的核心部分编写单元测试。从那里开始,当您有或多或少的回归测试体时,您实际上可以继续进行重构。
当我遇到混乱的代码库时,我通常会从重命名名称不佳的类型和方法开始,以更好地反映它们的初始意图。接下来,您可以尝试将大型方法拆分为较小的方法。
请记住,这个带有意大利面条代码的遗留系统目前可以正常工作。不要仅仅因为它们看起来不那么漂亮就去改变它们。在将旧代码从左到右和中心剥离之前,请关注稳定性、新功能和熟悉度。
首先,让我说有效地使用遗留代码可能是一本非常值得阅读的书,从一分钟内的三个答案判断。
- 糟糕的数据库表设计
这个,你可能被困住了。如果您尝试更改现有的数据库设计,您可能会承诺重新设计整个系统并为现有数据编写迁移工具。别管闲事。
我对这个问题的标准答案是:重构低悬的果实。在这种情况下,我倾向于参加 10K 线课程之一并寻找机会参加Sprout Class,但这只是我自己的倾向;您可能会更愿意先更改其他内容(设置源代码管理是一个很好的第一步!)测试你能做的;重构无法测试的东西,一步一步,让它变得更好。
请记住,随着您的进步,您做得更好;如果你只关注事情还有多糟糕,你很可能会变得灰心。
正如其他人所指出的,不要为了让它更漂亮而改变一些有用的东西。引入错误的风险很大。
我的理念是:因为我必须进行更改以满足新需求或修复报告的错误,所以我尝试使我必须更改的代码片段更简洁。无论如何,我将不得不测试更改后的代码,所以现在是进行少量清理的好时机。
基本的设计更改是最困难的,必须保存以备需要进行足够大的更改以测试所有更改的代码的情况。
改变糟糕的数据库设计是最难的,因为设计糟糕的表可能被许多程序使用。对数据库的任何更改都需要更改读取或写入它的每个程序。实现这一点的最佳方法通常是尝试减少访问数据库任何给定部分的位置的数量。举个简单的例子:假设有20个地方读取客户记录,计算客户账户余额。将此替换为一个读取数据库并返回总数的函数,以及对该函数的二十次调用。现在您可以更改客户记录的架构,并且只需要更改一段代码而不是 20 段。原理很简单,但实际上访问给定记录的每个函数不太可能都在做同样的事情。
关于这个主题的一本好书是 Michael Feathers 的《有效地使用遗留代码》(2004 年)。它经历了进行小改动的过程,同时努力进行更大的清理。
有效地使用遗留代码可能会有所帮助。
设计问题很难发现。首先要了解应用程序的设计。我发现使用 UML 或流程图绘制图表很有用,任何可以传达设计和为应用程序工作的东西都可以。
从那里我进入更多细节,并问自己“我会这样做吗”的问题,还有哪些其他选择。很容易看到代码债务,即我们从做出错误选择中得到的债务,一如既往地糟糕,但有时还涉及其他因素,如预算、时间、资源可用性等。你必须问这个问题是否值得重构一个工作但设计不佳的应用程序。
如果有许多即将推出的新功能、更改、错误修复等,我会说重构是件好事,但如果应用程序很少更改并且稳定,那么保持原样可能是更好的方法。
另一个需要注意的问题是,如果代码被另一个应用程序用作服务或模块,那么重构可能首先意味着围绕服务器作为接口的代码创建一个存根,一旦它被明确定义并有单元测试来证明它工作。您可以选择任何技术来填写详细信息。
首先尝试创建一些可以触发代码中的某些操作的单元测试。
在 SVN 中提交所有内容并标记它(如果出现问题,您将拥有一个逃生舱)。
使用 inCode Eclipse 插件http://www.intooitus.com/inCode.html并寻找它提出的重构。检查建议的重构是否适合您的问题。试着理解他们。
使用之前创建的单元重新测试。
现在您可以使用 FindBugs 和/或 PMD 来检查其他细微问题。
如果一切正常,您可能需要再次办理登机手续。
我还会尝试阅读源代码以检测某些可以应用模式的情况。