单独的'调试'和'发布'构建?

时间:2009-01-07 13:42:03

标签: testing debugging release release-management

我认为发布开发人员实际测试的软件版本会更好;因此,我倾向于从project / makefile中删除'debug'目标,因此只有一个版本可以构建(并经过测试,调试和发布)。

出于类似的原因,我不使用'断言'(另见Are assertions always bad? ...)。

有人认为“调试”版本的原因是它更容易调试:但是,我反驳说你可能最终想要支持和调试你发布的任何东西,所以你需要构建一个版本,你可以在必要时调试...这可能意味着启用调试符号,并禁用一些优化,即使在'release'版本中也是如此。

有人说“这是个坏主意”;这是我几年前发展起来的一项政策,被烧毁了:

  • 一些开发人员测试他们的调试但不测试发布版本
  • 一些开发人员编写的错误只出现在发布版本
  • 该公司在测试不充分后发布了发布版本( 完全足够?)
  • 被要求调试发布版本

从那时起,我看到不止一家开发商遵循这种做法(即没有单独的调试和发布版本)。

你的政策是什么?

19 个答案:

答案 0 :(得分:31)

单独的调试和发布版本是一个好主意,因为它确实使开发更容易。

但是调试版本应该仅用于开发,而不是用于测试。您只测试发布版本。并且您不使用开发人员来测试这些构建,而是使用测试人员。

这是一个简单的政策,可以提供两个世界中最好的,IMO。

编辑:为了回应评论,我认为调试和发布构建(可以)生成不同的代码显而易见。想想“-DDEBUG”与“-DNDEBUG”和“#if defined(DEBUG)”等等。

因此,测试最终发布的代码至关重要。如果你在调试和发布版本中生成不同的代码,这意味着测试两次 - 无论它是否由同一个人测试。

然而,调试符号并不是一个大问题。始终使用调试符号构建,保留未提取的二进制文件的副本,但释放已剥离的二进制文件。只要您以某种方式使用内部版本号标记每个二进制文件,您应始终能够识别哪个未剥离的二进制文件对应于您必须调试的剥离二进制文件...

如何从外部源中删除调试器中的二进制文件和加载符号取决于平台。

答案 1 :(得分:21)

这可能是次要的,但它增加了其他人在这里所说的内容。拥有QA测试版本构建的一个优点是,随着时间的推移,软件的内置调试和日志记录功能将由于开发人员的需求而有所提升,他们需要弄清楚QA中出现问题的原因。

开发人员需要调试发布版本的次数越多,客户开始遇到问题时就会有更好的工具。 当然,开发人员没有理由将发布版本作为开发周期的一部分。

另外,我不知道任何软件公司有足够长的周期来支付从版本测试期间中途将QA从调试转换到发布版本的开销。必须进行完整的QA循环,这种情况很少发生。

答案 2 :(得分:12)

我们的政策是让开发人员使用Debug版本,但其他人(QA,BA,销售等)都会运行发布版本。 昨天我不得不修复一个只出现在发布版本中的错误,很明显发生了什么,因为它只是在发布中出现

这是本店第一家,我已经在这里待了18个月左右。

当事情变得多毛的时候,Release版本对调试版本做了不同的事情 - 是的,我去过Hell并在一些非常古老的,非常复杂的生产代码中看到了它。

如果配置之间的唯一区别是调试符号和优化,我认为没有理由不同时使用两者。

答案 3 :(得分:9)

  

所以你需要构建一个版本   你可以在必要时调试......这个   可能意味着启用调试符号,和   禁用一些优化,即使在   '发布'构建。

嗯......听起来你正在为我做一个调试版本......对吧?

你出错的部分就是这句话:

  

我认为最好发布   您的软件版本   开发人员实际测试了

开发人员不测试代码。测试测试代码。

您的单元测试应测试所有构建配置。不要让你的开发人员单手绑在背后 - 让他们使用他们拥有的所有调试工具。 Debug构建就是其中之一。

关于断言:断言的使用在很大程度上取决于你是否按合同编程。如果这样做,那么断言只是在调试版本中检查合同。

答案 4 :(得分:5)

根据我在链接线程中的回答,我们也使用相同的版本进行调试和发布,原因非常相似。与算法级别的手动优化相比,优化器10%-20%的性能提升往往非常小。单个构建消除了许多潜在的错误。具体而言;

  • 未初始化的变量和小的缓冲区溢出可能会在调试和优化的发布版本中产生非常不同的结果。

  • 即使有符号信息,调试优化版本也很困难,因为对象与源不匹配,例如变量可能已经过优化,代码可能已经重新排列。因此,在测试版本构建中报告的错误可能更难以追踪,因此非常耗时。

在自动化回归测试中比较了未经优化和优化的构建,优化提供的性能提升并不能提供足够的额外价值,以便在我的案例中有两个构建。值得注意的是,我开发的软件非常耗费CPU(例如,创建和操作大型表面模型)。

答案 5 :(得分:4)

使用Java进行开发时,我讨厌非调试版本。抛出异常时,您不会获得任何行信息,这使得很难甚至无法跟踪错误。此外,使用Java 5或更高版本,调试和非调试之间的运行时差异大约为5%,因此这确实没有问题,而且对于今天的硬盘,大小不再重要。

在使用调试版本的正面:

  • 堆栈跟踪包含您需要的所有信息
  • 可以检查变量
  • 如果您在生产中遇到问题,只需连接到正在运行的进程,而无需先停止服务器以安装调试版本。
  • 你不会被聪明的优化错误抓住
  • 构建更简单(只有一个工件)

答案 6 :(得分:4)

