【问题标题】:How do you keep debug code out of production?您如何使调试代码脱离生产环境?
【发布时间】:2011-05-22 22:44:00
【问题描述】:

这发生在我们最好的人身上。

特别是在处理没有内置调试功能(如断点和监视变量)的语言时,这些错误会困扰开发人员。调试代码、警报和 Response.Writes 显示在生产代码中。

如何将调试问题与 javascript、php 或 vbscript 中的功能代码分开?您如何确保这些调试更改永远不会进入生产环境?

【问题讨论】:

  • +1 使用最近的事件来介绍问题:)
  • 我以为我看到了这个,因为我一直在搞乱浏览器的 cookie 设置。
  • @Pekka:我正要发布完全相同的句子;)

标签: php javascript debugging vbscript


【解决方案1】:

代码审查。通常,当有人查看代码时,这种事情真的很突出。

【讨论】:

  • 你会这么认为,但是使用 ASP.NET,在响应的海洋中添加一个额外的 response.write 很容易被忽略。
  • 那么您是否应该考虑减少 Response.Writes 的数量?
【解决方案2】:

最简单的方法

define("DEBUG", true);


if (DEBUG) {
    echo "Debug Method";
}

对于 js 也是类似的。

【讨论】:

  • +1 我喜欢这个答案。有一种说法是调试代码不应该出现在生产代码中,而不仅仅是永远不会在生产环境中运行。
  • 这正是我们公司的做法。
  • @Pekka 该示例使用 PHP。 Joel 编辑的是 Javascript。不知道,如果JS知道define(),但至少它根本不是JS打算的。
  • 这是一种糟糕的做法。请参阅php.net/manual/en/language.constants.php#52008 了解一个很好的例子。
  • @vbence 仍然是最简单的方法。我从不建议在生产中完全删除常量;)如果做对了,我不会将其命名为“最佳实践”,但可以肯定的是,现在有更好的解决方案。
【解决方案3】:

确实,开发人员的勤奋和优秀的测试人员都是阻碍因素。没有单一的工具或流程可以防止此类事情的发生。

如果有的话,这是一个很好的例子,说明为什么拥有一个无痛的构建/部署过程至关重要。坏事进入生产环境。保证。真正的问题不是如何预防,而是如何应对。

