• 请不要在回答技术问题时复制粘贴 AI 生成的内容
midsolo
V2EX  ›  程序员

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

  •  1
     
  •   midsolo · Nov 5, 2025 · 21068 views
    This topic created in 369 days ago, the information mentioned may be changed or developed.

    国外的同事来国内出差,趁着这个机会,邀请他跟我们一起进行 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();
        }
    
    }
    
    Supplement 1  ·  Nov 5, 2025
    团队中有好几位热门开源项目的 contributor ,他们写业务代码也跟写中间件源码一样,导致代码中存在严重的过度设计,60% 以上的预留扩展点,估计等公司没了都用不上。

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

    还有说什么领导喜欢这种什么"高内聚低耦合",已经系统化的需求和项目这么做没啥毛病,但是很简单的东西,大概率不会有后续需求和更新的情况,也这么干,那真的是浪费团队的时间,别拿职场糟粕去骗自己啊!
    1  2  
    ❮ ❯
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   953 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 178ms · UTC 20:11 · PVG 04:11 · LAX 12:11 · JFK 15:11
    ♥ Do have faith in what you're doing.