糟糕系统设计的代码重构

ilo*_*arn 23 java refactoring legacy-code

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

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

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

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

Pét*_*rök 16

获取并阅读有效使用旧版代码的工作.它完全符合这种情况.

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

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

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

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

  • 测试它以了解其行为.它不仅可以让您自信地进行更改,而且其他程序可能依赖于当前系统中的BUGS! (9认同)

小智 14

首先,不要修复未破坏的东西.只要你要接管的系统工作,只留下功能.

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

记住,没有什么是"完美的".不要过度工程.遵守KISSYAGNI原则.

EDIT: 添加了与YAGNI文章的直接链接


And*_*son 14

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

一些想法:

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

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

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

祝好运!


Mic*_*rdt 8

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

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

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

一旦了解了应用程序,您至少会知道哪些功能对于测试(手动或自动)非常重要.


Noe*_*l M 6

首先写一些单元测试,并确保它们通过.然后,每做一次重构更改,只需继续确保测试不断通过.然后,您可以确信您对外部世界的应用程序行为没有改变.

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

  • @liangteh,如果你不了解业务规则,你可以编写表征测试来验证当前存在的功能.编写失败的测试,观察失败的测试并修改测试以传递当前代码库.这不会告诉您代码是否正常工作,但它会告诉您正在进行的更改是否正在改变行为. (3认同)