【讨论】:

    【解决方案4】:

    在代码投入生产之前,我们有多个测试阶段。每个阶段有不同目标的不同测试人员组。到目前为止似乎有效(我们从未将这样的调试代码投入生产)。

    我本来想说“代码审查”,但其他人都已经说过了,我不确定它会不会遇到这样的事情......

    【讨论】:

      【解决方案5】:
      【解决方案6】:

      一种方法是使用环境变量。在您的服务器配置中,您可以设置一个环境变量来表示是否调试。生产服务器将被配置为 false,而开发服务器将被配置为 true。这样你在代码中所做的就是检查环境变量:

      在 PHP 中:

      if (getenv('DEBUG_MODE')) {
          var_dump($foo);
      }
      

      这样,就不会忘记,因为它会自动关闭。但如果你真的需要在生产中打开它,只需拨动开关...

      【讨论】:

      • 我对这种方法的理解是,您将打开整个环境的调试,而不是特定组件。这是正确的吗?
      • 嗯,它会为整个服务器打开它。这是假设用于生产和开发的单独服务器(以及分期,因为您通常不会在开发中关闭调试)。您总是可以设置一组按位的常量来启用不同的组件...
      • 你也可以根据ip/port/DNS自动改变环境
      • 我见过使用 url 来关闭调试代码的代码,但我担心主机文件或其他机制被用来显示这些调试消息。
      【解决方案7】:

      如果您使用专门用于调试目的的语言功能,这种情况往往会减少:

       assert( is_string($param1) );
      

      不会损害生产代码。

      【讨论】:

        【解决方案8】:

        有几种方法可以在生产环境中隐藏调试代码,但很少能将其删除(当编译器无法自动删除它时)。

        我通过以下方式隐藏调试代码:

        • 仅当登录用户是开发人员或测试人员时才显示。
        • 在服务器端将其输出到日志/数据库。

        我在部署前通过搜索特殊的 cmets 将其删除:

        • alert("false") //TODO:REMOVE DEBUG CODE

        我的同事也建议:

        • 覆盖alert 以检查调试变量。 (副作用?)
        • 编写alertDebug 方法来检查调试变量。 (有人记得吗?)
        • 检查firebug是否正在运行

          if(window.console && window.console.firebug) { alert("you are using firebug"); }

        【讨论】:

          【解决方案9】:

          它可能并不完美,但我的编辑器中有一个宏,允许我添加调试并将其包装在适当的标记 cmets 中。我还有一个稍后运行的脚本,可以将这些东西撕掉。诚然,我花了一段时间才真正相信这种机制,但随着时间的推移,我已经习惯了。

          我的偏好是避免检查调试代码。显然,与任何其他“规则”一样,这也有例外,但因为以后很容易错过,我不喜欢检查它。

          【讨论】:

          • +1 用于实际删除调试代码并使过程自动化。
          • 我认为,如果您自动化源代码管理以拒绝使用调试代码签入,那么您可能会拥有比目前所提供的任何东西都更出色的工作流程。
          • 你能提供你用来去除调试代码的代码吗?我很想看到一个可行的例子。
          【解决方案10】:

          我所做的是在 php 中

          define ("DEBUG", true);
          
          
          function op (){
              if ( !DEBUG ) return true;
          
              $args = func_get_args();
          
              foreach ( $args as $var ){
                  if ( is_object ( $var ) or is_array ( $var ) ){
                      print "<br /><pre>";
                      print_r ( $var );
                      print "</pre>";
          
                  }
                  else{
                      print "<br />" . $var;
                  }
              }
          
                  return true;
          }
          
          // On places to check 
          op ($array, $var);
          

          在 js 中我也会这样做

          function calert(message){
              if (!debug) return;
              alert (message);
          }
          

          【讨论】:

            【解决方案11】:

            您是直接在生产服务器上工作吗? 您听说过登台服务器或测试服务器吗? 你可以用你自己的电脑成为你的舞台服务器——使用微软网络矩阵! 让您的代码干净整洁并在那里完美运行,然后转移到生产环境。

            没有其他好的方法可以确保在生产服务器上弹出调试代码——生产前的QA

            【讨论】:

            • 拥有 dev/test/QA/staging/live 服务器是先决条件;但这仍然不能防止代码意外地从一个环境转移到另一个环境; 恕我直言,OP 的问题。但是,您是对的 - 代码应该已被 QA 捕获,是的。
            【解决方案12】:

            我遵循调试代码的三个规则

            让源代码看起来很糟糕,通过...

             not indenting it from the left margin
            
             egregiously violating the coding standard
            
             putting in extra whitespace above and below
            

            设置全局调试开关,

             have it alter an obvious output if it is ON, and
            
             make the debug code compilation depend on that switch being ON (i.e., so the code won't compile if the global switch is OFF)
            

            破坏明显的输出,例如:

             delete something really important
            
             put up 99/99/99, for the date
            
             comment out the "File Load" function
            
             delaying the splash-screen
            
             etc.
            

            这三个规则对我很有效。

            【讨论】:

              【解决方案13】:

              即使在生产模式下,我推荐的调试 PHP 代码的方法。

              1. http://todell.com/debug免费注册并创建一个应用程序

              2. 像这样调试你的 php 代码

                define("DEBUG_LVL",1); /* 将它放在便于编辑的任何地方,或放在整个 Web 应用程序中包含的单个文件上。 */

                如果(DEBUG_LVL > 0) file_get_contents("http://todell.com/w/y///".urlencode(json_encode($object))."/".LINE."/".urlencode(FILE)."/ ".$_SERVER["REMOTE_ADDR"]);

              $object 是您要发送到调试应用程序的对象。它可以是您的代码抛出的异常或基准测试数据中的任何内容。 $object 大小限制为 64KB 这不仅限于 PHP 语言。

              【讨论】:

                【解决方案14】:

                我只提这个,因为没有人去过那里。

                如果您不编写任何调试代码,那么调试代码将无法投入生产。

                如果您正在编写“调试代码”,则表明您实际上并没有很好地理解您的代码。也许它太复杂了。

                首先编写单元测试。这种做法将导致更好的设计。确保您有完整的代码覆盖率。测试难以发生的情况——无法获得套接字连接、数据库不可用等。编写回归测试。不要部署任何无法通过它们的东西。在更改代码之前,任何错误报告都应该变成回归测试。回归测试应该失败 - 并且是唯一失败的测试。修复错误。

                自动化编译和测试。如果实际编写调试代码,则应在测试成功后立即将其删除。当您的组织真正成熟时,也许您甚至会自动部署。

                【讨论】:

                  【解决方案15】:

                  由于最流行的答案存在安全漏洞,所以让我包含一个来自php.net 的风险较小的版本。

                  define ('DEBUG', 1);
                  
                  if (DEBUG == 1) {
                     // echo some sensitive data.
                  }
                  

                  基本相同,但如果未声明常量DEBUG,则不会执行调试代码。

                  if (DEBUG) 的问题在于,如果未定义常量,它将假定字符串“DEBUG”,其计算结果为 true。

                  【讨论】:

                    【解决方案16】:

                    如果它只是“避免生产中的调试”,那么使用内置的 assert() 函数。

                    这完全避免了您的调试消息被处理,并防止您可能在其中进行的任何计算消耗内存或处理能力。

                    assert 在生产中被完全忽略。

                    function debug(...$stuff){
                        var_dump($stuff);
                        return true; //always return true so assert will always pass it.
                    }
                    assert(debug("This code will not even be processed on production server. "));
                    

                    这是最安全的方式,但不是很灵活。

                    我经常使用的一种方法是检查主机名或客户端 IP 地址。

                    所以我有一个功能可以像这样检查主机名:

                    function onTestServer(){
                        $SERVER_NAME = $_SERVER["SERVER_NAME"];
                    
                        if(substr($SERVER_NAME,-5)==="te.st") return true;//all *.te.st domains are test servers
                        if (strpos($SERVER_NAME, ".localhost")!==false) return true; //all *.localhost domains are test servers
                        return false;
                    }
                    

                    然后我有自己的 vardump、debug 和 die 语句,它们不会在生产中执行,类似于:

                    function varDump($stuff){
                        if (!onTestServer()) return;
                        echo "<pre>";
                        var_dump($stuff);
                        echo "</pre>";
                    }
                    

                    那么您只需要使用自定义 varDump() 函数,因此只有您可以看到它。

                    我的调试功能要复杂得多,并显示可扩展的信息树等。但基本原理是相同的。如果在 localhost 上执行 vardumps 等,则不显示任何内容。

                    如果您总是想在测试时看到额外的信息,但又不想在部署到服务器之前删除所有的 vardump,这真的很方便。

                    如果客户端 IP 地址是我自己的,我还会检查客户端 IP 地址并在实际生产服务器上显示错误和信息。

                    function getIp()
                    {
                        if (!empty($_SERVER['HTTP_CLIENT_IP']))   //check ip from share internet
                        {
                            $ip=$_SERVER['HTTP_CLIENT_IP'];
                        }
                        elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))   //to check ip is pass from proxy
                        {
                            $ip=$_SERVER['HTTP_X_FORWARDED_FOR'];
                        }
                        else
                        {
                            $ip=$_SERVER['REMOTE_ADDR'];
                        }
                        return $ip;
                    }
                    
                    function onTestClient(){
                        $office_ip = "xxxx.xxxx.xxxx.xxxx";
                        $test_client_ips = array($office_ip,"any other ip you want");
                        $client_ip = getIp();
                        if (in_array($client_ip,$test_client_ips)) return true;
                        return false;
                    }
                    

                    如果您需要使用方便的计算机在实时站点上测试一些快速更新,而无需使用本地测试环境,这将非常方便。可以将您当前的 IP 添加到列表中并使用如下功能:

                    function die_dev($message){
                        if (onTestServer() || onTestClient()) die($message);
                    }
                    

                    甚至:

                    if (onTestClient()){
                        //show a completely different interface/webpage html js etc
                    } else {
                        //show the original content that is currently live
                    }
                    

                    【讨论】:

                      猜你喜欢
                      • 2011-01-05
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2016-06-14
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多