zoukankan      html  css  js  c++  java
  • 【连载】优秀程序员的45个习惯之34

    警告就是错误

    —— 高效程序员的 45 个习惯之习惯34

    “编译器的警告信息只不过是给过分小心和过于书呆子气的人看的。它们只是警告而已。如果导致的后果很严重,它们就是错误了,而且会导致无法通过编译。所以干脆忽略它们就是了。”
     

    当程序中出现一个编译错误时,编译器或是构建工具会拒绝产生可执行文件。我们别无选择 —— 必须要先修正错误,再继续前行。

     

    然而,警告却是另外一种状况。即使代码编译时产生了警告,我们还是可以运行程序。那么忽略警告信息继续开发代码,会导致什么状况呢?这样做等于是坐在了一个嘀嗒作响的定时炸弹上,而且它很有可能在最糟糕的时刻爆炸。

    有些警告是过于挑剔的编译器的良性副产品,有些则不是。例如,一个关于未被使用的变量的警告,可能不会产生什么恶劣影响,但却有可能是暗示某些变量被错误使用了。

     

    最近在一家客户那里, Venkat 发现一个开发中的应用有多于 300 个警告。其中一个被开发人员忽略的警告是这样:

     

    Assignment in conditional expression is always constant;

    did you mean to use == instead of = ?

    条件表达式中的赋值总为常量,你是否要使用 == 而不是 =

    相关代码如下:

     

    if (theTextBox.Visible = true)

    ...

    也就是说, if 语句总是会评估为 true ,无论不幸的 theTextBox 变量是什么状况。看到类似这样真正的错误被当作警告忽略掉,真是令人感到害怕。

     

    看看下面的 C# 代码:

     

    public class Base

    {

      public virtual void foo()

      {

        Console.WriteLine("Base.foo ");

      }

    }

     

    public class Derived : Base

    {

        public virtual void foo()

      {

        Console.WriteLine("Derived.foo ");

      }

    }

     

    class Test

    {

      static void Main(string[] args)

      {

        Derived d = new Derived();

        Base b = d;

        d.foo();

        b.foo();

      }

    }

     

    在使用 Visual Studio 2003 默认的项目设置对其进行编译时,会看到如此信息“构建: 1 个成功, 0 失败, 0 跳过”显示在 Output 窗口的底部。运行程序,会得到这样的输出:

     

    Derived.foo

    Base.foo

     

    但这不是我们预期的结果。应该看到两次对 Derived 类中 foo 方法的调用。是哪里出错了?如果仔细查看 [ 输出 ] 窗口,可以发现这样的警告信息:

     

    Warning. Derived.foo hides inherited member Base.foo

    To make the current member override that implementation,

    add the override keyword. Otherwise, you' d add the new keyword.

     

    这明显是一个错误 ——Derived 类的 foo() 方法中,应该使用 override 而不是 virtual 。 [1] 想象一下,有组织地忽略代码中类似这样的错误会导致什么样的后果。代码的行为会变得无法预测,其质量会直线下降。

     

    可能有人会说优秀的单元测试可以发现这些问题。是的,它们可以起到帮助作用(而且也应该使用优秀的单元测试)。可如果编译器可以发现这种问题,那为什么不利用它呢?这可以节省大量的时间和麻烦。

     

    要找到一种方式让编译器将警告作为错误提示出来。如果编译器允许调整警告的报告级别,那就把级别调到最高,让任何警告不能被忽略。例如, GCC 编译器支持 -Werror 参数,在 Visual Studio 中,开发人员可以改变项目设置,将警告视为错误。

     

    对于一个项目的警告信息来说,至少也要做到这种地步。然而,如果采取这种方式,就要对创建的每个项目去进行设置。如果可以尽量以全局化的方式来进行设置就好了。

     

    比如,在 Visual Studio 中,开发人员可以修改项目模板(查看 .NET Gotchas [Sub05] 获取更多细节),这样在计算机上创建的任何项目,都会有同样的完整项目设置。在当前版本的 Eclipse 中,可以按照这样的顺序修改设置: Windows→Preferences→ Java→Compiler→Errors/Warnings 。如果使用其他的语言或 IDE ,花一些时间来找出如何在其中将警告作为错误处理吧。

     

    在修改设置的时候,要记得在构建服务器上使用的持续集成工具中,修改同样的设置选项。(要详细了解持续集成,查看在第87 页上的习惯 21。)这个小小的设置,可以大大提升团队签入到源码控制系统中的代码质量。

     

    在开始一个项目的时候,要把相关的设置都准备好。在项目进行到一半的时候,突然改变警告设置,有可能会带来颠覆性的后果,导致难以控制。

     

    编译器可以轻易处理警告信息,可是你不能。

     

    将警告视为错误 签入带有警告的代码,就跟签入有错误或者没有通过测试的代码一样,都是极差的做法。签入构建工具中的代码不应该产生任何警告信息。

     

    切身感受

    警告给人的感觉就像……哦,警告。它们就某些问题给出警告,来吸引开发人员的注意。

    平衡的艺术

    • 虽然这里探讨的主要是编译语言,解释型语言通常也有标志,允许运行时警告。使用相关标志,然后捕获输出,以识别并最终消除警告。
    • 由于编译器的 bug 或是第三方工具或代码的原因,有些警告无法消除。如果确实没有应对之策的话,就不要再浪费更多时间了。但是类似的状况很少发生。
    • 应该经常指示编译器:要特别注意别将无法避免的警告作为错误进行提示,这样就不用费力去查看所有的提示,以找到真正的错误和警告。
    • 弃用的方法被弃用是有原因的。不要再使用它们了。至少,安排一个迭代来将它们(以及它们引起的警告信息)安全地移除掉。
    • 如果将过去开发完成的方法标记为弃用方法,要记录当前用户应该采取何种变通之策,以及被弃用的方法将会在何时一起移除。


    [1] 这对 C++ 程序员来讲是一个潜伏的陷阱。在 C++ 中代码可以按预期方式工作。

    ---------------------------------------------------------------------------------------
    1.诚邀合作: 如果您想翻译、写作或是推荐IT类图书,我们将竭诚为您提供最专业的服务平台。
    2.联系我们: yuany@turingbook.com(E-Mail)
    3.欢迎加入图灵社区与作译者、业内人士进行交流:

    http://www.ituring.com.cn/article
  • 相关阅读:
    HashMap按键排序和按值排序
    LeetCode 91. Decode Ways
    LeetCode 459. Repeated Substring Pattern
    JVM
    LeetCode 385. Mini Parse
    LeetCode 319. Bulb Switcher
    LeetCode 343. Integer Break
    LeetCode 397. Integer Replacement
    LeetCode 3. Longest Substring Without Repeating Characters
    linux-网络数据包抓取-tcpdump
  • 原文地址:https://www.cnblogs.com/turingbooks/p/1616072.html
Copyright © 2011-2022 走看看