• 【连载】优秀程序员的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
  • 相关阅读:
    vagrant使用
    商品分类
    猜你喜欢
    [NOIP2012]开车旅行
    bzoj 1029: [JSOI2007]建筑抢修
    bzoj 2127: happiness
    bzoj 2561: 最小生成树
    bzoj 3331: [BeiJing2013]压力
    数组中简便方法求最大值,最小值,平均值,求和,和个数
    #include 和 #import 的区别, @class 的含义
  • 原文地址:https://www.cnblogs.com/turingbooks/p/1616072.html
Copyright © 2020-2023  润新知