让知识连接你我
投稿赚钱
当前位置: 首页 > 职场生活 > @程序员,该如何接手别人遗留下的代码?
  • 101
  • 微信分享

    扫一扫,在手机上查看

@程序员,该如何接手别人遗留下的代码?

2019.01.16 10:00 286 浏览 举报

  如果你在软件行业工作足够长的时间,迟早你都将面临个棘手的问题:修复遗留的代码库。本文所提出的并不是唯可行的方法,且遗憾的是,这种方法并不是众所周知的。不过以下内容保证风险最小化。假设你遇到了修复遗留应用程序的问题,已经存在风险,并且不需要添加更多应用程序。采用本文方法的风险和成本将会比从头开始重写更低。

  在我们开始之前,你应该先了解些事项。首先,请阅读这篇 joel spolsky 的著名文章,了解为什么永远不应该重写代码。在这篇文章中,spolsky 强调了为什么要重构代码库而不是重写代码库。所谓重构,即在不改变行为的情况下对代码质量进行系列逐步改进的过程。当你尝试修复代码时,同时更改其结构和行为是自寻麻烦。

  话虽如此,但我觉得“永远”词有些言重。假设你的代码是用 unibasic 编写的,而如今你已找不到该语言的人员(包括愿意学习它的人),那么重写是你唯的选择。或者,如果你使用的是个影响较小的小软件,重写可能并不那么危险。

  但是,假设你可以轻松找到或者培训人员使用当前软件的编程语言,并且该软件的意义举足轻重,而且它的代码库非常庞大,那么重写就不是那么有意义了。重构意味着你的代码直都在,你不会丢弃业务知识,而你的人员不必从头开始写代码,可以快速出成果。换句话说,你可以将风险降至最低。

  理虽如此,但是依然有很多公司和者选择重写。新代码令人兴奋,有望带来新的机遇。新代码很有趣,但修复旧代码通常被视为苦差事。但是,如果你有个庞大的遗留代码库,并且你编写的新代码是个大型项目,而大型项目的风险很高:

  it 权威机构 standish group 在1995年的项研究表明,只有大约17%的 it 项目被认为是“完全成功的”,52%属于“勉强合格”(没有达到预算、质量或时间目标),30%是“失败的”。最近,standish 对2003年至2012年期间的3555个 it 项目进行了调研,这些项目的总成本至少为1000万美元,而仅有6.4%的 it 项目成功。

  尽管这项调研时间有些久远,但它仍然适用于当今 it 世界。项目越大,风险也越大。事实上,在我参与的各种公司的大型项目中,很少有人能够在预算范围内按时完成项目。有些项目会被彻底取消,由于没人愿意承担失败的责任,因此他们将项目拖延很久,这完全就是场灾难。比如,原本计划年完成的项目已经四年都未能完成,目前仍然充满了漏洞和设计缺陷,并且该软件向后兼容,因此只能硬着头皮继续做。该公司能够继续运转的唯原因在于,他们收购了另家具有盈利能力的公司。

  这个例子暗示了个行业中没有公开的小秘密:大规模的重写通常会将堆乱糟糟的代码换成另堆。这些公司并未真正解决潜在的问题,而是用系列已知的问题替换了系列未知的问题。如果你需要修复遗留代码,那是因为你需要将风险降至最低;为什么你会故意采用无法量化的风险?

  如何重构遗留代码

  假设你不想面对大规模重写带来的成本和风险,那么如何重构代码呢?

  首先,你需要对当前项目进行评估,至少包含以下方面:

  代码的功能需求是什么?

  如果有文档的话,具体有哪些?

  通过跟踪 bug,了解哪部分代码更脆弱。

  依赖的外部资源有哪些?

  如果已做了的话,具体包含哪些。

  所有这些都需要写下来,以便任何人都可以目了然地查阅这些信息。假如你要雇用专家来收拾这个烂摊子,这些信息则是重要的必需品。如果上面的列表看起来过于简单,那是因为我们正在重构,而不是重写。

  是的,你可能会聘请位外部专家。如果当前项目的人员无法制定修复遗留代码库的可靠计划,同时最大限度地降低风险,那么你需要聘请位在该领域有丰富经验的人,他们不仅会看到你无法看到的问题,还可以让目前的人员变得更好。以下内容无法做到完全直观,但专家的经验能够帮助你摆脱困境。你的专家至少需要满足以下条件:

  你的代码库使用的主要编程语言的专家

  强大的自动化背景

  熟练使用代码覆盖率工具

  熟知数据库

  设计和架构专家

  能够自责自省

  了解业务需求

  能够说服别人

  最后几点似乎很奇怪,但的确非常重要。流的人员很难兼具以上能力,因此很值得花钱去寻找这样的专家。

  开始

  首先,你得大致清楚如何规划你的应用程序。也就是所谓的架构路线图,但请记住,该路线图比较灵活,它会随着时间的推移而发生变化。这也正是需要架构专家介入的原因。应用程序的各个功能应当被拆分为单独的部分,以确保应用程序的各个部分都具有其专注的领域。当应用程序的每个部分都有其专注领域时,它就更容易维护、扩展和重用,这也是我们想要修复遗留代码库的主要原因。但是,这阶段最好不要制定太过详细的计划;相反,只需确保你对大方向有个粗略的认识即可。

  接下来,你将像吃大象样点点重构你的应用程序。你将选择个小的初始目标来熟悉新工具。随着时间的推移,它会变得更容易,但是当你最开始使用时,切不要操之过急。

  重构个大型应用程序意味着需要编写,但除非你非常清楚知道自己在做什么,否则你很可能会出错。通常很少使用 tdd,代码已经写好了,你很难为所有代码都编写。相反,你应当采用集成。

  你需要做的第件事是了解应用程序中不会改变的东西。也就是应用程序的输出,无论是通过 json api、网站、soap 接口还是其它什么方式输出结果都不会改变。由于某些东西必须使用该软件,因此它可以使切运转起来。你需要为其编写集成。假设我们正在重构 web 应用程序,你已决定首先编写以验证是否可以在页面上列出用户。

  在该中,你将创建个浏览器对象,以员用户身份登录,获取用户页面,并编写把预期的用户显示在该页面上。想要实现这些功能通常需要你做大量的工作。例如,如何获取连接到数据库的代码?如何确保之间的数据隔离(换句话说,运行的顺序无关紧要)?如何创建浏览器对象?当你真正动手时,你需要回答这些问题,以及更多其它的问题。

  如果你已经进行了些,那么可能会更容易实现这点,如果你没有进行其它那就会非常困难,但这是重构非常重要的第步。

  旦你针对接口的个相对较小的不变部分进行了第次集成,就可以在中运行代码覆盖率工具,以查看这些高级集成所涵盖的代码。涵盖的代码通常是可以安全重构的代码。

  现在,你可以查看应用程序的哪些功能部分嵌入到经过的代码中,并制定计划将这些部分移到你的架构路线图中。此时,我们要避免把切分散开来。相反,我们应该每次只专注个点。例如,如果你在整个代码中分散了 sql,请将其提取到你的架构路线图中,以便拥有个干净的 api 来处理你需要的数据。又或者你有个 web 应用程序,而你直采用直接打印 html 的方式,请尝试使用模板并开始将 html 整合到模板中。不要次修复所有东西,否则你会不堪重负。相反,你应当关注个领域并充分理解。

  不做单元

  请注意,我们直在讨论集成,而不是单元。这有个很好的理由:对于遗留的大规模重构,当你刚开始重构时单元模块会发生很大的变化,但集中在静态接口上的集成则不会。你想花时间重构你的应用程序,而不是你的,所以在你稳定代码内部工作之前,单元可能会分散你的注意力。集成的优势在于,你可以次覆盖大部分代码,如果正确完成,可以非常快速地编写。此外,对于结构不良的应用程序,单元可能很难执行。集成还有助于发现单元无法发现的错误:不同组件具有不同期望的错误。但是,集成也存在些缺点:

  集成比单元运行得慢

  很难追查 bug

  如果没有很好地隔离代码,那么集成更容易造成

  话虽如此,在这个阶段集成的优势很明显:当你有些基本的来防止最坏的错误时,重构会容易得多。同样值得注意的是,如果你在此之前很少甚至没有做,如果你有些可靠的,就不会那么糟糕。

  如果你还没有实现持续集成(ci),那么现在是时候开始了。即使你的人员忘记运行,你的 ci 也不应该。如果失败,你需要快速找到答案。

  进阶

  在你开始重构了的小部分功能之后,你可能很快会发现原始计划中的些错误。没关系,你已经开始小规模重构,以尽量减少风险。纠正这些错误,开始使用代码覆盖率工具对的其它小部分进行集成,以及你已经在处理的功能部分(数据库调用、html 或者其它部分)。如果你觉得自己已经摆脱了些最糟糕的问题,那么请开始查看的另个功能,即当前的代码共享,看看是否可以解决这个问题。

  请注意,这正是专家的架构技能将会发挥作用的地方。他们将理解解耦应用程序采用不同功能部分的重要性。他们将了解如何编写健壮且灵活的界面。他们将学会识别业务逻辑中可以抽象出来的模式。不要把这个责任交给现有的程序员,除非你绝对相信他们拥有完成这项工作所需的技能和经验。

  接下来就是重复这些方法,在最坏的情况下可能需要数年才能完成。这需要很长时间,但它有着显着的优点:

  代码始终能够正常工作

  你无需为同时维护两个而付费

  业务知识不会丢失

  仍然可以添加新功能

  可以轻松编写针对现有 bug 的(即使你尚未重构该代码)

  旦发现你的代码库“足够好”了,随时都可以收工

  为什么这种方法有效?任何大型项目看起来都令人生畏,但通过将其分解为更小且更易于的部分,你至少可以知道从哪里开始并了解目标,而不必担心大型项目的失败。

  当我以前使用这种技术时,我经常发现自己能够更清楚地了解代码是如何发展的,而且当前经验丰富的团队并没有面对看到他们的工作消失的令人沮丧的前景。这种技术的缺点是,虽然代码质量大大提高,但总有种感觉,它不够好。然而,正如我之前提到的,许多重写仅仅会产生新的设计缺陷以取代旧的缺陷。这太常见了,它意味着将已知问题换成未知问题。

  总结

  上述策略并不能得到所有人的认可,对于那些崇尚新事物的人来说很难接受。事实上,在许多方面它可以被视为无聊(虽然我喜欢重构代码),但我已经成功地在多个遗留代码库中使用了这种方法。但是,如果你仍在尝试从重写与重构之间做出决定,请记住,这种方法是种成本相对较低且风险也较低的方法。如果它被证明是行不通的,你可能会冒很小的风险。如果改写证明不可行,那么你可能会花费公司大笔钱。

  因此,你应当明白何时应该考虑修复遗留代码库。我建议你未雨绸缪。修复遗留代码库虽不如送火箭上天般高难度,但它确实需要定程度的专业知识来转换现有的代码库。遗憾的是,大多数人员似乎对此技能并不感兴趣,他们似乎也并不想处理遗留代码库。


本文首次发布于开创者素材 ,转载请注明出处,谢谢合作!

相关文章推荐