V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
banli
V2EX  ›  问与答

编程过程中, 你是习惯提前返回, 还是统一返回。

  •  
  •   banli · Apr 24, 2017 · 7722 views
    This topic created in 3301 days ago, the information mentioned may be changed or developed.

    在编程的过程中, 每个人都有每个人的编程习惯。 就比如在写一个函数的时候, 我就喜欢判断一下不符合预期的接口, 提前报错或者提前返回,这样写下了代码会容易看懂, 没有复杂的嵌套判断。 。

    然而还一种习惯,就是习惯统一返回。这样就只有一个地方返回,比较好测试预估。但是相应的,代码的各种判断嵌套可能就比提前返回来的多了,看逻辑会吃力一些。

    你觉得呢?

    75 replies    2017-04-25 14:19:41 +08:00
    jedrek
        1
    jedrek  
       Apr 24, 2017
    我觉得这两种并没有好坏之分。我两种都用,主要是看函数里的逻辑情况,捡逻辑最清晰、最易读的方式写
    lany
        2
    lany  
       Apr 24, 2017
    哪种不费脑用哪种,脑子能不用最好。。。
    murmur
        3
    murmur  
       Apr 24, 2017
    有的时候提前返回可以少写 if/else ,尤其是因为参数不合法的
    sagaxu
        5
    sagaxu  
       Apr 24, 2017
    统一返回,是 bad smell
    815lbh
        6
    815lbh  
       Apr 24, 2017
    提前返回
    rozbo
        7
    rozbo  
       Apr 24, 2017   ❤️ 1
    看起来你们都不写 c 和 c++等手动内存管理的语言啊。
    在这种语言中,不能够提前返回,否则可能上面申请的内存忘记释放,或者句柄忘记关闭造成内存泄露或僵尸对象。
    当然,即使是自动内存管理的语言,也存在需要手动管理的资源。这个时候提前返回同样可能导致问题的发生。
    因此,我建议尽量都使用一个返回语句。除非你确定提前返回不会导致问题的发生。而且,在多人协同工作的时候,不会因为别人在前面加了代码而导致问题的发生。
    在我们团队,要求所有人在每个函数或者方法里都有且只能有一个 return 语句。
    huijiewei
        8
    huijiewei  
       Apr 24, 2017
    提前返回
    coderluan
        9
    coderluan  
       Apr 24, 2017   ❤️ 2
    @rozbo

    手动管理内存方法很多,可以创建内存池统一管理,可以规定只在构造之后申请内存,或者是提前返回需要特定错误值,你这只是一种解决方法而已,又不是唯一的方法,怎么能看出来别人不写 C++呢,我反而是感觉你 C++写的少。
    sagaxu
        10
    sagaxu  
       Apr 24, 2017   ❤️ 4
    @rozbo 写 C++的会不知道 RAII?
    Shura
        11
    Shura  
       Apr 24, 2017 via Android
    @rozbo 这个语言并没有任何关系,习惯而已。
    rozbo
        12
    rozbo  
       Apr 24, 2017
    @coderluan 你说的这几种方案对于你个人来说是可以的,但对于团队成员来说就不是那么容易接受的了,在你提出的这几种方案中,实现成本最小的无疑是约束团队成员用统一的返回方式。
    你能保证你团队中没有新手吗?
    coderluan
        13
    coderluan  
       Apr 24, 2017
    @rozbo

    我们团队确实没啥新手,假设有的话,也是应该他自己去学习,而不是我们找个简单的办法迁就他。另外实现成本最小的就是 RAII ,简单来说构造申请析构释放,再新手也能学会吧。
    jarell
        14
    jarell  
       Apr 24, 2017   ❤️ 1
    @rozbo goto
    rozbo
        15
    rozbo  
       Apr 24, 2017
    @coderluan
    char * a=(char*) malloc(0x1000);
    这种的,怎么 RAII ?
    rozbo
        16
    rozbo  
       Apr 24, 2017
    @jarell 这个屌。
    jarell
        17
    jarell  
       Apr 24, 2017
    @rozbo 该 goto 时就 goto 自己写的开心就好
    mkdong
        18
    mkdong  
       Apr 24, 2017 via iPhone
    同意 goto ,不仅可以减少不必要的嵌套,还可以统一返回
    0915240
        19
    0915240  
       Apr 24, 2017 via iPhone
    fast failed
    dingz
        20
    dingz  
       Apr 24, 2017
    @rozbo auto_ptr
    liul85
        21
    liul85  
       Apr 24, 2017
    提前返回 少写 if , else
    gamexg
        22
    gamexg  
       Apr 24, 2017 via Android   ❤️ 1
    @rozbo c 这么说还算合适,但是 c++忘记释放内存? 智能指针想哭。
    chunqiuyiyu
        23
    chunqiuyiyu  
       Apr 24, 2017 via iPhone
    能提前返回就一定要提前返回
    coderluan
        24
    coderluan  
       Apr 24, 2017
    @rozbo

    用 a 当类成员变量,该咋整咋整呗,要不你告诉我为啥你认为这种不能 RAII 吧?
    otakustay
        25
    otakustay  
       Apr 24, 2017
    使用符合语义的提前返回
    lrxiao
        26
    lrxiao  
       Apr 24, 2017
    @dingz 17 年了还 auto_ptr... 难道被三体人锁死了编译器吗
    lrxiao
        27
    lrxiao  
       Apr 24, 2017   ❤️ 1
    @rozbo std::unique_ptr<char[]> p{new char[1000]};
    dingz
        28
    dingz  
       Apr 24, 2017
    @lrxiao 不好意思,表述不当,是想说“智能指针”的,没有特指啥哈
    think2011
        29
    think2011  
       Apr 24, 2017
    提前返回,容易看到
    wuethan
        30
    wuethan  
       Apr 24, 2017
    封装函数更适合提前返回··· 我喜欢清晰的感觉 无限嵌套思路混乱··· 另外只做过串口和数据库交互 没遇到什么需要关闭的问题,数据库都是一次性的查询完就关 串口就是一直打开做判断即可 条件不足就不执行就完了·· 我是不会在打开和关闭之中写 return;的
    lrxiao
        31
    lrxiao  
       Apr 24, 2017
    @dingz 啊我语气太重了..
    limhiaoing
        32
    limhiaoing  
       Apr 24, 2017 via iPhone   ❤️ 1
    @rozbo
    auto a = std::make_unique<char[]>(0x1000);
    其实现代 C++不需要手动写任何的 new 和 delete 也能把内存资源管理得很好。
    举个例子 https://github.com/lxrite/DawnPlayer 是我写的一个 flv demuxer 涉及到大量的内存分配和释放,但是 C++部分的代码一个 delete 都没有写。
    rozbo
        33
    rozbo  
       Apr 24, 2017
    @limhiaoing
    @lrxiao
    @coderluan
    @gamexg
    @dingz
    提到 c++的内存,统一返回确实不是唯一的解决方案。
    但是各种对象具柄怎么办? c 语言怎么办?数据库连接怎么办?
    另外我问的是 char * a=(char*) malloc(0x1000);这种怎么办,请正视问题,不要改写这一段。
    难道你们写代码的时候,真的是从来不用 malloc ?
    limhiaoing
        34
    limhiaoing  
       Apr 24, 2017 via iPhone
    @rozbo
    http://en.cppreference.com/w/cpp/memory/unique_ptr
    sto::unique_ptr 的 deleter 是可定制的,你想释放其他资源定制下 deleter 就可以了。
    另外 不明白你是什么需求非得用 malloc 而不能用 std::make_unique 。
    limhiaoing
        35
    limhiaoing  
       Apr 24, 2017 via iPhone
    上面的链接有用 std::unique_ptr 管理文件资源的例子。
    limhiaoing
        36
    limhiaoing  
       Apr 24, 2017 via iPhone
    @rozbo
    忘了回答你最后一句了,我写代码确实从来不用 malloc 。
    Ouyangan
        37
    Ouyangan  
       Apr 24, 2017
    java-->遇到要返回的话直接就返回 ,避免后面很多 if 判断
    htfy96
        38
    htfy96  
       Apr 24, 2017
    @rozbo
    1. 对象句柄封装下 unique_ptr
    2. C 本来就是另一种语言
    3. 数据库连接也可以啊:参见 https://github.com/cruisercoder/cppstddb/blob/master/src/cppstddb/mysql/database.h#L104
    4. auto a = std::unique_ptr<char[]>(new char[0x1000])
    5. 基本不用
    sciooga
        39
    sciooga  
       Apr 24, 2017 via Android
    提前返回一般有更好的可读性
    usbuild
        40
    usbuild  
       Apr 24, 2017
    C++中不需要 malloc ,甚至有些情况下连 new/delete 都不需要,一般 vector 就够用了。
    jhdxr
        41
    jhdxr  
       Apr 24, 2017
    php/java: 取决于具体情况,但能够提前返回的时候绝对不会硬拖着到最后再统一返回(例如函数开头的异常情况判断)。
    至于资源回收,不熟悉 c++不敢随便说话,但是 php/java 都可以通过 finally 来解决
    Observer42
        42
    Observer42  
       Apr 24, 2017
    提前返回,减少嵌套层数,参照 4 楼的

    c 没怎么写过, c++有 RAII ,而且自 11 以后 unique_ptr 可以少很多 new/delete ,性能基本不会是问题
    geelaw
        43
    geelaw  
       Apr 24, 2017
    ……不用 malloc 是不是没写过性能要求高的程序哇……用 vector 的更是,你们很理论计算机科学,常数统统扔掉

    @rozbo 这个问题很简单,你可以

    char *a = (char *)malloc(0x1000);

    struct _free_a_tag
    {
    char const *ptr;
    _free_a_tag(char const *p) : ptr{p} { }
    ~_free_a_tag() { free(ptr); }
    } _free_a = a;

    用得多就 refactor 一个结构到外面去咯。

    如果你有一个 handle ,你可以写一个关闭 handle 的类似的玩意儿
    geelaw
        44
    geelaw  
       Apr 24, 2017
    @geelaw 更正:把 char const * 改成 char * const
    zacard
        45
    zacard  
       Apr 24, 2017
    尽量提前返回
    limhiaoing
        46
    limhiaoing  
       Apr 24, 2017 via iPhone   ❤️ 2
    @geelaw
    真不知道说你什么好,性能高必须用 malloc ?
    高性能程序都是用内存池的好吗?
    另外 vector 有性能问题是你不会用。
    jarlyyn
        47
    jarlyyn  
       Apr 24, 2017
    看这个帖子发现 go 的 defer 真是疼程序员
    changwei
        48
    changwei  
       Apr 24, 2017 via Android
    看是写什么代码,像 golang 等语言有 defer 关键词,各种提前返回可能会导致逻辑上的混乱,还是统一返回比较好。毕竟偷懒和优雅二者不可得兼。
    geelaw
        49
    geelaw  
       Apr 24, 2017
    @limhiaoing 我应该更正为“只用 new/delete 和 vector<T>”,本意当然不是只能用 malloc ,比如你还可以 calloc ,或者 VirtualAlloc 。

    另外如果希望提高 vector 的性能,需要写自己的 allocator (避免愚蠢的 new ,通常的实现),然后调用一次 reserve ,再祈祷编译器可以帮你把那些抽象都返朴归真(好在大多数编译器都可以搞定);反正我是不觉得在性能密集场景下 vector 比脱掉 vector 高明多少——如果要求期间不发生内存重新分配,那 vector 还有什么价值呢?
    xiubin
        50
    xiubin  
       Apr 24, 2017
    不说使用场景的都是耍流氓吧

    判断合法,不合法直接返回 nil :
    if (para1 == nil) return
    if (para2 == nil) return
    if (para3 == nil) return

    // para ...

    return ...

    根据不同条件会有不同结果:

    id result;
    if ..
    result = ..
    else if ..
    result = ..

    return result
    ldp940622
        51
    ldp940622  
       Apr 24, 2017
    自从使用了 swift ,就比较习惯使用 gurad 和 defer 了
    sagaxu
        52
    sagaxu  
       Apr 24, 2017
    @jhdxr Java7 开始都用 try-with-resource 了,不用在 finally 里 close
    sagaxu
        53
    sagaxu  
       Apr 24, 2017
    @changwei 你知道 defer 是干什么用的吗?就是为了提前返回的时候不让你忘记清理工作。有 defer 反而更适合提前返回。
    xiaowangge
        54
    xiaowangge  
       Apr 24, 2017
    游戏行业的表示,一般来说,编码风格都是强制的提前返回 :-)
    bumz
        55
    bumz  
       Apr 24, 2017
    提前返回
    jhdxr
        56
    jhdxr  
       Apr 24, 2017
    @sagaxu 多谢,之前还真没注意到这个特性。。。比 finally 写着优雅多了。
    0915240
        57
    0915240  
       Apr 24, 2017
    orderc
        58
    orderc  
       Apr 24, 2017 via iPhone
    提前返回,不用加一大堆 if else
    mb4555
        59
    mb4555  
       Apr 24, 2017 via Android
    提前
    ldp940622
        60
    ldp940622  
       Apr 24, 2017 via iPhone
    @ldp940622 gurad -> guard
    ivvei
        61
    ivvei  
       Apr 24, 2017 via Android
    看心情吧…
    shijingshijing
        62
    shijingshijing  
       Apr 24, 2017
    嵌入式里面,这种直接是真值表套状态机的, Guard Clauses 写代码的时候是爽了,测试和 MC/DC 覆盖率分析的时候分分钟教做人。
    kongkongyzt
        63
    kongkongyzt  
       Apr 24, 2017 via Android
    提前返回,并且尽量提前返回。
    mingyun
        64
    mingyun  
       Apr 24, 2017
    尽早 return
    zoffy
        65
    zoffy  
       Apr 24, 2017
    提前
    loveyu
        66
    loveyu  
       Apr 25, 2017
    提前吧,至少把错误判断提前,如果觉得复杂就 try_catch ,否则真的很难理解。
    RqPS6rhmP3Nyn3Tm
        67
    RqPS6rhmP3Nyn3Tm  
       Apr 25, 2017 via iPad
    我这里禁止提前返回,因为会要求 proof 。
    MajorAdam
        68
    MajorAdam  
       Apr 25, 2017
    肯定提前
    fanqsh123
        69
    fanqsh123  
       Apr 25, 2017
    int luaGetStringMd5(lua_State* L)
    {
    int nResult = 0;
    BOOL bRet = false;
    char szMd5[64];
    const char* pszString = NULL;

    TRY_GETSTRING(pszString, 1);

    bRet = GetStringMD5(szMd5, pszString);
    XYLOG_FAILED_JUMP(bRet);

    lua_pushstring(L, szMd5);
    ++nResult;

    Exit0:
    return nResult;
    }


    goto 挺好用的
    dogfeet
        70
    dogfeet  
       Apr 25, 2017
    @geelaw 既然都是自己 malloc 了,那操作这块内存的时候大小一定是自己很自信了。实在看不出 vector<uchar> 额定大小再操作 data 比你上面的写法性能低效在哪里,至少肯定不会是比 malloc 低。
    lance26
        71
    lance26  
       Apr 25, 2017
    @shijingshijing 可以给段代码看看吗?想学习下
    wayslog
        72
    wayslog  
       Apr 25, 2017 via Android
    @rozbo 看来你不用 RAII 啊…都什么年代了写 C++还手动管理内存?当然了,写 C 的无解了…
    rogerchen
        73
    rogerchen  
       Apr 25, 2017 via Android
    @wayslog
    一看那哥们就是写 C 的,连 C with class 都算不上, RAII 管理外部资源这种常识都不知道。
    allgy
        74
    allgy  
       Apr 25, 2017
    提前返回
    geelaw
        75
    geelaw  
       Apr 25, 2017
    @dogfeet 啊我突然发现“ vector 的价值”了 - - 就是自动回收内存(为啥说着说着连最初的目的都忘掉了逃
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   3369 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 132ms · UTC 12:13 · PVG 20:13 · LAX 05:13 · JFK 08:13
    ♥ Do have faith in what you're doing.