开发人员使用调试版本,QA,其他人都使用发布版本,我们称之为“生产”。这样做的主要优点是在调试版本中,我们可以添加许多额外的代码和断言。除了在调试器中查看代码之外,某些对象包含额外的信息。某些对象会定期验证自身,以确保所有状态信息都是一致的。这些事情使得调试版本变得更慢,但是它们帮助我们找到了在生产版本中无法找到的错误。

正如我所说的,我们所有的质量检查和性能测试都使用了生产版本,我们偶尔遇到的问题出现在生产中但不会出现在调试中。但它们相对较少,作为开发人员,调试调试版本而不是生产版本的优势远远超过了这个问题。

答案 7 :(得分:3)

由于您在问题中列出的所有原因,我一直订阅“发送您调试的内容,以便调试您发布的内容”方法。

答案 8 :(得分:3)

我认为这取决于项目大小以及您正在使用的构建系统和测试类型。

如果您有自动构建系统,并且在给定构建上运行单元和功能测试很简单,那么您应该永远不会遇到任何多种构建类型的问题。

答案 9 :(得分:3)

在我看来,这个讨论错过了一个非常重要的观点:

这实际上取决于它是什么类型的项目!

如果你创建一个本机(C / C ++)项目,你实际上将被迫创建调试版本,这只是因为在某些情况下编译器优化可能使调试几乎不可能。

如果您创建Web应用程序,您可能更愿意只使用一个构建(尽管“构建”对于某些Web应用程序而言具有误导性),这些构建可以在运行时启用日志记录功能。

虽然本机C ++项目和PHP Web应用程序显然不是所有类型的项目,但我希望我的观点能够实现。

P.S。:在为C#开发时,你会遇到一个边框情况,因为虽然使用调试版本会禁用编译器优化,但根据我的经验,你不会遇到与C ++差不多的差异

答案 10 :(得分:1)

我们总是建立两者,甚至从未考虑过这样做。启用调试选项会增加代码大小并降低性能,在测试时可能不会影响您的软件类型,但如果客户正在运行您的代码以及其他5个应用程序,该怎么办...

测试问题可以通过使用自动化测试进行整理,因此当您认为自己已准备好发布时,可以毫不费力地测试发布版本。您的开发人员或公司未能正确测试发布版本并不是发布和调试版本的失败,而是在您的开发人员和/或公司中。

关于你的最后一点,我从未被要求调试版本构建,只是为了修复它......

答案 11 :(得分:1)

这是一个权衡。鉴于CPU周期很便宜且价格便宜而人工周期仍然很昂贵,因此只维护一个大型复杂程序的单一版本 - 调试(山墙)版本是非常有意义的。

始终使用断言总是比从不使用断言更安全的策略。如果生成单独的调试版和发行版,请重新启用所需的#define个符号,以保证在发行版中也启用了断言。

答案 12 :(得分:1)

这里我们在调试模式下开发并在发布模式下进行所有单元测试。我们是一个小商店,只有少数(12岁以下)应用程序支持从经典ASP,ASP.Net,VB.Net和C#。 我们还有一个专门负责处理所有测试的人,调试后的问题会被抛回给开发人员。

答案 13 :(得分:1)

我认为权衡很简单:是的,只有发布版本,你真的测试实际发送的是什么。另一方面,您确实为开发人员的调试和/或用户的性能付出了代价,因此您可以自行检查这两种情况。

在大多数中型到大型项目中,易于调试 最终确保为用户提供更好的产品。

答案 14 :(得分:1)

请参阅此What's your most controversial programming opinion?

报价:

  

意见:永远不会有不同   “debug”和“release”之间的代码   构建

     

主要原因是发布   代码几乎从未经过测试。更好   在测试中运行相同的代码   因为它在野外。

答案 15 :(得分:1)

通过删除“调试目标”,您迫使开发人员调试该软件的发行版本。这在实践中意味着什么是两件事:

1)“发布版本”将禁用优化(其他开发人员不能使用调试器)

2)没有版本会有特殊的PREPROCESSOR宏改变它们的执行。

所以你真正要做的就是合并发布和调试配置,而不是仅仅消除“调试”模式。

我个人已经在iOS开发中完成了这项工作而没有任何不良影响。在我们编写的代码中花费的时间少于实际发生的时间的1%,因此优化不是重要的贡献者。在这种情况下,它们确实似乎确实导致了bug的增加,但即使它们没有,但是单向测试的想法,然后用不同的代码给QA引入了另外一个要考虑问题的因素。

另一方面,有些情况下需要进行优化,有用的地方,甚至有足够时间进行测试的情况。通常,调试和发布之间的变化非常小,以至于根本不会引起任何问题。

答案 16 :(得分:0)

在我的公司,我们有Debug和Release。 - 开发人员使用调试版本来正确查找和修复错误。 - 我们正在使用TDD,因此我们有一个大型测试套件,我们在服务器上运行,测试调试和发布版本配置以及我们也有64/32版本。

因此,如果使用“debug”配置可以帮助开发人员更快地找到错误,那么就没有理由不使用它 - 当代码进入服务器(待进一步测试)或审查时我们使用“Release”

答案 17 :(得分:0)

我学会了很久以前用.PDB文件构建发布版本,以便我可以调试发布版本。许多程序员往往会忘记的是,当您运行调试版本时,关闭所有优化后,您将完全调试另一个程序。它可能表现得像发布版本(大多数情况下),但它仍然是一个与发布版本不同的程序。

此外,调试发布版本并不困难。如果你得到一个崩溃转储,你必须能够做到这一点。

答案 18 :(得分:0)

如果你有一个真正的QA小组可以指望完全测试这个东西,我会说make debug build直到你接近发布,然后确保完成一个完整的QA循环同样的建筑就要出门了。

虽然至少在一个案例中我们发布了一些仍然有一些调试代码的东西。唯一的后果是它运行得慢一点,日志文件非常大。