在作数据库的读写操作时大家有没过一种奇怪的焦虑感? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
webcoder
V2EX    程序员

在作数据库的读写操作时大家有没过一种奇怪的焦虑感?

  •  
  •   webcoder 2020-01-04 14:36:38 +08:00 5204 次点击
    这是一个创建于 2156 天前的主题,其中的信息可能已经有所发展或是发生改变。
    明明系统里已经约定了,运行到某个代码前数据库里肯定会有这个记录,但写的时候总有种这记录可能不存在的焦虑而会写上一大堆的校验检查甚至是如果不存在就创建的代码,而且在写时还会有种这代码正式使用时估计一辈子也不可能运行到的感觉,从而进化成,既然运行不到为什么还要写啊,的奇怪情绪。
    27 条回复    2020-01-06 09:57:56 +08:00
    xiaotuzi
        1
    xiaotuzi  
       2020-01-04 14:40:05 +08:00 via iPhone
    这是代码的严谨性。
    liuzhedash
        2
    liuzhedash  
       2020-01-04 14:42:30 +08:00   1
    写好抛异常,抓日志的代码就行。
    如果系统设计这个点是应该存在记录的,那有日志不管定位还是甩锅都方便;如果系统设计没有明确这个点,最好提前明确,否则就是定位困难+甩锅大战。
    shawnsh
        3
    shawnsh  
       2020-01-04 14:48:08 +08:00   3
    不要这样写冗余代码。检查不符合条件直接崩溃
    opengps
        4
    opengps  
       2020-01-04 14:49:21 +08:00
    这里要说的是任何代码都进行异常捕获的重要性!
    billlee
        5
    billlee  
       2020-01-04 15:36:54 +08:00
    assert 就行了
    crazytudou
        6
    crazytudou  
       2020-01-04 16:02:46 +08:00
    以前也会考虑这些,现在。。不考虑,只有给对才执行下去,不对就抛异常,这个很有好处,1 是可以知道程序不对要改正,2 是不用再去写一堆感觉没用的东西,这个严谨无关吧
    laminux29
        7
    laminux29  
       2020-01-04 16:05:26 +08:00
    1.检查代码肯定要写。

    2.如果不符合约定,则先写日志,后抛异常。
    guyeu
        8
    guyeu  
       2020-01-04 16:05:39 +08:00
    在该 crash 的时候 crash,不要做不该做的容错。
    guokeke
        9
    guokeke  
       2020-01-04 18:35:45 +08:00
    会写。因为没什么是肯定的。
    Mohanson
        10
    Mohanson  
       2020-01-04 18:53:58 +08:00   1
    分清楚"异常"和"错误". 异常是预期会发生的, 而错误是预期不会发生的. 遇到错误就 crash 掉方为正手.
    GrayXu
        11
    GrayXu  
       2020-01-04 19:20:34 +08:00
    约定了就不管啊。。本地日志记得说明下就好了
    whalegao
        12
    whalegao  
       2020-01-04 20:36:39 +08:00 via iPhone
    考虑主从同步了吗。
    sun1991
        13
    sun1991  
       2020-01-04 20:46:12 +08:00
    如果记录不存在会导致直接 crash 的就可以不管. 否则检查条件并手工 crash. (不过有时候我会偷懒~)
    xavierchow
        14
    xavierchow  
       2020-01-04 21:52:53 +08:00
    > 会写上一大堆的校验检查甚至是如果不存在就创建的代码

    你需要明确你的模块的接口和职责,我猜测你的焦虑是由于对接口定义的不清晰, 另外不存在就创建很容易掩盖其他地方的错误,造成后期问题定位的更大问题。
    可以看一下 [fail fast]( https://en.wikipedia.org/wiki/Fail-fast)。
    另外你这些所谓的多余的代码有测试代码吗?能在测试环境跑过吗?不要去写不可测的代码,因为你不道你所谓的多加的处理是否正确。(尽管你本意是让系统更 robust,但是增加复杂度和降低可读性来换取不知正确性的容错处理得不偿失)
    FrankHB
        15
    FrankHB  
       2020-01-04 22:20:07 +08:00
    正常是看到 DBMS 就有焦虑感。只不过业务上抖 M 惯了很多人才没感觉罢了。
    这和所谓防御性编程贩卖的焦虑本质上是一样的,虽然就影响范围来讲,往往更严重。
    本来是系统内部的 contract,因为 DBMS 和上层业务逻辑的隔离多了一个间接层,因为实现缺陷的问题导致你不得单独考虑风险。这不但让你有焦虑感,一定情况下还成为一个 attack surface。在 DBMS 不是最终用户需要感知的实现细节的情况下,这就是歪曲系统需求的原罪。
    很遗憾,如何有效地、系统地尊重准确地表达需求而不弱化外部指定的整体接口约束,这是一个从理论 CS 开始一直就缺乏足够重视一直到头疼医头脚疼医脚也还没解决的问题。工业界的某些人刚刚才认识到 artificially widening narrow contracts considered harmful。理论界这方面整体反而更呵呵就是了。这应该是这里的人都推动不了的;所以你如果干不掉 DB,继续忍几十年好了。
    JJstyle
        16
    JJstyle  
       2020-01-04 22:40:35 +08:00 via iPhone
    如果是 laravel 项目,建议用 findOrFail 方法代替 find,这个函数在找不到数据时直接抛异常,而不是返回 null,免得后面还去判断取得的数据是不是 null
    xiaozoom
        17
    xiaozoom  
       2020-01-04 23:06:13 +08:00
    这种焦虑我理解。
    “运行到某个代码前数据库里肯定会有这个记录”
    在我看来,这真的没法肯定的,原因可能会有多方面的,比如换人维护了,又比如后来维护的人根本没时间弄懂前面的代码就开始改后面的部分(亲身经历)。
    yafoo
        18
    yafoo  
       2020-01-04 23:19:19 +08:00 via Android
    有同样焦虑
    wuchujie
        19
    wuchujie  
       2020-01-05 01:29:36 +08:00
    go 写多了吗
    wzzzx
        20
    wzzzx  
       2020-01-05 01:36:21 +08:00 via Android
    @shawnsh #3 @shawnsh #3 很多情况并不需要崩溃的
    lxml
        21
    lxml  
       2020-01-05 01:45:19 +08:00
    @wuchujie #19 哈哈哈,是我没错了
    go 语言日常操作

    // 从数据库中读一行记录

    xxx ,err := dao.Find()xxx


    // 出现错误错咋办
    if err != nil
    // 处理拿不到的错误
    if err = ErrNotFound
    // 处理其他奇奇怪怪的错误
    else{
    }


    // json 序列化一下,反序列化出错又咋办
    err = Unmarshal()



    求求 go 语言的老大爷们 早点出错误一把梭方案吧,我知道这样写确实能方便处理错误,但是写业务写多了,实在是非常崩溃啊
    lihongjie0209
        22
    lihongjie0209  
       2020-01-05 10:24:56 +08:00
    我担心服务器的内存在某一时刻内存数据受到物理影响被改变了, 怎么办
    asj
        23
    asj  
       2020-01-05 11:41:34 +08:00
    说明业务逻辑和数据库存取耦合了。
    Takamine
        24
    Takamine  
       2020-01-05 12:28:06 +08:00 via Android
    ……Java 只把异常区分了 checked 和 unchecked,没考虑到突然停电了怎么办。
    :doge:
    crclz
        25
    crclz  
       2020-01-05 20:19:42 +08:00
    根据业务代码的行为,根据逻辑推演,可以证明:运行到某处,某条件一定成立。(这也是“约定”的数学基础)
    如果某个条件没有被满足,那么就说明它的数学基础不满足:一定是代码有 bug,或者 DBMS 有 bug,或者是有其他未遵守约定的程序(或者人)随意的修改了数据库的记录。

    假设某记录不存在,那么你在访问模型类(假设用 orm )的成员的时候(也可以主动检查)就会抛出空引用异常,然后就可以查看 log,排查以上三条中的哪一条出了问题。
    站在普通成员的角度,通常只有第一条是你的锅,那么就在业务代码中做足测试,并且在业务代码中加上(适量的)判断约定条件是否成立的语句。

    站在
    crclz
        26
    crclz  
       2020-01-05 20:20:40 +08:00
    (接上文)
    站在系统负责人的角度,要防御到各方面的因素,那么就请使用 [事件溯源] 模式。
    shawnsh
        27
    shawnsh  
       2020-01-06 09:57:56 +08:00
    @wzzzx 我说的是没电机器就不能跑,不能判断下没电也让机器跑吧.
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1055 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 18:11 PVG 02:11 LAX 10:11 JFK 13:11
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86