调试代码的方法(噩梦情况)


16

我经常在工作中负责调试应用程序。它是一个我们部署到企业的BI应用程序,其中包括测试环境和生产环境。我想知道,基于这些限制,人们是否可以建议任何应用程序/工具/方法:

  1. 调试器不能在客户端站点上或本地使用,因为该软件依赖于我们没有测试环境的自定义第三方应用程序。(编辑:说实话,在某些情况下,可以在本地进行调试。如果我们只使用核心代码,那么大多数有问题的代码都位于一个DLL中,该DLL封装了第三方特定的通信:套接字,进程管道,soap调用,更改核心代码行为的自定义逻辑。通常,在为客户实施或增强功能时,我们会在此区域编写新代码。)

  2. 实际上,我们的应用程序中没有任何日志记录。没有单元测试。

  3. 版本控制只有完整解决方案的1个版本(使用Source Safe 2005)。因此,不可能仅通过单个文件来获得整个解决方案的先前版本。(除非有人知道解决此问题的方法)。

  4. 无法本地复制,通常无法在测试环境上复制(测试和生产版本不同的可能性很高)。

  5. 客户端使用的版本与来源安全版本不同的可能性很大。这是因为已更新单个文件,这些文件具有针对该特定客户端的嵌入式自定义逻辑。通常会发生的事情是对二进制文件进行更新,这需要更改其他几个二进制文件,但是提交完成后,没有人对此有任何记录或知识。我看到的一个常见错误是客户端环境上的“找不到函数/方法”或“方法调用指定的参数太多/太少”。

  6. 这是一个.net VB解决方案

  7. 无法在客户端站点上安装任何软件,但可以在本地

  8. 我们的应用程序具有极高的可定制性,但是不幸的是,定制逻辑分布在所有类和文件中,从前端一直到数据层,包括基于每个客户端对数据库进行的定制更改。

  9. 代码中几乎没有注释。没有有关体系结构的文档。没有有关api的文档。我们唯一拥有的是成百上千的电子邮件链,这些链在某种程度上解释了正在发生的事情。唯一知道该代码的人是最初编写该代码的人,但是他们不再是每个人所说的开发人员,因此他们不会参与其中。

在你说出来之前……是的,我知道;我也想开枪 意大利面条代码,数百个编译器警告以及确实应该修复的破碎多态性并没有帮助,但是我没有发言权。

我遇到的最常见的错误类型是空引用错误,无效的强制转换和缺少的功能/功能签名不匹配。有时我很幸运,事件查看器将记录类,方法和异常消息。它不是最有用的,但还是有帮助。最糟糕的是没有屏幕快照,没有复制步骤的错误,而且是类似于上面提到的一般错误消息。有时,不可能找出它们发生的原因,只能祈祷环境配置不正确,以后环境会消失。

我知道这有点像咆哮,在某种程度上是这样。但是我渴望选择。我还能使用其他方法/工具吗?


43
你有简历吗?
罗伯特·哈维

5
为“我也想开枪自杀” +1。来源Safe 2005,哎呀。好吧,至少您应该“关注”精彩的历史课-您基本上是时间旅行者!您将学到十年的经验教训,这些知识是经过精心开发的,“这就是为什么我们不再这样做了”。Godspeed,蚱hopper。
BrianH

7
在给定要求#1的情况下,有效调试这种混乱状况的唯一方法是千里眼。认真地说,除了胡言乱语之外,没有什么能使这一切变得神奇的了。在某些方面,这应该减轻您的压力,因为调试必然是个运气问题。还是您的管理层要命令您走运?显然,这是不可持续的,因此您应该寻找其他机会。
Charles E. Grant

14
这是一些实际的职业建议:在一个拥有可怕的软件工程实践的房子里花费太长时间,您可能会因为无法避免的问题而成为糟糕的开发人员,从而被管理层指责。我去过那里,我敢肯定其他人也有。从根本上说,这会导致不良的开发习惯。
Gort Robot

2
如何处理这些情况:如果我的薪水不高于市场价格,我会去找其他事情做。
凯文·克莱恩

