代码之家  ›  专栏  ›  技术社区  ›  Bradley Smith

避免或接受中断编辑并继续的C构造?

  •  20
  • Bradley Smith  · 技术社区  · 15 年前

    出于这个原因,除其他原因外,我发现自己变得非常依赖于edit并继续使用调试器。它不仅有助于bug搜索和bug修复,在某些情况下也有助于正在进行的开发。我发现能够在运行中的应用程序的上下文中执行新编写的代码是非常有价值的—不需要重新编译并向新代码添加特定的入口点(必须添加虚拟菜单选项、按钮,对应用程序来说,记住在下一个产品构建之前删除它们——所有的东西都可以在不停止过程的情况下进行实时测试。

    我坚持编辑,并继续在这样的高度重视,我积极编写代码,以充分兼容它。例如,我避免:

    • 泛型方法(稳定、不变的实用程序代码除外)
    • 以“任何CPU”为目标的项目(即从不在64位中执行)
    • 在声明点初始化字段(初始化被移动到构造函数)
    • 编写使用 yield

    现在,我完全知道C#3和4中的新语言特性在很大程度上与edit和continue(lambda表达式、LINQ等)不兼容。这就是为什么我拒绝将项目升级到框架的新版本的原因之一。

    我的问题是,避免使用这些更高级的构造来支持非常容易调试的代码,这是否是一个好的实践?这种发展是合法的,还是浪费?另外,重要的是,这些构造(lambda表达式、匿名方法等)是否会导致性能/内存开销,而编写、编辑和继续兼容的代码可以避免这些开销。。。或者,C编译器的内部工作机制是否使这种高级构造的运行速度比手动编写的“扩展”代码快?

    10 回复  |  直到 15 年前
        1
  •  21
  •   Mitch Wheat    15 年前

    在不想听起来老套的情况下,编写单元/集成测试而不是依赖于编辑继续是一个好的做法。

    现在,我并不是建议您回顾性地为所有代码编写单元;相反,每次您必须修复一个bug时,首先编写一个测试(或更常见的多个测试)来证明修复。

    正如@Dave Swersky在评论中提到的,Mchael Feathers的书, Working Effectively with Legacy Code 是一个很好的资源(这是你写了5分钟后留下的遗产,对吧?)

    所以,是的,我认为为了允许编辑和继续而避免新的C#构造是一个错误;但是我也认为仅仅为了它而接受新的构造是一个错误,特别是如果它们导致代码更难理解的话。

        2
  •  6
  •   Jim Balkwill    13 年前

    我喜欢“编辑并继续”。我发现它是交互式开发/调试的巨大推动者,当它不起作用时,我也觉得它很烦人。

    我最讨厌的是用lambda表达式编辑函数中的任何内容都会打断“编辑并继续”。如果我被它绊倒了,我可以写出lambda表达式。我对lambda的表情持怀疑态度。我可以用它们做一些更快的事情,但是如果我以后再把它们写出来,它们不会节省我的时间。

    在我的例子中,我避免在不需要的时候使用lambda表达式。如果它们妨碍了我将它们包装在一个函数中,这样我就可以“编辑并继续”使用它们的代码。如果它们是免费的,我可以把它们写出来。

        3
  •  4
  •   JaredPar    15 年前

    想澄清一下

    最好避免使用这些更高级的结构,而使用非常容易调试的代码?

    “编辑并继续”并不是真正的调试,而是开发。我之所以做出这种区分,是因为新的C#特性非常易于调试。该语言的每个版本都添加了对新语言功能的调试支持,使它们尽可能容易地调试。

    任何东西都可以在不停止进程的情况下进行实时测试。

    这句话有误导性。使用Edit和Continue可以验证更改是否修复了一个非常具体的问题。很难验证更改是否正确,并且不会破坏许多其他问题。也就是说,因为edit和continue不修改磁盘上的二进制文件,因此不允许进行单元测试等项。

    总的来说,虽然是的,但我认为避免新的C协议而允许编辑和继续是错误的。编辑和继续是一个伟大的特性(当我第一次在C++时代遇到它时,它真的很喜欢它)。但作为一个生产服务器助手,它的价值并不能弥补IMHO新C特性带来的生产收益。

        4
  •  4
  •   Reed Copsey    15 年前

    我的问题是,避免使用这些更高级的构造来支持非常容易调试的代码是否是一个好的实践

    我认为,任何时候你强迫自己编写的代码是:

    1. 表现力差
    2. 比较长的
    3. 不可移植(从不调试和测试64位??!?!?)

    您增加的总体维护成本远远超过调试器中“编辑并继续”功能的损失。

        5
  •  2
  •   Bryan Watts    15 年前

    虽然您的方法本质上没有什么问题,但它确实将您限制在IDE所理解的表达能力的范围内。您的代码成为 它的 能力,而不是语言的能力,因此您在开发世界中的总体价值会降低,因为您在学习其他提高生产力的技术时遇到了阻碍。对我个人来说,避免使用LINQ而选择编辑和继续,感觉像是一个巨大的机会成本,但矛盾的是,你必须先获得一些经验,然后才能有这种感觉。

    另外,正如在其他答案中提到的,单元测试代码将删除 需要 一直运行整个应用程序,从而以不同的方式解决您的难题。如果不能在IDE中右键单击并只测试您关心的3行代码,那么在开发过程中您已经做了太多的工作。

        6
  •  1
  •   atamanroman    15 年前

    http://www.codinghorror.com/blog/2006/02/revisiting-edit-and-continue.html

    关于具体的问题:不要回避这些构造,也不要依赖于你疯狂的调试技巧——尽量避免bug(在部署的软件中)。改为编写单元测试。

        7
  •  1
  •   Jon Hanna    15 年前

    我使用了匿名方法和内联委托,使一些相对简单的使用逻辑接近它们唯一的使用位置。

    我已经在构造函数中尽可能完整地初始化了类,以维护类不变量,并消除对象处于无效状态导致错误的可能性。

    我使用枚举器块将创建枚举器类所需的代码量减少到几行。

    所有这些都有助于将快速变化的大型项目保持在可靠的状态。

    我会做很多事情来让你更容易找到虫子,但如果这也能让你更容易找到虫子的话就不行了。

        8
  •  0
  •   Grzenio    15 年前

    Test Driven Development . 我发现完全避免使用调试器非常有用。你从一个新的测试(例如单元测试)开始,然后你只运行这个单元测试来检查你的开发——你不需要整个应用程序一直运行。这意味着你不需要编辑和继续!

        9
  •  0
  •   Jas    15 年前

    依靠Edit和Cont.听起来好像在设计新特性上花费的时间很少,更不用说单元测试了。我发现这很糟糕,因为你可能会做很多调试和错误修复,有时你的错误修复会导致更多的错误,对吧?

    然而,很难判断是否应该使用语言特性,因为这还取决于许多其他因素:项目需求、发布期限、团队技能、重构后代码可管理性的成本等等。

    希望这有帮助!

        10
  •  0
  •   Ian Ringrose    15 年前

    你现在面临的问题是:

    重建应用程序需要太长时间, 重新启动,开始 你正在处理的用户界面。

    在过去,我编写了一个测试应用程序,它将快速加载我正在处理的UI,并用虚拟数据填充它,以减少周期时间。

    将一个UI代码分离到可以用单元测试进行测试的其他类中,将允许您使用这些类中的所有C#构造。然后您可以限制UI代码中使用的结构。

    当我开始编写大量的单元测试时,我对edit和continue的使用率下降了,除了UI代码之外,我很难使用它。

    推荐文章