我们的代码很糟糕,我无力修复它。帮助!
我们的代码很糟糕。事实上,让我澄清一下。我们的旧代码很糟糕。它很难调试,并且充满了很少有人理解甚至记住的抽象概念。就在昨天,我花了一个小时在我工作了一年多的领域进行调试,发现自己在想,“哇,这真的很痛苦。”这不是任何人的错——我确信这一切一开始都是完全合理的。最糟糕的部分通常是它只是有效......只要你不要求它做任何超出其舒适区的事情。
我们的新代码非常好。我认为我们在那里做了很多好事。它是清晰的、一致的并且(希望)可维护的。我们已经有一个正在运行的 Hudson 服务器用于持续集成,并且我们已经开始了单元测试套件。问题是我们的管理层专注于编写新代码。没有时间为旧代码(甚至旧的新代码)提供它迫切需要的 TLC。在任何特定时刻,我们的 Scrum 积压工作(针对 6 名开发人员)都有大约 140 个项目和大约 12 个缺陷。这些数字并没有太大变化。我们以尽可能快的速度添加东西。
那么我该怎么做才能避免陷入旧代码深处的马拉松式调试会话的麻烦呢?每一次冲刺都充满了新的发展和令人惊叹的缺陷。具体来说......
- 我可以做些什么来帮助维护和重构任务获得足够高的优先级来进行工作?
- 您是否采用了任何特定于 C++ 的策略来帮助防止新代码如此快速地腐烂?
Our code sucks. Actually, let me clarify that. Our old code sucks. It's difficult to debug and is full of abstractions that few people understand or even remember. Just yesterday I spent an hour debugging in an area that I've worked for over a year and found myself thinking, "Wow, this is really painful." It's not anyone's fault - I'm sure it all made perfect sense initially. The worst part is usually It Just Works...provided you don't ask it to do anything outside of its comfort zone.
Our new code is pretty good. I think we're doing a lot of good things there. It's clear, consistent, and (hopefully) maintainable. We've got a Hudson server running for continuous integration and we have the beginnings of a unit test suite in place. The problem is our management is laser-focused on writing New Code. There's no time to give Old Code (or even old New Code) the TLC it so desperately needs. At any given moment our scrum backlog (for six developers) has about 140 items and around a dozen defects. And those numbers aren't changing much. We're adding things as fast as we can burn them down.
So what can I do to avoid the headaches of marathon debugging sessions mired in the depths of Old Code? Every sprint is filled to the brim with new development and showstopper defects. Specifically...
- What can I do to help maintenance and refactoring tasks get high enough priority to be worked?
- Are there any C++-specific strategies you employ to help prevent New Code from rotting so quickly?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
您的管理层可能会专注于将工作功能添加到产品中并保持其正常工作。在这种情况下,您将需要提出一个重构旧东西的业务案例,因为通过投入 X 的时间和精力,您可以在 Z 期间将必要的维护时间减少 Y。或者您的管理层可能根本上一无所知(这种情况发生,但比大多数开发人员想象的要少),在这种情况下你永远不会获得许可。
你需要从商业角度来看。对于最终用户来说,代码丑陋还是优雅并不重要,重要的是软件的功能。糟糕代码的代价是潜在的不可靠性以及更改代码的额外困难;它给程序员带来的情绪困扰很少被考虑。
如果您无法获得进入并重构的许可,您始终可以自己尝试,一次一点点。每当您修复错误时,请进行一些重写以使事情更清晰。这可能比最小可能的修复速度更快,特别是在验证代码现在是否有效时。即使不是,通常也可以多花一点时间来修复错误,而不会遇到麻烦。只是不要得意忘形。
如果你每次进入时都能把代码做得更好一点,你就会感觉好很多。
Your management may be focused on getting working features into the product, and keeping them working. In this case, you will need to make a business case for refactoring the old stuff, in that by X investment of time and effort you can reduce necessary maintenance time by Y over period Z. Or your management may be fundamentally clueless (this happens, but less often than most developers seem to think), in which case you'll never get permission.
You need to see the business point of view. It doesn't matter to the end user whether the code is ugly or elegant, only what the software does. The cost of bad code is potential unreliability and additional difficulty in changing it; the emotional distress it causes to the programmer is rarely considered.
If you can't get permission to go in and refactor, you can always try it on your own, a little bit at a time. Whenever you fix a bug, do a little rewriting to make things clearer. This may turn out to be faster than the minimum possible fix, particularly in verifying that the code now works. Even if it isn't, it's usually possible to take a little more time on a bug fix without getting into trouble. Just don't get carried away.
If you can leave the code just a little better each time you go in, you'll feel a lot better about it.
站立会议
我可能会去找我的机械师,我们早上有一个小型站立会议:
这些都不是我想听到的。我想听到我会在半小时内开车离开那里,车轮、轮胎和机油都已完成。
我的机械师对我非常坦率和诚实。 您对管理层是否诚实?或者您是否避免告诉他们他们不想听的事情?
单元测试
我不会碰一行我不理解的代码,也不会签入一行我没有彻底测试的新代码。 (至少,不是故意的。)
您的问题似乎暗示,不知何故,一大堆记录不良的代码使其在没有任何单元测试的情况下通过了审查。也许你参与了,也许你没有。每个相关人员都需要为此承担责任——包括管理层。无论如何,该做的已经做了。你不能回去改变它。
然而,现在,每个人都有责任停止导致问题的行为。您说您花了一年的时间编写您发现难以理解且没有单元测试的代码。那一年,当您努力提高理解时,您编写了多少单元测试来记录并验证这种理解?
当您努力通过代码慢慢获得理解时,您写了多少注释添加这样你下次就不用再挣扎了?
Scrum Backlog
就我个人而言,我认为“Scrum backlog”这个术语用词不当。要做的事情的清单只是一个清单——如果你愿意的话,可以说是一个购物清单。当我去找机械师时,我有一份清单。我与机械师的站立会议实际上更像是一次冲刺计划会议。
冲刺计划会议是一次谈判。如果你的管理层在没有进行谈判的情况下限制时间,那么他们就什么也管理不了。他们只是想把 10 磅的粪便塞进 5 磅的袋子里,你有责任告诉他们这一点。
当您参加冲刺计划会议时,您应该致力于一系列工作,并且您有责任为此做好准备。准备意味着了解完成列表中的每一项需要做什么——包括理解晦涩代码所需的时间以及编写单元测试所需的时间。
如果有人邀请您参加一个您没有时间准备的计划会议,请拒绝该会议并建议何时重新安排,以便您有时间。
如果您有一个没有单元测试的现有代码体,并且某个功能可能会影响该代码的操作,则您需要为尽可能多的可能受影响的旧代码编写单元测试。当您承诺编写该功能时,您就承诺完成这项工作。如果这让你没有时间致力于其他功能,那就直说吧。不要致力于其他功能。
当您承诺修复缺陷时,您就承诺测试您的工作。显然,这意味着为缺陷编写单元测试。但是,如果它涉及没有单元测试的旧代码,则也意味着为尚未损坏但可能因更改而损坏的内容编写单元测试。您还将如何测试修复?
如果你的缺陷列表保持不变,那么你的团队就会在修复的同时退步。礼貌地向任何需要了解单元测试可以防止当前缺陷列表缩小的回归的人解释。
如果您因为提交了太多功能而未能编写这些单元测试,那么这是谁的责任?
重构
当您重构代码时,您必须测试所有代码,这意味着为所有代码编写单元测试它的。如果您有大量没有单元测试的代码,则必须在重构之前编写所有这些单元测试。
我建议您推迟重构,直到这些单元测试就位。同时,如果您坚持将单元测试包含在您所承诺的工作的估计中,那么最终所有这些单元测试都会在那里。然后你就可以重构了。
唯一的例外是可测试性重构。您可能会发现某些代码不是为测试而设计的,并且在创建单元测试之前您必须针对依赖项注入之类的事情进行重构。当您承诺编写需要单元测试的功能时,您就承诺使代码可测试。当您承诺使用该功能时,请将其纳入您的估算中。
承诺+责任=力量
你说你无能为力。当你接受责任并致力于做需要做的事情时,我想你会发现你拥有你需要的所有力量。
PS 如果有人抱怨有人在修复单个缺陷时“浪费时间”编写多个单元测试,请向他们展示这个关于 80:20 规则的视频,并向他们的大脑中灌输“缺陷簇”。
Stand Up Meetings
I might go to my mechanic, and we have a little stand-up meeting in the morning:
None of that is what I wanted to hear. I wanted to hear that I would drive out of there in a half hour with my wheels, tires and oil done.
My mechanic was just straight up and honest with me. Are you straight up and honest with your management? Or do you avoid telling them things they don't want to hear?
Unit Testing
I wouldn't touch a line of code I didn't understand, and I wouldn't check in a new line of code I didn't test thoroughly. (At least, not intentionally.)
Your question seems to imply that somehow a large corpus of poorly documented code made it past review without any unit tests. Maybe you participated in that, and maybe you didn't. Everyone involved needs to accept responsibility for that--including management. Regardless, what's done is done. You cannot go back and change it.
However, right now, in the present time, it is everybody's responsibility to stop the behavior that led to the problem in the first place. You say you spent a year working in code that you find difficult to understand and that has no unit tests. During that year, as you worked hard to improve your understanding, how many unit tests did you write to document and to verify that understanding?
As you struggled through the code slowly gaining understanding, how many comments did you add so you wouldn't have to struggle next time?
Scrum Backlog
Personally, I think the term "Scrum backlog" is a misnomer. A list of things to do is just a list--a shopping list if you will. I had a list when I went to the mechanic. My stand up meeting with the mechanic was really more of a sprint planning meeting.
A sprint planning meeting is a negotiation. If your management is time boxing without that negotiation, they aren't managing anything. They are simply trying to cram 10 lbs of shit into a 5 lb sack, and it's your responsibility to tell them so.
When you show up to a sprint planning meeting, you are expected to commit to a body of work, and it's your responsibility to prepare for that. Preparation means having some idea of what you will have to do to complete each item on the list--including the time it takes to understand obscure code and the time it takes to write unit tests.
If someone invites you to a planning meeting where you won't have time to prepare, decline the meeting and suggest when to reschedule so you will have time.
If you have an existing body of code with no unit tests and a feature might conceivably affect the operation of that code, you need to write unit tests for as much of the old code as might be affected. When you commit to writing the feature, you are committing to doing that work. If that leaves you too little time to commit to some other feature, just say so. Don't commit to the other feature.
When you commit to fix a defect, you commit to testing your work. Obviously, that means writing a unit test for the defect. But if it involves old code with no unit tests, it also means writing unit tests for things that aren't broken yet, but might break due to your change. How else will you test the fix?
If your defect list remains a constant size, your team regresses as much as it fixes. Politely explain to whomever needs to understand that unit tests prevent the regressions that currently keep your defect list from shrinking.
If you fail to write those unit tests because you commit to too many features, whose responsibility is that?
Refactoring
When you refactor code, you have to test all of it, and that means writing unit tests for all of it. If you have a large body of code with no unit tests, you will have to write all of those unit tests before you refactor.
I suggest you hold off on refactoring until those unit tests are in place. In the meantime, if you insist on including unit tests in your estimates for the work you commit to, eventually all those unit tests will be there. And then you can refactor.
The one exception to that is refactoring for testability. You may find that some of the code was not designed for test and that you have to refactor for things like dependency injection before you can create your unit tests. When you commit to writing the feature that requires the unit test, you commit to making the code testable. Include that in your estimate when you commit to the feature.
Commitment + Responsibility = Power
You say you are powerless. When you accept responsibility and commit to doing what needs doing, I think you will find you have all the power you need.
P.S. If anyone complains about anybody "wasting time" writing multiple unit tests when fixing a single defect, show them this video on the 80:20 rule and pound "defect clusters" into their brains.
从您提供的信息中很难看出太多内容。我的一些问题是编写新代码的逻辑原因是替换旧代码。如果这就是您正在做的事情,请放弃旧代码。
旧代码是否也存在严重缺陷?如果是的话,他们来自哪里?旧代码没有“showstopper”缺陷,它通常只是越来越接近停止。毕竟它是旧代码 - 它应该具有相同的旧缺陷和相同的旧限制,而不是必须立即查看的东西。重大缺陷是新的代码缺陷。听起来旧代码正在积极开发。
如果您在糟糕的旧代码之上编写所有这些新代码,并且不打算一劳永逸地修复它,那么抱歉,当您忙于埋头苦干而无暇挖掘自己时,您能做的就只有这么多。
如果是后者的话。你应该认清自己的前进方向,并尝试脱离一点。如果你打算留下你的力量进行一场有价值的战斗,那么一切最终都会崩溃。
同时尝试采用一些设计模式。有一些至少可以帮助您保护新代码免受旧代码的影响,但最终仍然很难编写好代码来对抗坏代码。
你的冲刺听起来可能很混乱。没有一个总体方向吗?这应该决定你有多少积压,尽管情况可能每个月都在变化,但是否没有明确的朝着某个最终目标迈进的感觉?
新代码会腐烂吗?防止这种情况发生的方法是拥有有意义的设计、有意义的方向以及致力于工作质量和设计愿景的质量团队。如果你有这样的能力,纪律就是保持质量的关键。如果您没有那么抱歉,那么您基本上已经在毫无目的地编写代码了。基本上已经烂在藤蔓上了。
不是批评,只是想诚实。深吸一口气。减速。看来你需要它。看看你在这里写了什么。它什么也没说。你谈到了重构、scrums、showstoppers、缺陷、旧代码、新代码。这意味着什么?一切都乱七八糟。
那么“新举措与遗留系统”又如何呢? “需要根据最新的理解等重构早期的冲刺周期代码。”事实上,“当前企业计划的早期组件已经发布,但遇到了问题,并且由于新的开发而没有时间预算”。
这些将是有意义的概念。你什么也没给我们。我知道这很激烈。我的冲刺也很疯狂,我们添加了很多 back;pg 项目,因为我们无法预先获得很多需求(我的很多新需求是由于还必须与外部监管机构抗衡,正常的业务流程并不总是可用)。
但与此同时,我也被必须做的事情的巨大性和完成时间所压垮。添加到我的积压工作中的所有内容都需要在那里。这很疯狂,但与此同时,我非常清楚我去过哪里,我需要去哪里,以及为什么道路变得越来越难。
退后一步,理清思绪,弄清楚同样的事情——你去过哪里,要去哪里。因为如果你知道这一点,它肯定不是显而易见的。如果你无法与同事沟通任何可以理解的内容,那么你与业务经理能走多远?
It is hard to tell much from the information you give. Some questions I would have is a logical reason to be writing new code is to replace the old code. If that is what you are doing, abandon the old code.
Is it also old code that has showstopper defects? If so where are they coming from? Old code does not have "showstopper" defects, it just grinds closer and closer to a halt usually. It is old code after all - it should have the same old defects and the same old limitations, not stuff that has to be looked at right away. Showstopper defects are new code defects. It sounds like there is active development on in the old code.
If you are writing all this new code on top of old code that sucks, with no plans to fix it once and for all, sorry, there is only so much you can do when you are too busy burying yourself to dig yourself out.
If the latter is the case. you should recognize where you are headed, and try to detach a little. It is going to all collapse eventually, if you plan on being around save your strength for a worthwhile battle.
In the meantime try to pick up some design patterns. There are several that can at least help shield you new code from the old stuff, but still, ultimately it is just hard to write good code against bad code.
And your sprints sound maybe confused. Is there not an overall direction? That should determine how much backlog you have, although things can change month to month, is there not a clear sense of moving towards some final goal?
And new code rotting? The way you prevent that is you have a meaningful design, a meaningful direction, and a quality team that is committed to both the quality of their work and the vision of the design. If you have that, discipline is what maintains quality. If you don't have that sorry, you basically were writing code with no purpose already. It was basically rotten on the vine.
Not being critical, just trying to be honest. Take a deep breath. Slow down. You seem like you need it. Look at what you have written here. It tells nothing. You talk of refactor, scrums, showstoppers, defects, old code, new code. What does any of that mean? It is all jumbled up.
What about "new initiatives versus legacy systems"? "Need to refactor early sprint cycle code in terms of latest understanding etc." Are showstoppers in fact "Early components of the current enterprise initiatives have been released but are experiencing problems and no time is budgeted because of new development".
These would be meaningful concepts. You've given us nothing. I understand it is intense. My sprints are crazy too, we add a lot of back;pg items because we could not get many requirements up front (a lot of my new requirements result from having to also contend with external regulatory bodies, the normal business process is not always available).
But at the same time I am ground down by the sheer magnitude of what has to be done and the time to do it. Everything that is added to my backlog needs to be there. It is crazy, but at the same time I have a very clear idea of where I have been, where I need to go, and why the road is getter harder.
Step back, clear your thoughts, figure out the same - where you have been and where you are going. Because if you know that, it sure is not obvious. If you cannot communicate anything your peers can understand, how far are you going to get with a business manager?
旧代码总是很糟糕。可能有一些罕见的例外是由像 Kernighan 或 Thompson 这样的人编写的,但是对于典型的“在办公室编写的代码”的东西,随着时间的推移,它会变得很糟糕。开发人员变得更有经验。持续集成等新的实践改变了游戏规则。东西被遗忘了。新的维护者无法掌握设计并希望重写。所以最好像平常一样接受这一点。
一些可能有帮助的随机事情...
总体而言,在这种情况下获胜与编码技能无关,而更多地与明智的选择和处理人性化有关。
希望有帮助。
Old code always sucks. There's probably some rare exceptions written by people with names like Kernighan or Thompson but, for the typical "code written in an office" stuff, over time it's gonna stink. Developers get more experienced. Newer practices, such as continuous integration, change the game. Stuff get's forgotten. New maintainers fail to grasp designs and wish for re-writes. So best accept this as normal.
Some random things that might help...
Overall, winning in this kind of situation is less about coding skills and much more about smart choices and handling the human aspects.
Hope that helps.
我建议跟踪有多少错误和代码更改涉及您的“旧代码”,并在下次团队会议上将其呈现给您的经理或其他开发人员。有了这个,应该很容易让他们相信需要做更多的工作来重构你的“旧代码”并使其与你的“新代码”保持一致。
谨慎地记录“旧代码”中最难理解的部分。这些也是“旧代码”的一部分,一旦获得批准,您应该首先重构它们。
I recommend keeping track of how many bugs and code changes involve your "old code" and present this to either your manager or to your fellow developers at your next team meeting. With this in hand it should be simple enough to convince them that more needs to be done to refactor your "old code" and bring it up to par with your "new code".
It would also be prudent to document the parts of your "old code" that are most difficult to understand. These would also be the parts of your "old code" that you should be refactoring first once you get the approval.
可以尝试一下:将你的班级分为最差的 10%、最好的 10% 以及其余的。将列表交付给您的管理层,并说:“我预测下个季度的大多数错误将在第一组中发现。”基于长度、圈复杂度、测试覆盖率 - 无论您使用什么工具都方便且舒适。然后坐下来观察——然后就正确了。现在,当您说“我想投入一些资源来改进我们的糟糕代码,以减少错误和维护成本 - 而且我知道该在哪里投入这些精力,明白吗?”时,您已经有了一些可信度和一些影响力。
Something to try: group your class into - say - worst 10%, best 10%, and the rest. Deliver the lists to your management, saying, "I predict the majority of bugs over the next quarter will be found in the first set." Based on length, cyclomatic complexity, test coverage - whatever tools are handy and comfortable to you. Then sit back and watch - and be right. Now you've got some credibility, some leverage when you say, "I'd like to invest some resources in making our bad code better, to reduce bugs and maintenance costs - and I know where to invest that energy, see?"
您可以创建图表和草图来说明新代码如何工作以及类和函数如何相互关联。您可以使用 FreeMind 或 Dia。我绝对同意记录和评论你的代码。
我曾经也遇到过这个问题。我为我自己的语言编写了一个 J2ME 字体类。由于这些原因,这很糟糕,也许您也可能在代码中看到这些原因。
但几个月后,我被迫再次编写整个内容。现在我学会了使用有时很长的有意义的变量名。写注释比写代码更重要。并使用图表来表示项目的类及其关系。
我不知道这是否是一个真正的答案,但它绝对对我有用。对于旧代码,您实际上可能需要重新阅读整个内容,并在记住功能时添加注释。
希望有帮助。
You could create diagrams and sketches of how the new code works and how the classes and functions are related to one another. You could use FreeMind or maybe Dia. And I definitely agree with Documenting and commenting your code.
I once had a problem with this too. I wrote a font class for J2ME for my own language. It was awful for these reasons that maybe you might also see in your code.
But after a few months I was forced to write the whole thing again. Now I've learned to use meaningful variable names that are sometimes VERY long. write comments more than writing codes. And using diagrams for the project's classes and their relationships.
I don't know If it was a real answer but it definitely worked for me. and for old codes you might actually have to reread the whole thing and add comments when you remember the functionalities.
Hope it helped.
与您的产品负责人交谈!解释说,一旦这个障碍被消除,在重构旧代码上投入的时间将为他带来更高的团队开发新功能的速度。
Talk to your Product Owner! Explain that time invested in refactoring the old code will bring him benefit of higher team velocity on new features once this obstacle is removed.
除了上面提到的好的方法之外,您还可以尝试以下方法:
为了保持未来的代码整洁
清理旧代码:
您可能还需要考虑让产品所有者和 scrummaster 捕获旧代码与新代码的单独速度,并相应地使用它。
Other than the approaches mentioned above which are good, you can also try these:
For keeping future code clean
For Cleaning up the old code:
You may also want to consider getting the product owner and scrummaster to capture a separate velocity for the old code vs the new code, and use that accordingly.
如果有一个想要的新功能,并且您可以描述出一大堆阻碍的代码,那么您可能会得到管理层的批准,用具有所需新功能的新代码替换旧代码。当我这样做时,我必须编写一个有点丑陋的填充层来满足我不打算接触的软件部分的旧界面。测试工具可以执行现有代码并执行新代码,以确保通过填充层看到的新代码可以欺骗应用程序的其余部分,让其认为没有发生任何变化。通过重新设计我们重新设计的部分,我们能够展示出巨大的性能优势、与所需新硬件的兼容性、减少我们每个现场站点对管理应用程序空间的专业知识的需求 - 新代码是 更易于维护。最后一点对用户来说并不重要,但返工的其他优点足以吸引用户“推销”用户一些痛苦的数据库转换的优点。
另一个更温和的成功故事:我们有一个像样的故障跟踪系统,实际上已经有多年的历史了。我们的应用程序中有一个子系统,它以快速耗尽维护程序员的速度而闻名。显然(嗯,在我看来很明显)它需要进行重大重写,但管理层对此并不热衷。我们能够深入挖掘故障跟踪数据的历史记录,以显示维护该模块的人员配备水平,并且通过所有这些努力,每月针对该模块的故障单继续以恒定的速度到达。当面对这样的实际数据时,即使是那些长期以来对该子系统的人员重新设计采取严格措施的不情愿的管理者,也能看到分配人员重新设计该模块的优点。
与之前一样,方法是保留该模块的输入和输出。好消息是,将虚拟内存及其奇特的新数据结构添加到新代码中确实给模块带来了显着的性能改进。坏消息是,在我们真正了解原始实现中的问题之前,我们几乎已经完成了重新实现,因此它在大部分时间都有效,但在某些日子里某些事务失败了。第一次剪辑忠实地重现了这些错误,但这些错误在重新设计的代码中更容易理解,因此我们现在有机会真正解决真正的问题。回想起来,也许我们会更聪明地捕获产生问题的数据,并更加小心地确保重新设计的版本不会重现该问题。但事实是,直到我们在重写过程中取得了相当大的进展之前,没有人理解这个问题。因此,重写为用户提高了性能,并提高了当前程序员的理解,从而最终真正解决了真正的问题。
一个失败的例子:还有一个极其丑陋的模块一直是一个痛处。唉,我不够聪明,无法理解这个由败类和邪恶组成的可怜蜂巢的事实上的接口,至少在名义发布时间表的时间范围内是这样。我愿意相信,如果有更多的时间,我们也可以找到一个合适的计划来重新设计系统的这一部分,也许一旦我们理解了它,我们甚至可以确定用户期望的改进,我们可以将其融入到系统中。改写。但我不能保证您会在每个盒子中找到奖品。如果这个盒子对你来说完全晦涩难懂,那么将它的一部分切掉并用干净的代码替换它是很难做到的。负责该模块的人可能是最有能力制定攻击计划的人,但他将频繁的崩溃和来自现场的求助电话视为“工作保障”。我认为管理层从未真正认识到需要将他放在一边,让一个渴望变革的人离开,但这可能正是所需要的。
德鲁
If there's a desired new feature and you can delineate a non-overwhelming hunk of code that is in the way, then you might be able to get management's blessing to replace the old code with new code that has the desired new feature. When I did this, I had to write a somewhat ugly shim layer to meet the old interfaces of the part of the software I wasn't going to touch. And a test harness that could exercise the existing code and exercise the new code to make sure the new code, as seen through the shim layer, could fool the rest of the application into thinking nothing had changed. By reworking the portion we reworked, we were able to show huge performance benefits, compatibility with desired new hardware, reduction in each of our field site's needs for expertise in administering space for the application - and the new code was much more maintainable. That last point mattered not a whit to the users, but the other advantages from the rework were attractive enough to "sell" the users on the merits of a somewhat painful database conversion.
Another more modest success story: we had a decent trouble tracking system that had literally years of history. There was a subsystem of our application that was famed for the speed with which it would burn out maintenance programmers. Clearly (well, clearly in my mind) it was in need of a major re-write, but management wasn't enthused about that. We were able to dig through the history in the trouble tracking data to show the staffing level that had gone into maintaining this module, and for all that effort, the trouble tickets per month against that module continued to arrive at a constant rate. When faced with actual data like that, even the reluctant managers who had long been tight-fisted about staffing re-work of that subsystem could see the merit of assigning staff to rework that module.
The approach as before was to leave the input and output of that module alone. The good news was that throwing virtual memory at the new code with its fancy new data structures did give a noticeable performance improvement to the module. The bad news is that we were nearly done with the re-implementation before we really understood what was wrong in the original implementation such that it did work most of the time, but managed to fail on some of the transactions on some days. The first cut faithfully reproduced those bugs, but the bugs were easier to understand in the reworked code so we now had a shot at really fixing the real problem. In retrospect, maybe we'd have been smarter to have captured data that produced the problems and have taken better care to make sure the reworked version didn't reproduce that problem. But, the truth is, nobody understood the problem until we were quite far along on the re-write. So, the re-write gave improved performance to the users and improved understanding to the current programmers, such that the real problem could really be resolved at last.
A fail example: There was yet another incredibly ugly module that persistently was a sore spot. Alas, I wasn't clever enough to be able to understand the defacto interfaces to this particular wretched hive of scum and villainy, at least not in the time frame of the nominal release schedule. I'd like to believe that given more time we could have figured out a suitable plan for re-working that piece of the system too, and maybe once we understood it, we could even identify user-desired improvements that we could fit into the re-write. But I can't promise that you'll find a prize in every box. If the box is entirely obscure to you, slicing away a chunk of it and replacing that piece with clean code is hard to do. The guy who had charge of that module is probably the one who was best positioned to figure out a plan of attack, but he saw the frequent crashes and calls from the field for assistance as "job security". I don't think management ever really recognized that he needed to be eased aside for someone with a hunger for change, but that's what probably was needed.
Drew