Answers:


22

罗伯特·哈维(Robert Harvey)的建议可能是最好的,但是由于职业建议不在主题之内,我将给出可以给出的答案:

您位于一座陡峭的山的底部,那里布满荆棘,泥泞和易怒的山羊。没有简单的方法。如果您想登顶,就必须每次都强迫自己迈出一大步。

看来您确切知道应该如何工作。如果没有其他人能帮助您,那么(再次,忽略职业建议)您唯一的选择就是自己开始修复这些问题。

首先,对于所有神圣的东西,请将其放入真实的版本控制系统中。除了Source Safe以外,几乎没有任何其他东西,Source Safe被称为臭味十足的垃圾。 git是免费的,可以很容易地设置。您无法解决过去缺乏版本控制的问题,但至少可以阻止该问题持续到将来。

接下来,查看日志记录。查找,或者在最坏的情况下,编写一个日志记录系统,然后开始使用它。也可以使用可在客户端站点上使用的一种,这样,当事情发生横向变化时,您至少会有一些东西。

并开始编写测试,至少对于您所做的新更改。

它没有糖衣:这里没有答案不涉及很多工作,或将其视为职业问题。


相信我,除了添加断言,保护和日志记录外,我可能只想重写数据层(我正在编写配置验证器来诊断典型的配置问题)。不幸的是,这不取决于我。我可以要求将某些东西安全地放入源中,但是典型的答复是“您的意图很好,但这不是我们应该关注的事情”。las,我不过是具有1/2年经验的大三学生。我要爬这座山一段时间。
Igneous01 '01

9
老实说,@@ Igneous01,尝试找到另外一座要爬的山。在其他地方的工作条件可能并不完美,但我想至少大多数情况都比您所经历的要好得多。如果您的网守拒绝您通过“这不是我们应该关注的事情”来进行改进,那是他们做出的决定,他们将获得那项失败政策的结果(他们已经在开发时间上浪费了很多钱) 。问题是,您是否要坚持使用直到他们这样做?
cmaster-恢复莫妮卡

6
并且要记住,当错误的政策失败时,每个参与的人看起来都很糟糕,即使是那些不同意的人。

1
是的,开始记录和跟踪。也开始记录文档,并添加评论。一点一点地,它们全部加起来。另外,您说您很幸运,即使没有团队,仍然有一些公司的原始编码员。推动管理人员对他们进行评估如果可能的话,说服他们说他们宁愿制作一些文档,也不愿经常遇到问题。
Mawg说恢复Monica的

4
@ Igneous01:跑步,不要走路。这个地方生病了,会让你生病。
恢复莫妮卡-M.Schröder'16

8

1)调试器不能在客户端站点上使用...

完全正常。

...或本地

现在这是一个问题。

2)在我们的应用程序中几乎没有日志记录。

日志记录生产调试。

没有单元测试。

噢亲爱的。不过,这都是普通的。

3)版本控制只有完整解决方案的1个版本

然后,您不使用版本控制。

4)无法在本地复制,通常无法在测试环境上复制(测试和生产版本不同的可能性很高)。

因此,只有已部署的客户端环境会显示错误。

在这种情况下,你需要嵌入在应用程序代码disgnostic日志记录(一)陷阱和[充分]点播记录[致命]错误和(b)可以“拨打了”,以产生额外的,连续的,诊断是有用的跟踪问题。

5)客户端使用的版本与源安全版本不同的可能性很大。

同样,您只是没有使用版本控制来发挥自己的优势。

8)我们的应用程序是高度可定制的

这是很典型的。

特定于站点的差异应通过版本控制“分支”进行管理。

9)代码中实际上没有注释。

同样,这太普遍了,因为开发人员编写了“自我记录”代码,不是吗?
或者,至少是他们在编写当天就理解的代码。

没有有关体系结构的文档。

噢亲爱的。

没有有关api的文档。

哦,亲爱的,哦,亲爱的。

在你说出来之前……是的,我知道;我也想开枪

