V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
mitu9527
V2EX  ›  程序员

关于断言的一个疑问,希望可以和懂的人讨论一下,请不吝赐教。

  •  
  •   mitu9527 · 2020-05-12 22:39:17 +08:00 · 2707 次点击
    这是一个创建于 1416 天前的主题,其中的信息可能已经有所发展或是发生改变。

    今天在读《程序员修炼之道》一书中的 断言式编程 小节,其中提到了观点: 保持断言常开 。即断言不但要在开发和测试期间开启,在生产环境中同样要开启。

    两位大师给出的理由大概是:在开发和测试期间,断言很可能不会被触发,但是在生产环境中一切皆有可能,你不能因为在开发和测试期间通过了断言,就在生产环境中把断言给去除。他们认为就算断言存在性能问题,那么也只需要关闭那些真正会影响性能的断言。
    
    我最早是通过《代码大全 2 》中的 防御式编程 那章知道了断言,其中关于断言的一个观点是:断言主要是用于开发和维护阶段,在生成产品代码时不应该把断言编译到目标代码中,以免降低性能。后来我在 PHP 官方手册中也看到了同样的观点。这种观点已经先入为主,并且深入我心。
    
    现在双方提出了刚好相反的观点,并且双方都是比较权威的,而我自己在断言编程这块经验又比较少,没办法自行判断该怎么做,所以:
    
    想请问那些有思考过该问题的人,你站哪一边?站那一边的理由是什么?
    
    希望有这块经验的人能分享下你的想法,帮助我和没这块经验的人少走一点弯路,谢谢!
    
    15 条回复    2020-05-14 14:16:00 +08:00
    cigarzh
        1
    cigarzh  
       2020-05-12 23:22:18 +08:00
    你的程序要是高精尖行业,比如航空航天啥的,开断言也可以理解,甚至还有更变态东西来保证正确性

    别的就算了吧,别给自己找不痛快
    zhm1620
        2
    zhm1620  
       2020-05-12 23:34:57 +08:00   ❤️ 1
    想象一下你半夜睡的正香,收到了一条运维发的警告告诉你服务器宕机了,你火急火燎爬起来一看,assert 。
    wutiantong
        3
    wutiantong  
       2020-05-13 00:05:05 +08:00
    C++有 invariant 这个概念,可以去了解一下
    littlewing
        4
    littlewing  
       2020-05-13 02:30:58 +08:00 via iPhone
    那我为什么不用其他可控的异常处理方式
    luozic
        5
    luozic  
       2020-05-13 03:20:00 +08:00 via iPhone
    这种需要的是转换,在测试和 sit 环境是断言,在线上自动切换为 log to metrics 平台。当然高安全性和正确性要求的部分模块是要做形式化验证的,如果真有钱。
    msg7086
        6
    msg7086  
       2020-05-13 03:26:01 +08:00
    断言一般是用在特别重大的错误上。比如系统常量被修改,或者内存存储的数据自行改变了等等,这种一出现就意味着整套系统必须停机排查的情况。
    一般业务对这种要求不高吧,用异常处理我觉得够用了。
    laike9m
        7
    laike9m  
       2020-05-13 07:33:28 +08:00   ❤️ 1
    断言是 assert 吗?那当然要常开了,不开的话加它干嘛。加断言是为了 fail fast,不隐藏问题。当然,因为断言一旦 fail 一般会导致整个程序挂掉,所以加断言需要谨慎,一般只加在“如果条件不满足,程序即使继续跑下去也没有意义”的地方。其它预期会出错的地方用异常来处理。

    两篇文章供参考
    http://pgbovine.net/programming-with-asserts.htm
    https://blog.regehr.org/archives/1091
    mitu9527
        8
    mitu9527  
    OP
       2020-05-13 08:35:01 +08:00
    jdhao
        9
    jdhao  
       2020-05-13 11:52:04 +08:00
    要看语言,譬如对于 Python,如果开启了 optimize 模式,那么 assert 语句是不会运行的。如果要检查某个东西是否有效,应该使用 if 加上 raise 来处理或者使用异常捕获,并不推荐使用 assert 来检查。

    参考
    1. https://stackoverflow.com/questions/5142418/what-is-the-use-of-assert-in-python
    2. https://stackoverflow.com/a/20076295/6064933
    macha
        10
    macha  
       2020-05-13 12:29:57 +08:00 via iPhone
    我的习惯是打个 error 日志。
    namelosw
        11
    namelosw  
       2020-05-13 13:04:09 +08:00
    Runtime 的 assert 其实一般叫 invariant 。比如用 React 偶尔就可以看到抛。

    楼上都说当机之类的 crash,也不一定,invariant 也可以 handle,主要看目的是什么。

    需要 Case by case 权衡一下一个 invariant 被破坏,到底是继续运行的损失大,还是停下来损失大。

    另外就是 invariant 的另外一个目的是暴露这个问题,记下来就可以修了。
    jinzhongyuan
        12
    jinzhongyuan  
       2020-05-13 14:45:12 +08:00
    我还以为是说的 Spring 提供的 Assert 呢,我心想那个好像可以随便加
    vitoliu
        13
    vitoliu  
       2020-05-13 15:14:23 +08:00
    业务断言的目的一般是写在特殊逻辑前,确保后续逻辑能正常运行。看个人习惯,我不经常应用,有时候改别人的代码的时候会加。
    duzhanguan
        14
    duzhanguan  
       2020-05-14 10:15:06 +08:00
    @laike9m 你从哪找的这些博客
    laike9m
        15
    laike9m  
       2020-05-14 14:16:00 +08:00 via Android
    @duzhanguan 以前看过的,不是现找的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2745 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 12:24 · PVG 20:24 · LAX 05:24 · JFK 08:24
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.