如何管理经常修改的生产代码?

5

我的项目需要我对生产代码进行许多更改。需求不断出现,我需要尽快进行更改并部署。有时候,由于某些要求无法适应软件的整体设计,我最终会创建补丁式的代码。如何有效地处理这种情况?是否有任何设计模式可以处理这个问题?


经常修改生产代码?!天哪,不要啊! - OJ.
总有其他的选择... - Ilya
12个回答

14

我已经多次见过这种情况,它总是以泪水收场。上一次客户在改善他们的流程之前损失了数百万美元。

用户总是希望新的需求能够“尽快”得到满足,但他们不理解进行更改的风险,就像你所做的那样。他们看到没有该功能的成本,但他们不会预测如果更改破坏了某些东西,将会发生什么以及会损失多少钱。(我的意思并不是说你不是一个好开发人员,只是在任何非微不足道的软件中都会存在错误,并且不受控制的更改很可能会更快地暴露它们。)

因此,我认为你需要退一步,并尝试引入定期发布计划。会有阻力,但你可以更加有效地实现这一点。当然,有时确实需要立即进行更改,但如果有一个时间表,那么责任将落在用户身上,让他们证明打破发布周期是有意义的。

哦,正如其他人建议的那样,你需要像一个分阶段 / 测试系统,单击发布程序等技术基础架构。 (请参阅Joel Test。)


我完全同意你的观点,Stephen Darlington。但是有时候产品在发布后会遇到意外情况,需要快速修复。比如说市场上的任何操作系统,它们都会进行主要版本的发布,但总会需要热修补程序,因为问题太关键了。 - Robert Gould
@Robert Gould,我不确定您是否读完了他的所有帖子,但他说有时可能必须立即发布。“当然,有时可能需要立即进行更改。” - mmcdole
@Robert,热修补绝对有其存在的必要性。但是这应该是非常特殊的情况。你需要做出有意识的决定来应用它;它不应该成为默认选项。 - Stephen Darlington

5

测试,你需要一个可靠的测试框架来确保你的修复不会破坏其他任何东西。

编辑:回答评论中的问题。

不幸的是,除了花时间重构“hack”之外,我无法想出一个真正稳健的模式/解决方案来保持架构完整。但是你可能没有太多时间去抽空,因为你已经在生产中了。所以这并不容易...

然而更重要的是,如果架构被破坏了,因为你真的需要在解决方案中进行“hack”,这实际上可能表明原始设计未满足产品的实际要求,因为如果满足了,你应该能够在当前架构的框架内进行修复/补丁。

因此,试图对整个情况持积极态度,你应该注意你的修复措施以及当前架构如何不帮助/符合要求,这样当热修补开始稳定下来时,你就可以拥有数据和提示,重新设计任何现在需要设计的架构部分,因为你发现了在生产过程中更准确的要求。


谢谢您的建议!我还有一个担心。我经常修改代码,实际上破坏了整个架构。对此有什么建议吗? - Manoj
如果更改“破坏”了架构,那么通常最初的架构就不正确。很少有架构因为更改是一个非常糟糕的想法而被打破。 - S.Lott
是的,我认为我需要重新审视架构。我应该注意修复并尝试在未来重新设计它。感谢您的建议! - Manoj
@Robert - "......开始稳定下来,有数据和提示可以重新设计架构的任何部分......"这可能是危险的,特别是如果业务不知道你在做什么。在这种情况下,除非你有回归测试的安全网,否则你将一无所获。 - Eric Smith
@Eric 这实际上是真的,我们也必须小心不要破坏业务向后兼容性! - Robert Gould

4

大家都提出了很好的建议,比如测试等。但我认为我应该指出你可能在问错误的问题。你正在问是否有一个“模式”可以帮助解决这个情况。模式是一种设计选择,用于解决设计问题。实际上,您所面临的是“流程”问题。

我会问:“我可以使用什么流程来防止这种情况发生?”

不幸的是(在我工作的地方也是如此),设计是开发人员和架构师需要考虑的问题,但流程是管理人员需要考虑的问题。实现良好的流程并坚持它确实需要领导力。不幸的是,这通常是缺乏的。


2
这可能是一个太基础的答案了,但我认为你应该对敏捷软件开发进行一些研究。

2
我很幸运,我的HEAD几乎总是可发布的。每周至少有一次,我会在HEAD中编写代码,并且作为开发人员,我很高兴将其发布。这并不意味着每个可发布的版本都会被发布,但可能会被发布。在我的环境中,每周发布实际上非常实用,并且通常会被发布...
在部署到staging之前,我将我的代码升级到Release分支。我总是将已经在staging上测试过的代码部署到live。
任何紧急修复都可以在release分支中进行,并在部署之前在Staging上进行测试。如果修复足够好,我可以将其合并回HEAD。如果它是一个可怕的hack,我可以稍后在HEAD中正确地重新实现它。
我拥有一套良好的开发人员测试,每次检入时都会自动运行,以确认我没有破坏任何重要内容。我的应用程序还在每次部署时运行内部测试,这使我更加自信。
实际上,运气并不像你想象的那么重要。这不是偶然发生的;我必须努力使其成为可能。我必须致力于编写和维护良好的自动化测试,并获得持续集成服务器和一键式构建和部署能力。
我经常花时间清理我的代码,作为我的正常开发活动的一部分。这有两个好处。首先,它意味着我的代码库相对干净,因此架构非常灵活。其次,由于我一直在这样做,所以我擅长重构。我的意思是通过对现有代码进行一系列单独的小转换来重构,而不是在扔掉所有内容并重新实现的意义上重构(这更加危险)。
在我看来,“持续可发布性”是敏捷方法中最大的好处。

1
除了显而易见的版本控制、单元测试和自动化构建系统之外,听起来你还需要进行一些重度重构。如果你的设计基于不断变化的需求而不断变化,那么你应该尝试将代码中不断变化的部分隔离到它们自己的模块中。

1

你需要对需求积压进行严格管理。尽管可能会听起来有些老派和固执,但你需要告诉人们拒绝一些需求,并让他们与你一起学习关于设计变更的具体痛点和付出的努力。对于数据库,解释一下基数是如何引起问题的。坚持按计划发布周期进行发布,例如每周二进行生产发布,但前提是用户已经接受了。将每个请求分成2、4和8周的段,并且要严格控制这些时间范围内包含的内容。

如果您有明确定义的问题域和解决方案,那么有许多设计模式可以帮助您。具体来说,请查看命令模式策略模式插件架构,因为它们将帮助您更轻松地扩展解决方案集。如果您是 .Net 开发人员,请查看 Migeul Castro 在DNRTV上评审的插件架构。


当应用程序出现关键问题时,这并没有什么帮助,而且如果一直拖到下下周二再解决,将会损失数百万美元。 - David Thornley

0

有几个项目生命周期可以作为你的方法模式。这个网站列出了一些(听起来你正在使用“代码-修复”!),但这绝不是一个明确的列表,更大的列表可以在这里找到。


0
正如Robert Gould所指出的那样,您真的需要一个分阶段平台来检查在部署到生产环境时不会破坏任何东西。

0

两个明显的工具是版本控制和测试。尝试将发布系统与它们集成,这样您可以在每个步骤提交更改,并且当所有测试都通过(包括新要求的测试)时,发布系统会选择“已知良好”的版本,这将成为新版本。

我不知道其他系统,但Monotone有一些钩子专门用于使测试标记提交,因此有一个命令可以“给我最后一个通过所有测试的版本”。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接