没有; 您想拍摄写所有这些东西的人,创建一个没有证件的,无法维护的烂摊子,然后又搬到新的牧场,把那些不合情理的烂摊子抛在身后。

我遇到的最常见的错误类型是空引用错误,无效的强制转换和缺少的功能/功能签名不匹配。

空引用和无效的强制转换是运行时错误;在某种程度上,您应该期待它们,而您经常获得它们的事实则表明原始作者缺乏防御性编程(或过分乐观)。

功能签名不匹配会导致构建失败; 那些应该导致“破碎的构建”,并且永远都不要让它破门而入!


2
“总是编码,就像最终维护您的代码的人是知道您所住地的暴力精神病患者一样”
PerryC 2016年

运行时错误的原因更多是缺乏了解,而不是缺乏防御性编程。防御性编程只是隐藏代码无效的事实的一种方式。
user253751 '16

1
“没有有关体系结构的文档”通常意味着“没有体系结构” ...
gnasher729 '16

The site-specific differences should be managed through Version Control "Branching".-我认为这不是最好的方法。使用配置文件和功能切换似乎更常见,并且更容易推理。
sixtyfootersdude 2016年

5

从记录开始。这将产生最大的影响。在代码库中实现日志记录框架,例如Log4Net或类似代码。开始记录代码的作用。

应该可以在本地进行调试。如果没有,请继续获取符号文件(PDB),以便您可以调试到第三方dll中,以获取有关所发生问题的完整信息。如果系统崩溃,则诸如WINDBG之类的工具可以指出哪些DLL有问题。可以将任何服务器配置为在发生崩溃时进行内存转储。它基本上是问题发生时发生情况的快照。可以在本地检查转储以找到发生情况的线索。如果无法进行调试,请继续进行调试。记录调试所需的步骤。有时在复杂的系统上,需要进行大量调试才能完全调试。

错误跟踪...如果您不使用一种,请开始使用一种。这与适当的版本控制系统并驾齐驱。基本上,开始跟踪代码的缺陷和修订。开始建立系统的历史记录。

执行静态代码分析。投资ReSharper之类的工具。它将迅速指出所有可能的空引用异常和其他不良编码实践。只需单击几下,它就可以帮助使代码变得更好,并使诸如代码格式设置,变量命名等繁琐的项目自动化。测量代码,通过代码指标找出重构的热点。

重构和单元测试。我将假设大多数编写的代码不是非常可测试的,因此我不会为添加测试而烦恼。任何新代码,创建测试项目并开始编写单元和集成的测试。如果单元测试失败,则构建失败。因此,在重构时,应该进行测试。测试的一件事是,可以编写一个测试以调用任何方法并在该方法中进行调试,而无需加载整个应用程序或代码库。这有助于解决问题。

根据需要记录任何部落知识。该代码应该是自记录文档,因此注释应很少,但是许多系统具有“异常”的处理方式,请在WIKI编码或其他类型的非正式存储库中指出。另外,请考虑提出编码标准和实践。通过像Resharper这样的工具集来执行这些标准。由于大多数代码可能未遵循任何标准和准则,因此请在编写的新代码上实施这些标准。

自从您上任以来,我将把这当作当值旅行。6个月至2年,然后选择留下还是继续前进。使事情比前一天好一点,从而使您满意。


4

首先,以上所有……同上。

一些启发式:

  • 在开发计算机上使用源代码管理。这是我做过的最好的事情。它不能替代我们拥有的项目的版本控制。它是一种工具,它为惊人的自由度提供了极大的自由,可以无畏地进行实验,修改,同时同时独立地处理问题等。我更擅长使用版本控制,因为我拥有大胆,精通和学习的自由。
  • 在您添加注释的范围内,请优先考虑公共界面元素,以利用智能感知。在调试冒险过程中解密时执行此操作。
  • 坚持进行少量重构。迟早,对于给定的大量代码,您将达到临界数量,从而可以进行大型重构,例如在各个类之间干燥冗余代码。
  • 不要在同一版本控制提交中混用代码重新格式化和实际更改。
  • SOLID原则
    • 永远不要忽视单一责任。做得好,这就是实现面向对象的承诺的途径。恕我直言。
    • 始终忽略打开/关闭。
    • 我们在这里不谈论新代码。
    • 没有经过专门设计的接口会妨碍维护。
  • 重构
  • 某些代码文件甚至在尝试调试之前,都需要完全重新格式化,变量重命名等。不要在没有单元测试的情况下使用Visual Studio的重构菜单。
  • 唯一不能放错位置的文档在代码文件中。
  • 当您获得版本控制时,请提前考虑VC计划。并记录下来!并为分支机构命名约定,标记将突出主要软件版本和里程碑。
  • 使用好的设备
  • 练习橡皮鸭调试
  • 有时可能发生的最糟糕的事情是他们不会解雇您。

