V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
midsolo
V2EX  ›  程序员

code review 把国外的同事气到吐血

  •  1
     
  •   midsolo · 3 天前 · 15005 次点击

    国外的同事来国内出差,趁着这个机会,邀请他跟我们一起进行 code review......

    公司的代码没办法拿出来,只能临时写个伪代码让大家鉴赏一下:

    /**
     * 代码鉴赏:执行 1 个任务
     */
    public class JavaTasteSample {
    
        public static void main(String[] args) {
    
            // 国外同事:1 行代码就搞定,简洁明了
            // ==(浪费了大量的时间在做过度设计,毫无意义的炫技)==
            new Thread(() -> System.out.println("task1 running...")).start();
    
            // 国内同事:高内聚低耦合,把具体要执行的任务跟线程进行分离,方便扩展......
            // ==(这老外太 low 了,连设计模式都不懂,估计不会写代码)==
            new Thread(new Task(new TaskInnerSupport())).start();
        }
    
    }
    
    interface TaskInner {
    
        void execute();
    
    }
    
    abstract class AbstractTaskInner implements TaskInner {
    
        @Override
        public void execute() {
            runTask();
        }
    
        abstract void runTask();
    
    }
    
    class TaskInnerSupport extends AbstractTaskInner {
    
        @Override
        public void runTask() {
            System.out.println("task2 running...");
        }
        
    }
    
    class Task implements Runnable {
    
        private TaskInner inner;
    
        public Task(TaskInner taskInner) {
            inner = taskInner;
        }
    
        @Override
        public void run() {
            inner.execute();
        }
    
    }
    
    第 1 条附言  ·  2 天前
    团队中有好几位热门开源项目的 contributor ,他们写业务代码也跟写中间件源码一样,导致代码中存在严重的过度设计,60% 以上的预留扩展点,估计等公司没了都用不上。

    他们代码写爽了,接手的人一看惨了,调个 "1+1" 的方法要经历一堆 "接口、抽象类、实现类、回调、各种设计模式......" 才能拿到 "2" 这个结果。

    这 2 种写法没有谁对谁错,一方水土养一方人,很明显国外的同事水土不服,不知道国内领导喜欢听一些装逼的名词,比如:"高内聚、低耦合、扩展性......"

    作为程序员,我内心赞成国外同事说的用第一种写法。1 行代码就搞定,简单明了,等到需要扩展的时候再去抽取不就行了。

    但作为 "国内的程序员",我也只能跟着用第二种写法了。没办法,国内领导喜欢第二种,如果你用 1 行代码就实现了,那领导会认为你工作过于简单,工作量极不饱和;而用第二种写法,各种设计模式绕来绕去的,没十天半个月根本看不懂,既能体现你技术上的不可替代性,又能提供足量的代码......
    第 2 条附言  ·  2 天前
    大家轻点喷,因为 review 的是 Java 项目,所以我写了 Java 伪代码来演示这种情况,直接用 Go 也没办法写出这样的代码,我本人也是 Java 转的 Go 。

    关于具体业务,其实很简单,也不太可能有后续的扩展,都是留给以后用的。目前整个项目的代码风格都是这样的,可以参考 Apache Dubbo 源码(微内核+插件化+SPI 扩展),因为团队里好几个大佬都是其前 committer 。
    136 条回复    2025-11-08 17:50:46 +08:00
    1  2  
    mb4555
        1
    mb4555  
       3 天前   ❤️ 1
    单看着一行代码 支持老外 你这个封装有没有在其他地方用到 用到了 另说
    mb4555
        2
    mb4555  
       3 天前
    @mb4555 也看你们的使用场景
    midsolo
        3
    midsolo  
    OP
       3 天前
    @mb4555 #1 没有用到,就是为了以后好扩展
    erlking
        4
    erlking  
       3 天前
    支持老外
    spike0100
        5
    spike0100  
       3 天前
    我发现工作中至少 40%以上的预计扩展逻辑以后都不会用到。
    lvtuyukuai
        6
    lvtuyukuai  
       3 天前   ❤️ 1
    可以扩展的时候改写成第二种,每次新加功能重构已有代码方便扩展
    visper
        7
    visper  
       3 天前   ❤️ 12
    有时候,我更愿意去看一下写得很原始很差的复制多个地方的代码。而不是封装得十多差怎么也理不清关系的代码。虽然说为了扩展性。但是好像十年过去了也没有什么扩展。
    LoNeZ
        8
    LoNeZ  
       3 天前
    看场景..和重要程度...
    sneezry
        9
    sneezry  
       3 天前
    按照我们公司之前的 review 风格,会支持国内同事的设计。现在一直在强调开发速度和营业额,没人在乎设计模式。
    ohoh
        10
    ohoh  
       3 天前
    为什么是国外的气到吐血了,国内的就不?这意思你已经明显站队了啊。

    防御/预防式开发没啥问题啊,只是度有多大的问题。
    xubeiyou
        11
    xubeiyou  
       3 天前
    现在都讲究迭代速度和健壮性 不会在看设计模式了 除非真的有必要
    askfilm
        12
    askfilm  
       3 天前
    反正双标呗....
    midsolo
        13
    midsolo  
    OP
       3 天前   ❤️ 7
    @spike0100 现在都是 流水式的员工 跟 快餐式的代码,绝大多数扩展逻辑都不会用到,如果换不同的人来接手,估计不会用上个人留下的扩展,会自己写一套
    NO9527
        14
    NO9527  
       3 天前
    我支持老外的,等这种设计模式狂魔的代码到你手里就老实了
    midsolo
        15
    midsolo  
    OP
       3 天前
    @ohoh 我同意老外的看法,我觉得前期没有必要做过度设计,需求一下来就建十几个类,接口抽象类搞个几层,再套设计模式,完全没必要啊
    stinkytofux
        16
    stinkytofux  
       3 天前
    支持老外, 这种预留的拓展没必要, 需要的时候再把代码抽出来就是了.
    winglight2016
        17
    winglight2016  
       3 天前
    java 代码就习以为常,见怪不怪,看看 spring 的代码就明白了,恨不得你一行代码都不写,全部搞成无代码平台
    MrPat
        18
    MrPat  
       3 天前
    支持老外,過度設計了,為了設計而設計,等你需要用到這個預留,可能你的代碼已經要重構了,
    96
        19
    96  
       3 天前   ❤️ 3
    Java 开发魅力时刻
    chenluo0429
        20
    chenluo0429  
       3 天前 via Android
    设计时预留实现扩展的可能性,不要堵死扩展的路就好。
    千万不要真的实现扩展,除非你真的知道这里短时间内需要扩展以及扩展的明确方向。
    midsolo
        21
    midsolo  
    OP
       3 天前
    @askfilm 没有双标,这段代码是同事写的,他也是前 dubbo contributor ,平时写代码喜欢炫技
    darksword21
        22
    darksword21  
    PRO
       3 天前   ❤️ 15
    这种我统称为被 java 污染了脑子(
    qping
        23
    qping  
       3 天前 via iPhone
    封了好几层每一层职责是什么?现在看起来什么事也没做,就是大肠包小肠
    chenluo0429
        24
    chenluo0429  
       3 天前 via Android
    绝大部分自以为是的扩展,最后根本用不上。其中大概一半多增加了不必要的复杂度,对相关开发造成困扰。一小部分会对后续的基于真实需求的扩展造成非常大的阻碍
    WithoutSugarMiao
        25
    WithoutSugarMiao  
       3 天前
    javaer 写代码考虑的真多。换成 python 的话,就没有这种烦恼,绝大部分 Pythonista 估计都会用第一种直来直去的写法。
    songco
        26
    songco  
       3 天前 via Android
    支持第一种

    以前设计模式流行的时候,公司有的代码特别恐怖,所有的地方都支持扩展,但是 99%其实就一种实现
    otakustay
        27
    otakustay  
       3 天前
    现在有 Coding Agent 了,这种场景就算未来发现有扩展了改一套设计,找个 Agent ,明显有特征的代码( new Thread )全部扫一遍重构成新的方案,不要太简单
    i8086
        28
    i8086  
       3 天前
    业务变化无法预知,不要过早优化,也不要过度设计。

    这段伪代码,对应业务是什么?没对应业务,那肯定越简单越好。
    zh6335901
        29
    zh6335901  
       3 天前
    抽象一般是你发现或者预见到了需要抽象的东西才去做,而不是自己去制造抽象
    midsolo
        30
    midsolo  
    OP
       3 天前
    @winglight2016 哈哈,团队里好几个前 dubbo contributor ,很多业务代码也参照了 dubbo 的设计,使用 微内核+插件化+SPI 扩展,就是过度设计
    beneo
        31
    beneo  
       3 天前   ❤️ 1
    @midsolo 得看看你们在做时间什么事情,业务代码肯定不能过度设计,但是核心模块可以
    cloudzhou
        32
    cloudzhou  
       3 天前
    这里两个写法看不出什么,如果是我的话,会将这个 Task 的逻辑,写到具体的 Service
    然后 TaskRunner 作为一个中间组件

    到这个程度的话:
    1. new Thread(() -> XXXService.DoSomething).start(); // 原生线程池,没有特殊处理
    2. TaskRunner.Run("doSomething", () -> XXXService.DoSomething); // 中间件封装

    为什么中间件封装:
    1. 统计,监控,日志
    2. 线程数量控制(即便是协程)
    3. 以后 TaskRunner 控制复杂调度(优先级,丢弃,限流...)

    如果你们是一个成熟的团队,本来就需要这些中间件,在这个基础上,都只是一个简单的方法调用而已
    cloudzhou
        33
    cloudzhou  
       3 天前
    #32 上面的 1/2 区别很小,对于团队的人来说接受度没什么区别,所以你们的问题是:
    复杂场景下,需要丰富中间件,而不是“按需开发中间件”,这样会增加其他团队成员的理解程度
    ppooqq
        34
    ppooqq  
       3 天前
    说个常见的,IService/ServerImpl ,我写了多年代码也没遇上几回需要多实现的场景,我重来都是直接一个 Service
    leegradyllljjjj
        35
    leegradyllljjjj  
       3 天前
    不好意思 我们是按代码量算钱的
    spike0100
        36
    spike0100  
       3 天前
    @midsolo #13 确实如此。有时候你写的扩展,对接手的人来讲只是累赘。
    superrichman
        37
    superrichman  
       3 天前
    啰里八唆的 JAVA 味道是这样的
    BingoXuan
        38
    BingoXuan  
       3 天前
    最好加上 pool 去调度,任务开始前,创建上下文注入 thread local 去隔离变量就够了
    sankemao
        39
    sankemao  
       3 天前
    平白无故添加了认知负荷,人的精力是有限的
    newInterface
        40
    newInterface  
       3 天前
    我还见过在 java 里写 kotlin 的
    cvooc
        41
    cvooc  
       3 天前
    java 程序员特有的留着以后扩展用(然而并没有扩展)
    alienx717
        42
    alienx717  
       3 天前   ❤️ 6
    claude code 给我写啥,就是啥,我不挑
    Cooooooode
        43
    Cooooooode  
       3 天前
    以前喜欢预留扩展,现在的工作基本是删除那些代码
    aloxaf
        44
    aloxaf  
       3 天前   ❤️ 1
    想起一个 Java 笑话:一个程序员遇到了问题,他打算用 Java 解决,现在他有一个 ProblemFactory 了
    xz410236056
        45
    xz410236056  
       3 天前
    看到 java 我就都明白了,干什么之前先来个接口
    guanhui07
        46
    guanhui07  
       3 天前
    JAVA 味道是这样的
    jsq2627
        47
    jsq2627  
       3 天前
    "Java 味"
    PaulSamuelson
        48
    PaulSamuelson  
       3 天前
    为了以后可能用到,做的预留。Linus 看了直接开骂。
    jsq2627
        49
    jsq2627  
       3 天前
    AI 时代,尽量把业务逻辑集中在一起,对 AI Agent 才是最友好的。可能要打破过去十几年形成的最佳代码实践了。
    willchen
        50
    willchen  
       3 天前
    业务代码的话(通用的基础架构另说),就别过度设计了,产品分分钟打破你
    midsolo
        51
    midsolo  
    OP
       3 天前
    @darksword21 确实有点,我从 Java 转 Go 的时候,大概好几个月思想才慢慢转变
    midsolo
        52
    midsolo  
    OP
       3 天前
    @qping 确实什么都没做,是留着以后扩展的
    midsolo
        53
    midsolo  
    OP
       3 天前
    @i8086 没什么业务,留着以后扩展,后续可能会用到
    midsolo
        54
    midsolo  
    OP
       3 天前
    @cloudzhou #32 纯业务代码,团队中有一些开源项目的 contributor ,平时喜欢这样写
    midsolo
        55
    midsolo  
    OP
       3 天前
    @willchen 赞成,之前做过电商平台的营销系统,需求多变,朝令夕改,有时候上午出需求,晚上就得上线
    akakidz
        56
    akakidz  
       3 天前
    单从这里看,我觉得都没问题,还要看具体场景
    liaohongxing
        57
    liaohongxing  
       3 天前
    有用 lambda 的一律支持 ,支持第一种
    wangguyu
        58
    wangguyu  
       3 天前
    支持第一种,等要扩展的时候再复制一下代码改成第二种,没必要过度设计。
    cubecube
        59
    cubecube  
       3 天前
    AI 都会 refactor 了,何必浪费时间绕来绕去。
    simpleman
        60
    simpleman  
       3 天前
    问一下, 如果是内部的代码,有必要写成这样子吗? 业务拓展了内部重构不就行了?
    msaionyc
        61
    msaionyc  
       3 天前
    这也是一种护城河
    lscho
        62
    lscho  
       3 天前
    java 仔是这样的,能理解
    NoKey
        63
    NoKey  
       3 天前
    工作量,代码量,绩效巴拉巴拉的,老外有没有?
    你写一行?
    你这个月的代码量怎么这么少?
    喊你把你做的事情,写个 ppt 讲一下
    你说这里,我起了一个线程?
    我这里运用了 xxx 模式,能有效 xxxx ,利于后续扩展 xxx
    比一下?外行领导喜欢听哪个?
    那么多公司,用户就几十上百人,你看看架构师要设计多大并发?
    动不动就千人级,万人级,最后就那么几十人。。。
    为啥。。。
    卷呗
    fkname
        64
    fkname  
       3 天前
    最近看了下重构,这是典型的代码坏味道之夸夸其谈未来性
    oczizx
        65
    oczizx  
       3 天前
    我之前组里就有个同事,无论怎样的业务代码在他手里都是一层套一层再套一层。遇到这种技术扎实的同事就偷着乐吧。。这种事这种人在 Java 上真的特别常见我只能说。。。。。
    alexluo1
        66
    alexluo1  
       3 天前 via iPhone
    过度设计增加心智负担,太累了
    ultimate
        67
    ultimate  
       3 天前
    搁这开发 Spring 呢
    y547679519
        68
    y547679519  
       3 天前
    职场新人是这样的,老手都不会提前优化,前面搞那么合理,以后技术的 KPI 不就没有优化空间了么
    darkengine
        69
    darkengine  
       3 天前
    这个“以后”可能是 never /doge
    jorneyr
        70
    jorneyr  
       3 天前
    这大概就是内卷的具像化吧。
    lishere
        71
    lishere  
       3 天前
    面向“面向对象编程”编程,去翻一翻百度的 paddle 系列代码,你会气吐血
    Exception615
        72
    Exception615  
       3 天前
    @midsolo 过早优化是万恶之源 ------ 唐纳德·克努特
    redca
        73
    redca  
       3 天前
    炫技一点用没有,解决实际问题才是关键。 再牛的技术也要解决实际问题才可以。 这样多写代码,只能是浪费电,浪费时间, 当然公司如果按代码行数 kpi 那没得说, 建议在扩展一下~
    WngShhng
        74
    WngShhng  
       3 天前
    我记得之前在哪里看的,日本的程序员每个 if 都要包装一下,防止未来拓展,当时还被称为一种好的实践,好像是这篇: https://medium.com/@sohail_saifi/why-japanese-developers-write-code-completely-differently-and-why-it-works-better-de84d6244fab
    wu00
        75
    wu00  
       3 天前
    虽然不用 java ,大概率选 2
    - 不做任何设计先按流水代码写,后续继续迭代此处时再来做设计,实际上后续不管是自己还是其他人来接手的时候都是倾向于"复制粘贴"、"保持风格一致",谁 TM 有时间给你去做设计做重构,想多了!就跟到处打的 TODO 注释一样

    - 别以为统计代码行数是互联网段子,如果你们公司在用项目/代码管理工具,那大概率会统计工时/代码,只是你不知道或者没明面上拿来做绩效
    nicebird
        76
    nicebird  
       3 天前
    未来是多久?几个月内没有扩展需求,就选 1.
    kakki
        77
    kakki  
       3 天前
    Java 讨人厌就是因为 Javaer 讨人厌,说的就是你国内同事。
    RangerWolf
        78
    RangerWolf  
       3 天前
    我称第二种为 “防御性编程”
    twogoods
        79
    twogoods  
       3 天前
    所以你们最终的结论是啥?评论里也有不同意见的;拿你这个例子其实两种都可以,我觉得当时写成啥就啥吧别改了,但总有人拿着一个理由非要叫你改成另一种,codereview 最烦的就是这个。review 重点看思路和逻辑,看看有没有 bug ,风格这种不是特别糟糕的就别没事找事了...
    aecra
        80
    aecra  
       3 天前
    就因为 javaer 这种样子,我到现在都不想继续学 Java ,每次都是开个头就受不了了
    iyaozhen
        81
    iyaozhen  
       2 天前
    Java 魅力时刻
    JobsHwang
        82
    JobsHwang  
       2 天前   ❤️ 2
    具体看写在哪个层级的应用。
    如果是业务应用的门户层,那就第一种。
    如果是业务核心系统,那就第二种。
    这点代码都算心智负担的话,得反思下自己源码是不是看少了.....
    acerphoenix
        83
    acerphoenix  
       2 天前
    java er 净干些脱裤子放屁的事,心比天高,总认为写的代码要适应超高并发,多变的业务;命比纸薄,没啥用一两年就全废掉
    levelworm
        84
    levelworm  
       2 天前 via iPhone
    扩展的代码等扩展的时候再改。但是很多程序员喜欢过度设计,也很难互相说服。只能说谁做决定谁大。
    kkwa56188
        85
    kkwa56188  
       2 天前
    脱了裤子放屁, 放完了再把裤子优雅的穿起来,主打一个仪式感
    twig
        86
    twig  
       2 天前
    这跟国内国外没关系吧……
    jeesk
        87
    jeesk  
       2 天前 via Android
    没场景不好评价, 假设你的场景是启动应用就要执行一次,一个进程生命周期只执行一次,完全没毛病。


    如果还要考虑任务队列,并发,那就要好好设计一番了。 那么第一种肯定没法用。
    liyafe1997
        88
    liyafe1997  
       2 天前
    坐标欧洲,我跟你正好相反,现在当地同事老想着各种封装,一个类套一个类,搭一个非常完美的框架,各种 over design & over engineering 。有点怀念之前在国内工作,各种全局变量/指针满天飞,怎么爽怎么快怎么方便怎么来,以解决问题&产品 work 为首要目标。
    dongdong12345
        89
    dongdong12345  
       2 天前
    扩展后把文档写清楚,让后来人接手时,通过文档就可以快速上手
    RightHand
        90
    RightHand  
       2 天前 via Android
    支持老外,要承认自己的菜
    hoolindao
        91
    hoolindao  
       2 天前   ❤️ 1
    底层牛马写个代码还要鄙视来鄙视去。op 动不动就说同事炫技炫技的。结果人家也只是正常用一些接口抽象类什么的 Java 入门级的语法特性。笑不活。
    thetbw
        92
    thetbw  
       2 天前
    支持第二种,线程能用得到的地方还挺多的,对于管理后台,我还加了个异步任务进度和可中断的设计,很多地方都用的到。
    hoolindao
        93
    hoolindao  
       2 天前   ❤️ 1
    @hoolindao 所以我反感 op 不谈具体业务场景,就揪着国内同事的设计倾向说别人纯炫技拉偏架。
    nekoneko
        94
    nekoneko  
       2 天前
    第一种写法是出新需求时的写法.
    第二种是在业务稳定且需要扩展时进行的重构.
    kelololy
        95
    kelololy  
       2 天前
    我倾向于第二种,当然具体看任务场景,评论说等扩展了再改,殊不知后来者大概率直接 copy ,然后堆屎山
    ibearu
        96
    ibearu  
       2 天前
    奥卡姆剃刀,好的架构应该是演进出来的
    woodfizky
        97
    woodfizky  
       2 天前
    过度设计夸张点说就像横穿泥地都要先买个舟桥车然后架桥过去。。。哪怕只走那一次。。

    不过工作中遇到的屎山代码更多的反而是每天都要横穿泥地,每次走都要新买一对靴子,还有可能买错码数(到处复制粘贴还不改好,不做封装和代码重用)

    两种方式需要看项目实现的功能是怎么样的,原始需求是怎么样的,项目怎么发展过来的。

    我个人觉得很多时候一个不是很复杂的需求一开始就没必要像 Javaer 搞那么重那么过度设计。。
    只有需求比较复杂,有系统化的倾向的时候才开始做这种设计会比较好。
    kelololy
        98
    kelololy  
       2 天前
    @wu00 对,真实场景,一个是时间给不了,第二继任者不懂,肯定不改原逻辑
    geminikingfall
        99
    geminikingfall  
       2 天前
    你们 Javaer 真的是。。。写法 1 在再改的时候很容易变成屎山,因为加代码的人一般会选择修改量最小的写法。写法 2 就纯属炫技,增加阅读难度。
    woodfizky
        100
    woodfizky  
       2 天前
    "为了以后好扩展",所以就预留接口等当前无用的代码量,应该只适用于目前正在实现的功能已经有明确的后续需求和系统设计的情况。

    还有说什么领导喜欢这种什么"高内聚低耦合",已经系统化的需求和项目这么做没啥毛病,但是很简单的东西,大概率不会有后续需求和更新的情况,也这么干,那真的是浪费团队的时间,别拿职场糟粕去骗自己啊!
    1  2  
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   Solana   ·   2683 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 13:18 · PVG 21:18 · LAX 05:18 · JFK 08:18
    ♥ Do have faith in what you're doing.