如何处理错误的代码
作为一名开发人员,在我整天的生活中遇到的最不愉快的事情之一就是我必须修复错误或将特性添加到糟糕的代码中。 现在,作为一名优秀的工匠,我希望将代码保持在比我find的更好的状态。 如果我不重构devise,通常不能实现新function。 那么 – 他们可以,但这会使代码变得更糟。
不幸的是,这正是我所面对的难题。 我觉得如果有一件事很难,那就是重构糟糕的代码,特别是当你有最后期限的时候。 触及不好的和复杂的代码,或多或less的作品是可怕的。 因此,当我在代码中修改一个新function而不修改现有代码时,会引入更多混乱。
现在我的问题是我怎样才能学会处理不好的代码? 我怎样才能学会理解庞大的代码库,然后重构其中的一部分而不破坏那些已经工作并且没有超过最后期限的东西? 有什么文献可以推荐? 你有什么一般的秘诀吗?
Michael Feathers准确地写了一本关于这个题目的好书。
有效地使用遗留代码 。
另一本很棒的书是由Martin Fowler,Kent Beck等人撰写的:
重构:改进现有代码的devise 。
一般提示:
if (it is working) Do (not touch it); else { Make (as few modifications as possible) Or (it will stop working at all); }
这是几代人的经验。
重构需要unit testing套件的安全性,以消除“我打破了它? 感觉。 在一堆testing中覆盖不好的代码将会帮助你,同时努力寻找干净的代码。
Pex是一个我觉得有用的工具(如果你在.NET世界中)创build遗留代码的testing。
旧版代码==没有testing的代码!
善良,
担
当我不得不处理添加坏代码的function时,我通常的做法是:
- 为每个必须工作的重要function编写自动化testing(因为大多数错误代码没有任何testing)。
- 做代码更改。
- 确保testing仍在工作。
这给了你至less一些信心,你没有破坏一切。 至于如何学习应对不好的代码,我想这只是经验。
那么,如果你要在项目中重构大量的代码,我build议使用一些体面的版本控制,这样你就可以轻松地分支和回退。 鉴于,这可能是一个开放的门,但关键的伊莫。
而且,在开始复杂的OO之前,请尝试将方法和function分解为更小的OO。 确保每个function的一定程度的primefaces性,使代码更易于维护,阅读和pipe理。 这是关于小东西,把它分解成逻辑运算单元,我正在做一个1k线方法的重构动作。 它有一些花哨的东西。 我的第一个目标是从小块中获得尽可能多的东西,当这样做的时候,我会开始考虑一个更好的面向对象的devise,这更容易,因为我对事物有更好的把握。
阿司匹林也很好。
我目前在这种情况下。 我的方法是在触摸代码之前回答一些问题:
- 代码真的很糟糕吗? 如果是的话,常见的错误是什么? ==>也许专注于那些第一
- 代码中的主要运行时stream程是什么? 也许你可以从它丢弃不less的构造。
- 尝试对代码进行分层/模块化,而不改变代码。 这导致一些相互依赖性的减less
- 尝试用testing戳代码。 如果代码库纠结在希望之外:使用类似PowerMock的东西来模拟那些还没有(需要)改变的对象
- 有一个可用的集成环境,您可以在此环境中testing生产环境中的更改。
- 不要回避重写代码库的一部分。 但是不要尝试太多的新东西
- 尝试组队,讨论devise,原则,解决scheme
这是艰苦的工作,没有人会感谢你。 以小改进为荣,享受完美的工作:)
我认为,总体来说,您正在开发/改进的软件中的所有工作都是一样的。 这就是devise文档和其他文档在开发过程之后或开发过程中产生的地方。我相信如果之前有人没有做好正确的文档,那么至less你应该在你的开发过程中写下几行关于你经历的内容。 我通常使用OneNote或其他东西来写关于我遇到的东西的笔记,通常会列出我觉得需要重构的东西。 如果在项目过程中出现停机时间,我通常会回到这个列表,并尝试改善一点一滴的东西。
所以基本上,如果你之前的某个人没有做对,那么至less你可以帮助减less其他开发者碰到相同代码的问题。
重构:改进现有代码的devise
这取决于一些因素,但最重要的是如果你有权力修改它。
如果你这样做,重构它。 例如,重命名类/函数/variables。 提取和概括function。 请参阅重构: 改进现有代码的devise (关于主题的圣经)。 在开始之前,确保代码处于正确的版本控制(VC)中,并且有一组好的testing用例。 VC让你回滚和testing案例有助于捕捉意想不到的副作用。
我build议像Mercurial / Bazaar和Git这样的分布式版本控制,因为它非常重构的结构不像增加特性那样。
如果没有testing(普通),则必须创build它们。 使用遗留代码阅读工作有效 。 特别是关于“密封点”(不是关于连体猫:p)。
如果你不创build一个更清洁的包装API。
例如:
Old code ==================== const ACT_SHOW = 'show'; const ACT_HIDE = 'hide'; function int DoThing(Object $Obj, Stirng $Action, Object $Param1, Object $Param1) { ....; } Added code ================== enum Actions { show, hide; }; class ActionDoer { private obj; ActionDoer($Object) { this.obj = $Object; } function int act(Actions $Action, $Param1, $Param1) { this.act($Action.toString(), $Param1, $Param1) ; } function int act(String $Action, $Param1, $Param1) { DoThing(this.obj, $Action, $Param1, $Param1) ; } function int show() { this.act(Actions.show, null, null); } function int hide(Color $ToBGColor, long $FadeTime) { this.act(Actions.hide, $ToBGColor, $FadeTime); } }
这样,旧的代码不会被触及,扩展可以使用新的代码来完成。 这种方法的好例子是jQuery,其中访问DOM的旧(默认)方法是痛苦的。
希望这可以帮助。