8 层嵌套, 400 多行代码的函数。。。 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
asanelder
V2EX    程序员

8 层嵌套, 400 多行代码的函数。。。

 
  •   asanelder 2020-06-09 21:13:10 +08:00 10751 次点击
    这是一个创建于 2004 天前的主题,其中的信息可能已经有所发展或是发生改变。

    遇到一个老的项目,有一个函数是 8 层嵌套,if 套 while 再套 if 再套 while 再套 if ....,而且每个条件判断中,各种&& 套 || 再套 &&,这个 8 层嵌套俺数了一下,一共 400 多行代码。。。

    让俺感觉到奇怪的是,之事从事这个项目的老员工对这个函数竟然没有丝毫的意见,他们似乎很平静。

    那么问题来了,俺之前受的教育是,函数应该尽量短小,嵌套应该尽量浅。所以遇到这个函数俺自然感觉浑身不适,但那些老员工似乎都很平静。是俺太笨了,理解不了这种 8 层嵌套,还是俺太矫情,太理想主义了,太教条了,还是老员工已经习惯了?

    求解惑

    第 1 条附言    2020-06-10 14:38:00 +08:00
    看到老铁们的回复,俺释然了,原来俺这种情况不是个例,心态平静了很多
    96 条回复    2020-06-15 15:50:59 +08:00
    lmmortal
        1
    lmmortal  
       2020-06-09 21:14:50 +08:00 via iPhone
    老员工见怪不怪了,这种东西谁都懒得动。动好了没好处,动坏了就捅破天了所以都不愿意动
    singerll
        2
    singerll  
       2020-06-09 21:15:56 +08:00 via Android   8
    你改了呗,以后系统有问题甭管是啥原因,第一个怀疑的就是你改的代码的问题,让你好好查个遍再查其他
    luckyrayyy
        3
    luckyrayyy  
       2020-06-09 21:18:44 +08:00
    首先你得看好不好改啊,是不是确实极其复杂,不好下手?
    或者说里面其实有大量裁剪,不一定复杂多真的这么高,这么写只是为了好理解?
    另外从事这个项目的老员工都接手过这一块的逻辑吗?说不定人家负责别的模块见都没见过这里的代码?
    最后都没问题的话,你改呗...即优化了代码,又满足了自己强迫症,多好啊。
    asanelder
        4
    asanelder  
    OP
       2020-06-09 21:21:39 +08:00   2
    @lmmortal
    @singerll

    关键是有个功能要在这基础上改,俺修改的时候瑟瑟发抖,生怕改坏了(注意,这个函数没有相关测试)

    这感觉就像是拿着一个很脆弱的易碎品,生怕摔了。
    又像是你去蹲坑,发现停水很久了,坑里已经被 S 塞满了,而你不得不忍着恶心蹲下
    asanelder
        5
    asanelder  
    OP
       2020-06-09 21:23:11 +08:00
    @luckyrayyy #3 看了一下 git 记录,有 6 个人修改过,其中 4 个已经离职,还有 2 个健在。。。
    td width="auto" valign="top" align="left">
        6
    prenwang  
       2020-06-09 21:24:19 +08:00   2
    没事的, 反正蹲下拉出来的也是 s
    prenwang
    asanelder
        7
    asanelder  
    OP
       2020-06-09 21:25:04 +08:00
    @prenwang #6 这话俺看听
    dswyzx
        8
    dswyzx  
       2020-06-09 21:28:54 +08:00
    敢承担后果就敢上手搞 bug
    无非就是修 bug 嘛
    786375312123
        9
    786375312123  
       2020-06-09 22:11:29 +08:00
    如果是 legacy code 就不要动,如果需要维护的话其实问一问改过的同事,也没什么大不了的。你们又不是微软,能遇到 80 年代写的代码。
    silvernoo
        10
    silvernoo  
       2020-06-09 22:20:46 +08:00   1
    flutter 表示 8 层嵌套根本不叫事
    miao666
        11
    miao666  
       2020-06-09 23:31:35 +08:00 via Android
    黑猫白猫,能跑就是好猫
    asanelder
        12
    asanelder  
    OP
       2020-06-09 23:32:02 +08:00
    @silvernoo #10 还没开始学 flutter,表示十分期待
    x86
        13
    x86  
       2020-06-10 00:26:59 +08:00 via iPhone
    没问题就不要改,要改就准备好出问题背锅的准备…
    Vegetable
        14
    Vegetable  
       2020-06-10 00:47:16 +08:00   15
    他们可能也年轻过,迷茫过,尝试过,服了。
    charlie21
        15
    charlie21  
       2020-06-10 00:58:33 +08:00
    应该该成状态机
    xstmjh
        16
    xstmjh  
       2020-06-10 01:01:53 +08:00
    一看就是没测试
    XanderChen
        17
    XanderChen  
       2020-06-10 04:05:52 +08:00 via Android
    我倒是觉得 if while 与或非各种嵌套的代码挺好改的,

    你用文本的形式或者思维导图把所有情况列出来就行了,按图索骥呗。
    ericgui
        18
    ericgui  
       2020-06-10 04:24:34 +08:00
    从理论上说,你应该改。从现实上,你先问问老板,然后再考虑下一步。
    IllBeBack
        19
    IllBeBack  
       2020-06-10 05:46:37 +08:00   4
    这么多逻辑写在一起在 Debug 的时候可能还清晰一点,IDE 都有 if else 及 while 的折叠功能,功能区块还可以用 region 包起来,说不定还很直观。

    如果拆成 N 个函数,Debug 的时候东跳西跳可能完全理不清头绪。理论上函数应该尽量短小,但实际上要看好不好 Debug,好不好理解。

    也就 400 行,你可以试着理一下,如果不是把一屎变成 N 屎,那就可以跟领导邀功了。
    Tony042
        20
    Tony042  
       2020-06-10 07:26:13 +08:00
    试下 matlab 的 state flow?貌似挺有效解决这类问题的
    evilic
        21
    evilic  
       2020-06-10 08:03:34 +08:00
    干好事有好报没?
    lasuar
        22
    lasuar  
       2020-06-10 08:12:06 +08:00
    这个一般是传承下来的,你要改它,准备好加班和挨骂的风险。
    isnullstring
        23
    isnullstring  
       2020-06-10 08:18:59 +08:00   1
    改出问题还得挨骂,改好了好像也不会加薪
    SO
    Vitta
        24
    Vitta  
       2020-06-10 08:19:46 +08:00 via iPhone
    我见过 7000 行的
    whywhywhy
        25
    whywhywhy  
       2020-06-10 08:20:29 +08:00   3
    偷偷的重新编写它,然后反复测测测,确保行为一致。然后找一个黄昏的早晨,轻轻的替换掉它。
    JieS
        26
    JieS  
       2020-06-10 08:24:10 +08:00 via iPhone   3
    @whywhywhy "你好骚啊"
    chaodada
        27
    chaodada  
       2020-06-10 08:30:52 +08:00 via iPhone
    这算啥,年前写了一个功能,整体用十几个函数实现,最大的函数 1300 行,上个月功能大还,我又将它拆分成了三个递归函数,这种函数一般功能不变,不会动的,动一动,公司就倒闭了
    butterf1y
        28
    butterf1y  
       2020-06-10 08:31:21 +08:00
    @whywhywhy 又是一个不眠夜
    littleshy
        29
    littleshy  
       2020-06-10 08:36:42 +08:00   1
    严以律己,宽以待人。
    fxxwor99LVHTing
        30
    fxxwor99LVHTing  
       2020-06-10 08:42:06 +08:00
    除非有问题,否决千万不要动。
    rhwood
        31
    rhwood  
       2020-06-10 08:51:59 +08:00
    默默地看了一下我写的一个 200 行的函数,能用就好,自己都懒的改
    anteros
        32
    anteros  
       2020-06-10 08:57:17 +08:00
    这或许是他们的生存智慧呢?也说不定的
    wanzi123
        33
    wanzi123  
       2020-06-10 09:04:38 +08:00
    前几天经历了一个方法里 5 层 for 循环哈哈
    hejw19970413
        34
    hejw19970413  
       2020-06-10 09:07:31 +08:00
    远古代码 尽量不要动
    CodingNaux
        35
    CodingNaux  
       2020-06-10 09:08:03 +08:00 via iPhone
    千万别动,哪怕格式化一下,留下 commit,以后 blame 出来都找你
    smallyu
        36
    smallyu  
       2020-06-10 09:09:05 +08:00
    我刚毕业的时候也这么想,各种代码规范,应该怎样应该怎样。后来遇到了一个多月一个 crud 项目的需求,而且中间需求变了三四回,道貌岸然敏捷开发,基本上重写三四回。
    dabang007
        37
    dabang007  
       2020-06-10 09:11:26 +08:00
    我做毕业设计时候,看到师兄的 VC 代码,总共 1W 多行,但其中一个函数就 8000 多行....
    zzzmh
        38
    zzzmh  
       2020-06-10 09:13:48 +08:00
    这才哪到哪,我在外包打杂的时候,随便一个 js 都是几千行,连 function 都不一定有,就见面先怼个 2000 行逻辑。。。还见过 for 循环一万次,然后得到的值被注释了,没起到任何作用。
    jorneyr
        39
    jorneyr  
       2020-06-10 09:16:54 +08:00
    IBM Domino 有个核心函数的代码有 1 万多行呢,脱离了业务逻辑谈代码,不敢随意下定论。
    xiaoyang7545
        40
    xiaoyang7545  
       2020-06-10 09:18:37 +08:00
    如果是函数内的东西随便他里面怎么搞。能得到正确结果就是了。如果是流程的话就比较恶心。后面要是有需求变化就难改。
    dog82
        41
    dog82  
       2020-06-10 09:21:31 +08:00
    你能把它改成 3 层吗?不行就不要动
    cxknmsl
        42
    cxknmsl  
       2020-06-10 09:23:49 +08:00
    @zzzmh,牛批,这场面真没见过
    Hallelu
        43
    Hallelu  
       2020-06-10 09:25:19 +08:00
    我们公司很多函数都在一两千行,各种业务逻辑判断。
    neroransom
        44
    neroransom  
       2020-06-10 09:28:55 +08:00 via Android
    这种 if else 又不是一个人写出来的,有时和完全重构相比,直接加一个 else 才是最优选项。
    lyz1990
        45
    lyz1990  
       2020-06-10 09:33:31 +08:00
    手上维护的项目,1000 行以上的函数五六个吧,所有的历史作者都离职了。
    zhuweiyou
        46
    zhuweiyou  
       2020-06-10 09:35:00 +08:00
    几千上万行一个文件,都是很正常的事情,大惊小怪?
    yuchenyang1994
        47
    yuchenyang1994  
       2020-06-10 09:36:43 +08:00
    我见过 3000 行的
    fhsan
        48
    fhsan  
       2020-06-10 09:37:45 +08:00
    代码 commit+1,离职+1,成为老坑
    adimn
        49
    adimn  
       2020-06-10 09:52:19 +08:00   1
    关键是有个功能要在这基础上改,俺修改的时候瑟瑟发抖,生怕改坏了(注意,这个函数没有相关测试)

    这感觉就像是拿着一个很脆弱的易碎品,生怕摔了。
    又像是你去蹲坑,发现停水很久了,坑里已经被 S 塞满了,而你不得不忍着恶心蹲下



    以前同事也是这么想的,可能原先只有七层嵌套, 他怕改出问题,一个稳妥的办法,八层嵌套
    dfourc
        50
    dfourc  
       2020-06-10 09:56:46 +08:00
    那就再加一层 if #滑稽
    mbtfdwlx
        51
    mbtfdwlx  
       2020-06-10 10:03:38 +08:00
    我在维护老项目时候遇到过这种情况,稳妥一些的办法,首先要在原来的基础上做好新需求。上线后再把原来的代码一点点重写掉,扔到测试服,多测试,最后体验服跑上一段时间后没问题,就可以上线了...
    statement
        52
    statement  
       2020-06-10 10:03:56 +08:00
    如果你在这家公司待了三年以上,可以考虑重现一个实现替换,但也别改。
    如果你刚来这家公司,且不是大牛。有这种想法可以但最好别和别人说。
    vevlins
        53
    vevlins  
       2020-06-10 10:04:39 +08:00
    四百多行我见过有二十个 ifelse 的,有时候代码烂是工期、需求、技术人员多方面一起造成的,有它的历史背景在。 如果要改就找个工期宽裕的,测试愿意配合,加上单测。
    whypool
        54
    whypool  
       2020-06-10 10:10:30 +08:00
    事实证明代码洁癖要不得
    如果再加一个需求,你还是会用 if,再去嵌套
    Doracis
        55
    Doracis  
       2020-06-10 10:11:34 +08:00
    我可能就是写了八层 if else 的程序员,没办法,开发周期短,需求变更频繁,本来我都计划的好好地,用一个 if else 解决,谁知甲方中途加需求改设计方案,后台加字段加状态加各种 flag,我也抓狂啊

    不过好在每次写 if else 我都会留下注释,为什么加每一层判断以及要干嘛这种的,算是方便后期维护吧,毕竟代码放了三个月再看,亲妈都不认识了

    这种代码俗称屎山,屎山不是一日堆成的,你要想撬动屎山就做好被屎淹没的勇气,撬不动就再堆点屎,浮冰之下用户也看不到屎山,再说了就大部分程序员的这个代码水平,芳古流传不可能了,十七八年基本就会整体换一代框架, 没必要,真的没必要
    micean
        56
    micean  
       2020-06-10 10:20:16 +08:00
    老纠结嵌套和行数,不如写上注释,啥都不是事
    jasonding
        57
    jasonding  
       2020-06-10 10:25:44 +08:00   1
    想起我写的一个类,1400 行,其中一个函数是 excel 导入,差不多占了近千行。两个 sheet,涉及 7 层数据结构,sheet1 是前四层,sheet2 是后四层,其中一个是映射层,这是基础数据结构。然后还有 excel 模板校验、实际数据格式校验、脚本逻辑校验、穷举遍历、组合计算、数据入库等实际业务逻辑。总共改版三次,其中第三版是兼容版,要求兼容老的 excel 模板,同时支持新的 excel 模板导入,我 TM 都快疯了。
    codergrowing
        58
    codergrowing  
       2020-06-10 10:28:39 +08:00
    8 层算什么,前一段接了一个项目,一个函数嵌套层级有 12 层……真的是理逻辑理到怀疑人生
    zhangyangkam1
        59
    zhangyangkam1  
       2020-06-10 10:44:33 +08:00
    从某种意义上来说写个十几层嵌套也不出错一直用下来也算挺厉害的
    tremblingblue
        60
    tremblingblue  
       2020-06-10 10:48:11 +08:00
    所以一个 if 上去保平安 然后下个月再加一个.
    nightwitch
        61
    nightwitch  
       2020-06-10 10:56:32 +08:00
    能打断点的话,if-else 的 400 行的函数还算凑合吧,搞清楚哪个分支会在什么情况进入就行了,if-else 多了就是作用域比较讨厌,debugger 可以帮你看到当前作用域可以看到哪些变量。

    如果你的业务代码需要用 400 行代码来描述,你拆成小函数也是差不多的,一样要走不同的分支,在不同的小函数里跳来跳去。
    Cmdhelp
        62
    Cmdhelp  
       2020-06-10 10:56:59 +08:00
    改一个公司倒闭
    wayslog
        64
    wayslog  
       2020-06-10 11:51:23 +08:00
    我就不说我曾经维护过一个 1k+行的 python 函数。。。参数十几个,还有 *args **kwargs 。。。我花了一个月才读通它的逻辑。。。
    vcode
        65
    vcode  
       2020-06-10 12:04:21 +08:00
    你是新手啊
    zyy314680012
        66
    zyy314680012  
       2020-06-10 12:09:36 +08:00 via Android
    如果是我,肯定不改
    mwftts
        67
    mwftts  
       2020-06-10 12:16:43 +08:00 via Android
    所以一直很好奇怎么才能优化这种,非专科,只是偶尔也会看到类似的代码,SAP 中
    mwftts
        68
    mwftts  
       2020-06-10 12:20:13 +08:00 via Android
    所以一直很好奇怎么才能优化这种,非专科,只是偶尔也会看到类似的代码,SAP 中
    bxb100
        69
    bxb100  
       2020-06-10 12:32:59 +08:00
    没有单测和边缘测试不要改
    wangyzj
        70
    wangyzj  
       2020-06-10 12:33:35 +08:00   1
    代码行数,复杂度和是否可优化没半毛钱关系
    业务拆分和是否能复用才是
    winglight2016
        71
    winglight2016  
       2020-06-10 12:52:21 +08:00
    哈哈哈,400 行还真不算多,我写过 4000 多行的代码,就是为了根据规则计算支付金额,业务逻辑太复杂,没有更好的办法。
    celeron533
        72
    celeron533  
       2020-06-10 13:18:35 +08:00
    会不会以前是 16 层嵌套,800 行代码。。。
    hu8245
        73
    hu8245  
       2020-06-10 13:54:42 +08:00
    如果逻辑清晰也没什么不合适的吧,当然从维护性来说,是下降了。
    justin2018
        74
    justin2018  
       2020-06-10 14:16:05 +08:00   1
    ![xNfesUX]( ) 想到了这个图
    sigl0p
        75
    sigl0p  
       2020-06-10 15:23:55 +08:00
    400 行不算长的,我接手过 C C++ 函数动则几千行
    la2la
        76
    la2la  
       2020-06-10 15:34:49 +08:00
    见过 java spring 一个类 7000+行的么?改一个标点符号就要备份
    Chowe
        77
    Chowe  
       2020-06-10 16:09:53 +08:00 via iPhone
    更可怕的是
    #if
    #else
    jsjgjbzhang
        78
    jsjgjbzhang  
       2020-06-10 16:40:02 +08:00
    想提升自己就去改 想给自己找麻烦就提交
    Keyes
        79
    Keyes  
       2020-06-10 17:24:13 +08:00
    @justin2018 哈哈哈读了一下竟觉得没毛病
    noobsheldon
        80
    noobsheldon  
       2020-06-10 17:24:46 +08:00
    楼主的帖子好喜欢用“俺”,总是让人想起《熊出没》里的熊二
    GopherTT
        81
    GopherTT  
       2020-06-10 18:12:33 +08:00
    @noobsheldon hhah 特地数了下 八个:)
    KasonPasser
        82
    KasonPasser  
       2020-06-10 18:22:28 +08:00
    好想见识一下,我一般都是复制一个新的函数出来改,原来的能不动尽量不动。
    改完了测试没问题再迁移,不过一般出问题了都是没有好结果。
    确实想改送你六个字:慎之慎之慎之。
    deplives
        83
    deplives  
       2020-06-10 18:29:07 +08:00
    我见过一个实习生写的 Python request handle 多达 1500 多行,仔细一看,他一个 handle 处理了 get post put delete 不同请求
    w516322644
        84
    w516322644  
       2020-06-10 18:43:21 +08:00
    @justin2018 你是不是在黑 php,我遇见过 java 这么类似写的。
    asanelder
        85
    asanelder  
    OP
       2020-06-10 18:46:50 +08:00
    @codergrowing #58 哈哈,笑尿了
    zuokanyunqishi
        86
    zuokanyunqishi  
       2020-06-10 18:58:30 +08:00 via Android
    你是没见过 800/1500 行的函数
    cwek
        87
    cwek  
       2020-06-10 20:52:45 +08:00
    没坏,别动
    akira
        88
    akira  
       2020-06-10 20:56:27 +08:00
    老员工都知道 这种代码不能动,一动就必然会死人.
    sampeng
        89
    sampeng  
       2020-06-11 07:28:14 +08:00 via iPhone
    去年这类帖子出来还是尽量自己慢慢重构了。除非是算法类,普通逻辑类的大函数就没有改不掉的。是会有风险,现在程序员都居安思危到这个地步了?太可怕了…
    codingbody
        90
    codingbody  
       2020-06-11 08:05:54 +08:00 via iPhone
    spring jdbctemplate 中 setvalue 方法 200 多行全是 if else else if
    soulmt
        91
    soulmt  
       2020-06-11 08:56:55 +08:00
    不要慌,常见操作, 老代码别动就对了
    Daniel17
        92
    Daniel17  
       2020-06-11 13:42:34 +08:00
    一个 switch800 行的见过没。。还全部写在 controller 层
    royan
        93
    royan  
       2020-06-11 14:08:42 +08:00
    补测试,动手改。大不了跑路,怕什么[狗头 /摊手]
    wisetc
        94
    wisetc  
       2020-06-13 11:09:17 +08:00 via iPhone
    你如果能改并且保证不出问题也要看看做了这件事对谁有利,是否在为前人背锅,成为搏傻游戏里的傻人呢?如果要扩展,并且之前开闭原则都不遵守,这家公司的管理是不是有问题呢?这个问题是你的吗?
    EscYezi
        95
    EscYezi  
       2020-06-13 14:34:17 +08:00 via iPhone
    还真拆过一个 400 行的,按业务逻辑拆成了三个。后来有需求要在这块加东西,还好之前拆了,不然真的要吐
    ruzztok
        96
    ruzztok  
       2020-06-15 15:50:59 +08:00
    逻辑没有问题、不影响性能、没有复用价值的 1000 层又怎样??现实一点,不要看太多阿里巴巴的编程手册和一些编码规范之类的书
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5110 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 30ms UTC 08:03 PVG 16:03 LAX 00:03 JFK 03:03
    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