重构 Java 屎山代码的一种妄想,大佬们评估一下 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
这是一个专门讨论 idea 的地方。

每个人的时间,资源是有限的,有的时候你或许能够想到很多 idea,但是由于现实的限制,却并不是所有的 idea 都能够成为现实。

那这个时候,不妨可以把那些 idea 分享出来,启发别人。
wellR
V2EX    奇思妙想

重构 Java 屎山代码的一种妄想,大佬们评估一下

  •  
  •   wellR 2024-05-27 11:43:11 +08:00 2901 次点击
    这是一个创建于 501 天前的主题,其中的信息可能已经有所发展或是发生改变。

    前提:

    • 假设能在 java 运行期记录方法执行轨迹

    场景:

    • 接手的代码需要加入新功能,有重构老代码的需求,
    • 比如现在有方法 method ,这个方法承担 4 个业务,代码混乱/耦合严重
    • 想将 method 拆分为 4 个,记作 method_1/method_2/method_3/method_4
    • 人工去读代码痛苦且低效,期望可以使用代码完成拆分

    理论:

    1. java 方法在编译期会生成 AST ,每个代码结构对应语法树中的节点 node ,AST 的分支也就对应方法的代码分支逻辑,比如 if/else 结构表现在 AST 中就是一个分叉,会有两个子分支
    2. 记录一次方法调用中所有执行过的 node ,这些 node 的集合 nodes 就是这次调用实际执行的代码分支
    3. 可以将 nodes 转换为代码,就是这次调用的源码

    问题

    • 如何在 java 运行期标注出某一个方法调用过程实际执行过的 AST 节点集?
    • AST 的节点集如何转化为可执行的代码?
    18 条回复    2024-05-30 10:07:08 +08:00
    monmon
        1
    monmon  
       2024-05-27 14:02:24 +08:00
    感觉你在找的可能是 Intellij Profile ? By the way...如果你这个 method 的执行效率不是特别离谱,没人吐槽它慢,业务能跑最好别去动它,屎山这玩意谁沾谁脏
    jamel
        2
    jamel  
       2024-05-27 14:04:42 +08:00
    链路追踪?
    yuanmomo
        3
    yuanmomo  
       2024-05-27 14:17:50 +08:00 via iPhone
    当年红岭创投重构.Net 到 Java ,花钱请了阿里的外援,全线使用阿里云。当时预计半年能搞完,我给他们预计的是,一年都搞完就不错了。结果最后花了一年多,上线的时候预计 8 小时,最后好像接近 20 小时吧。

    一个项目,要重构,太多的先决条件了,最重要的就是测试覆盖率。如果测试用例不够,我是绝逼不重构的。
    wellR
        4
    wellR  
    OP
       2024-05-27 14:17:55 +08:00
    @jamel 嗯,与链路追踪很相似,颗粒度更小,细致到表达式,到某行代码的追踪
    wellR
        5
    wellR  
    OP
       2024-05-27 14:20:58 +08:00
    @yuanmomo 对对, 要有完备的测试用例与懂业务的人协助,否则没完没了
    wellR
        6
    wellR  
    OP
       2024-05-27 14:28:42 +08:00
    @monmon 接手的项目,没有文档,反而要我们开发读源码输出文档,性能不是问题。有出那么些接口负责多种业务,一堆一堆的逻辑分支,头疼,开 debugger 才勉强搞明白些。说起来 java 的 Debugger 应该是能拿到我的“代码追踪”数据的,怎么才能拿到呢
    jamel
        7
    jamel  
       2024-05-27 14:37:22 +08:00   1
    阿里云的 arms 可以到方法 到类,还有性能数据,很像火焰图了
    Dream95
        8
    Dream95  
       2024-05-27 14:40:13 +08:00   1
    Jacoco ?
    wellR
        9
    wellR  
    OP
       2024-05-27 15:11:59 +08:00
    楼上的回答启发我了,这跟单元测试中的代码覆盖率很接近啊,只不过目标不一样,我是为了抽离代码,关注指定方法在指定输入下的实际执行的代码,而排除其它的逻辑分支的视觉干扰,降低心智负担。
    monmon
        10
    monmon  
       2024-05-27 15:17:47 +08:00
    idea 的 SequenceDiagram 插件应该可以满足你的需求
    monmon
        11
    monmon  
       2024-05-27 15:20:58 +08:00   1
    @monmon SequenceDiagram 可以解决问题一自动分析出代码的所有调用过程,但是你想要代码自动拆分 method ,这个可能不太好实现
    wellR
        12
    wellR  
    OP
       2024-05-27 15:53:13 +08:00
    @monmon 好的,多谢回复,我去了解了解
    5800X3D
        13
    5800X3D  
       2024-05-27 20:04:26 +08:00
    <<精简代码实战:核心系统缩减 80%代码>>
    https://mp.weixin.qq.com/s/30PHdlnGZ4lGm3H5VeLRWQ
    以前看过的一个文章和你说的很像,也是经过一个月的随机采样,采集到 46 万流量,以此来对系统代码进行染色,得到有效函数
    SoloCompany
        14
    SoloCompany  
       2024-05-28 00:58:13 +08:00
    实际上最简单的做法是把 method 直接复制 4 份, 然后把流程控制变量变成常量, 利用 IDE 静态分析删除 dead code, 剩余的 duplicate code 通常也能被分析出来, 根据提示 extract method
    wellR
        15
    wellR  
    OP
       2024-05-28 09:43:55 +08:00
    @ukpkmk 谢谢了,文章我看过了,“代码染色”很贴切的描述
    tikazyq
        16
    tikazyq  
       2024-05-29 22:35:27 +08:00
    用图论去解决屎山问题固然很酷,但投入产出比不一定值得,特别是需要重构的代码量没到一定量级的时候。几十百来个文件需要重构的话,可能还不如人海战术重写逻辑。

    还有,现在 GPT 都这么大窗口了,直接扔进去加合理的 prompt 理论上也可能有低成本的收获。

    最后,养成良好的编程习惯和团队文化(例如 TDD 、代码审核),比硬啃屎山更有效和稳定。屎山代码产生的根本原因,通常来自于急功近利的老板和不够负责的技术领导。
    wellR
        17
    wellR  
    OP
       2024-05-30 09:43:30 +08:00
    @SoloCompany 这也是个法子
    wellR
        18
    wellR  
    OP
       2024-05-30 10:07:08 +08:00
    java 的 debugger 能获取的信息很丰富,似乎可以支撑代码分割或者代码染色的实现
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     956 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 19:23 PVG 03:23 LAX 12:23 JFK 15:23
    Do have faith in what you're doing./span>
    ubao 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