编辑

.NET中的Brownfield应用程序开发

试试这本书。最好覆盖一下通篇。这本书将帮助您思考全局,可能性,并制定攻击的战略和战术计划。

伸出来

如果可以的话,请停留1.5年。足够长的时间才能知道您是否正在取得进步。您将知道您是否获得2年的经验或6个月的经验4次。

作为“有1/2年经验的初中生”,我担心潜在的雇主会将其视作早期保释,因为您无法破解它。说您学会了z,y,x并取了一些名字并踢了一些屁股,这是一回事,但是却不允许您为自己的能力做出贡献;另一种只是冒险以解释的方式散布工作,代码,管理等。

我可能以此为基础,但是我的“最好的时光和最糟糕的时光”是我的第一份工作,而这恰好是无法维护的代码。我有一位很棒的主管(其余所有人员都来自管理育种计划),他给了我重新编写一些关键程序的空间。那经验是启示。

结束编辑


+1表示请勿混合使用代码重新格式化和同一版本中的实际更改进行提交。-很棒的建议
kiwiron,2016年

0

我会说(5)是您首先需要解决的问题。如果您不知道生产中正在运行的代码,则没有安全的方法来重现和解决问题。这会使您进行的任何其他更改变得危险,因为它可能会导致无法预见和无法复制的问题。

您可能需要做一些侦探工作,也许还需要进行逆向工程,以找出部署了哪些版本的代码和哪些库。(并且您需要一个一致的构建和部署系统,以使所有部署的代码与源代码管理保持一致。)

您可能必须构建多个测试环境才能复制各种部署。(当然,最简单的解决方法是创建一个新的干净的构建并将其一致地部署到任何地方,但这听起来不可能吗?)

仅当您知道已部署的确切版本并具有相应的测试环境时,才应开始尝试修复/改进代码。

您的下一个优先事项应该是整合到可以部署到任何地方的单个代码库。听起来您由于定制而部署了各种版本的代码?您应该合并为单个版本,然后将配置开关用于自定义逻辑。

此后,您可以开始仔细地改进代码库,以简化调试过程。添加日志记录可能是风险最小的改进。

您将要添加自动化测试,但是单元测试通常很难添加到最初不是为测试而设计的项目中。相反,我建议从自动化的端到端集成测试开始。这些设置起来比较棘手,但是不需要您重新设计解决方案,因此风险较小。


0

忽略团队中存在的问题,似乎要解决的第一个问题是调试与生产环境匹配的代码。否则,您可能正在追寻已在“源代码控制”中的代码中修复的错误。由于这是.NET,因此您可以轻松地“反编译”生产二进制文件,以将代码与所拥有的代码进行比较。这不是一件容易的事,但是如果您成功的话,这就是一个更好的可以标记发行版本的源代码控制工具的有力理由。


当您指的是反编译时,您的意思是使用IDA Pro之类的东西来查看机器代码?那时我可能是唯一使用它的人,因为这里没有人知道汇编(我也很了解基本知识)。
Igneous01 '01

好的,因为这是.NET,所以二进制文件不是机器代码,它们在CIL中(en.wikipedia.org/wiki/Common_Intermediate_Language)。这可以很容易且准确地转换回c#或VB代码,尤其是在没有混淆的情况下。您可以尝试使用ILSpy作为示例(ilspy.net),但是可能还有其他工具可以使用。
20C
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.