• 邀请国外的同事一起review公司代码,直接把老外同事惊呆了
  • 发布于 1个月前
  • 121 热度
    15 评论
  • DuXing
  • 7 粉丝 58 篇博客
  •   
国外的同事来国内出差,趁着这个机会,邀请他跟我们一起进行 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();
    }
}
团队中有好几位热门开源项目的 contributor ,他们写业务代码也跟写中间件源码一样,导致代码中存在严重的过度设计,60% 以上的预留扩展点,估计等公司没了都用不上。他们代码写爽了,接手的人一看惨了,调个 "1+1" 的方法要经历一堆 "接口、抽象类、实现类、回调、各种设计模式......" 才能拿到 "2" 这个结果。

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

作为程序员,我内心赞成国外同事说的用第一种写法。1 行代码就搞定,简单明了,等到需要扩展的时候再去抽取不就行了。但作为 "国内的程序员",我也只能跟着用第二种写法了。没办法,国内领导喜欢第二种,如果你用 1 行代码就实现了,那领导会认为你工作过于简单,工作量极不饱和;而用第二种写法,各种设计模式绕来绕去的,没十天半个月根本看不懂,既能体现你技术上的不可替代性,又能提供足量的代码......
用户评论
  • 荒岛初冬
  • "为了以后好扩展",所以就预留接口等当前无用的代码量,应该只适用于目前正在实现的功能已经有明确的后续需求和系统设计的情况。还有说什么领导喜欢这种什么"高内聚低耦合",已经系统化的需求和项目这么做没啥毛病,但是很简单的东西,大概率不会有后续需求和更新的情况,也这么干,那真的是浪费团队的时间,别拿职场糟粕去骗自己啊!
  • 2025/11/7 9:02:00 [ 0 ] [ 0 ] 回复
  • 烂好人i
  • 过度设计夸张点说就像横穿泥地都要先买个舟桥车然后架桥过去。哪怕只走那一次。不过工作中遇到的屎山代码更多的反而是每天都要横穿泥地,每次走都要新买一对靴子,还有可能买错码数(到处复制粘贴还不改好,不做封装和代码重用)。两种方式需要看项目实现的功能是怎么样的,原始需求是怎么样的,项目怎么发展过来的。

    我个人觉得很多时候一个不是很复杂的需求一开始就没必要像 Javaer 搞那么重那么过度设计。只有需求比较复杂,有系统化的倾向的时候才开始做这种设计会比较好。
  • 2025/11/7 9:00:00 [ 0 ] [ 0 ] 回复
  • 昨日情书
  • 底层牛马写个代码还要鄙视来鄙视去。op 动不动就说同事炫技炫技的。结果人家也只是正常用一些接口抽象类什么的 Java 入门级的语法特性。笑不活。
  • 2025/11/7 8:57:00 [ 0 ] [ 0 ] 回复
  • 陪着我走
  • 坐标欧洲,我跟你正好相反,现在当地同事老想着各种封装,一个类套一个类,搭一个非常完美的框架,各种 over design & over engineering 。有点怀念之前在国内工作,各种全局变量/指针满天飞,怎么爽怎么快怎么方便怎么来,以解决问题&产品 work 为首要目标。
  • 2025/11/7 8:53:00 [ 0 ] [ 0 ] 回复
  • 清醒纪年
  • 虽然不用 java ,大概率选 2
    - 不做任何设计先按流水代码写,后续继续迭代此处时再来做设计,实际上后续不管是自己还是其他人来接手的时候都是倾向于"复制粘贴"、"保持风格一致",谁 TM 有时间给你去做设计做重构,想多了!就跟到处打的 TODO 注释一样
    - 别以为统计代码行数是互联网段子,如果你们公司在用项目/代码管理工具,那大概率会统计工时/代码,只是你不知道或者没明面上拿来做绩效
  • 2025/11/7 8:45:00 [ 0 ] [ 0 ] 回复
  • 晴格与猫
  • 工作量,代码量,绩效巴拉巴拉的,老外有没有?
    你写一行?
    你这个月的代码量怎么这么少?
    喊你把你做的事情,写个 ppt 讲一下
    你说这里,我起了一个线程?
    我这里运用了 xxx 模式,能有效 xxxx ,利于后续扩展 xxx
    比一下?外行领导喜欢听哪个?
    那么多公司,用户就几十上百人,你看看架构师要设计多大并发?
    动不动就千人级,万人级,最后就那么几十人。。。
    为啥。。。
    卷呗
  • 2025/11/7 8:41:00 [ 0 ] [ 0 ] 回复
  • 空城旧梦
  • 这里两个写法看不出什么,如果是我的话,会将这个 Task 的逻辑,写到具体的 Service
    然后 TaskRunner 作为一个中间组件
    到这个程度的话:
    1. new Thread(() -> XXXService.DoSomething).start(); // 原生线程池,没有特殊处理
    2. TaskRunner.Run("doSomething", () -> XXXService.DoSomething); // 中间件封装
    为什么中间件封装:
    1. 统计,监控,日志
    2. 线程数量控制(即便是协程)
    3. 以后 TaskRunner 控制复杂调度(优先级,丢弃,限流...)
    如果你们是一个成熟的团队,本来就需要这些中间件,在这个基础上,都只是一个简单的方法调用而已
  • 2025/11/7 8:36:00 [ 0 ] [ 0 ] 回复
  • LoveC
  • 绝大部分自以为是的扩展,最后根本用不上。其中大概一半多增加了不必要的复杂度,对相关开发造成困扰。一小部分会对后续的基于真实需求的扩展造成非常大的阻碍
  • 2025/11/6 11:38:00 [ 0 ] [ 0 ] 回复
  • 麻辣码农
  • 设计时预留实现扩展的可能性,不要堵死扩展的路就好。千万不要真的实现扩展,除非你真的知道这里短时间内需要扩展以及扩展的明确方向。

  • 2025/11/6 11:36:00 [ 0 ] [ 0 ] 回复
  • 黄月英
  • 为什么是国外的气到吐血了,国内的就不?这意思你已经明显站队了啊。防御/预防式开发没啥问题啊,只是度有多大的问题。
  • 2025/11/6 11:34:00 [ 0 ] [ 0 ] 回复
  • 回忆经典
  • 按照我们公司之前的 review 风格,会支持国内同事的设计。现在一直在强调开发速度和营业额,没人在乎设计模式。
  • 2025/11/6 11:31:00 [ 0 ] [ 0 ] 回复
  • 王晶
  • 有时候,我更愿意去看一下写得很原始很差的复制多个地方的代码。而不是封装得十多差怎么也理不清关系的代码。虽然说为了扩展性。但是好像十年过去了也没有什么扩展。
  • 2025/11/6 11:29:00 [ 0 ] [ 0 ] 回复
  • CEBBCt
  • 单看着一行代码 支持老外 你这个封装有没有在其他地方用到 用到了 另说,不过也要看你们的使用场景
  • 2025/11/6 11:13:00 [ 0 ] [ 0 ] 回复