
国外的同事来国内出差,趁着这个机会,邀请他跟我们一起进行 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 mb4555 41 天前 单看着一行代码 支持老外 你这个封装有没有在其他地方用到 用到了 另说 |
4 erlking 41 天前 支持老外 |
5 spike0100 41 天前 我发现工作中至少 40%以上的预计扩展逻辑以后都不会用到。 |
6 lvtuyukuai 41 天前 可以扩展的时候改写成第二种,每次新加功能重构已有代码方便扩展 |
7 visper 41 天前 有时候,我更愿意去看一下写得很原始很差的复制多个地方的代码。而不是封装得十多差怎么也理不清关系的代码。虽然说为了扩展性。但是好像十年过去了也没有什么扩展。 |
8 LoNeZ 41 天前 看场景..和重要程度... |
9 sneezry 41 天前 按照我们公司之前的 review 风格,会支持国内同事的设计。现在一直在强调开发速度和营业额,没人在乎设计模式。 |
10 ohoh 41 天前 为什么是国外的气到吐血了,国内的就不?这意思你已经明显站队了啊。 防御/预防式开发没啥问题啊,只是度有多大的问题。 |
11 xubeiyou 41 天前 现在都讲究迭代速度和健壮性 不会在看设计模式了 除非真的有必 |
12 askfilm 41 天前 反正双标呗.... |
14 NO9527 41 天前 我支持老外的,等这种设计模式狂魔的代码到你手里就老实了 |
16 stinkytofux 41 天前 支持老外, 这种预留的拓展没必要, 需要的时候再把代码抽出来就是了. |
17 winglight2016 41 天前 java 代码就习以为常,见怪不怪,看看 spring 的代码就明白了,恨不得你一行代码都不写,全部搞成无代码平台 |
18 MrPat 41 天前 支持老外,度了,了而,等你需要用到留,可能你的代已要重了, |
19 Java 开发魅力时刻 |
20 chenluo0429 41 天前 via Android 设计时预留实现扩展的可能性,不要堵死扩展的路就好。 千万不要真的实现扩展,除非你真的知道这里短时间内需要扩展以及扩展的明确方向。 |
22 darksword21 PRO 这种我统称为被 java 污染了脑子( |
23 qping 41 天前 via iPhone 封了好几层每一层职责是什么?现在看起来什么事也没做,就是大肠包小肠 |
24 chenluo0429 41 天前 via Android 绝大部分自以为是的扩展,最后根本用不上。其中大概一半多增加了不必要的复杂度,对相关开发造成困扰。一小部分会对后续的基于真实需求的扩展造成非常大的阻碍 |
25 WithoutSugarMiao 41 天前 javaer 写代码考虑的真多。换成 python 的话,就没有这种烦恼,绝大部分 Pythonista 估计都会用第一种直来直去的写法。 |
26 songco 41 天前 via Android 支持第一种 以前设计模式流行的时候,公司有的代码特别恐怖,所有的地方都支持扩展,但是 99%其实就一种实现 |
27 otakustay 41 天前 现在有 Coding Agent 了,这种场景就算未来发现有扩展了改一套设计,找个 Agent ,明显有特征的代码( new Thread )全部扫一遍重构成新的方案,不要太简单 |
28 i8086 41 天前 业务变化无法预知,不要过早优化,也不要过度设计。 这段伪代码,对应业务是什么?没对应业务,那肯定越简单越好。 |
29 zh6335901 41 天前 抽象一般是你发现或者预见到了需要抽象的东西才去做,而不是自己去制造抽象 |
30 midsolo OP @winglight2016 哈哈,团队里好几个前 dubbo contributor ,很多业务代码也参照了 dubbo 的设计,使用 微内核+插件化+SPI 扩展,就是过度设计 |
32 cloudzhou 41 天前 这里两个写法看不出什么,如果是我的话,会将这个 Task 的逻辑,写到具体的 Service 然后 TaskRunner 作为一个中间组件 到这个程度的话: 1. new Thread(() -> XXXService.DoSomething).start(); // 原生线程池,没有特殊处理 2. TaskRunner.Run("doSomething", () -> XXXService.DoSomething); // 中间件封装 为什么中间件封装: 1. 统计,监控,日志 2. 线程数量控制(即便是协程) 3. 以后 TaskRunner 控制复杂调度(优先级,丢弃,限流...) 如果你们是一个成熟的团队,本来就需要这些中间件,在这个基础上,都只是一个简单的方法调用而已 |
33 cloudzhou 41 天前 #32 上面的 1/2 区别很小,对于团队的人来说接受度没什么区别,所以你们的问题是: 复杂场景下,需要丰富中间件,而不是“按需开发中间件”,这样会增加其他团队成员的理解程度 |
34 ppooqq 41 天前 说个常见的,IService/ServerImpl ,我写了多年代码也没遇上几回需要多实现的场景,我重来都是直接一个 Service |
35 leegradyllljjjj 41 天前 不好意思 我们是按代码量算钱的 |
37 superrichman 41 天前 里八唆的 JAVA 味道是这样的 |
38 BingoXuan 41 天前 最好加上 pool 去调度,任务开始前,创建上下文注入 thread local 去隔离变量就够了 |
39 sankemao 41 天前 平白无故添加了认知负荷,人的精力是有限的 |
40 newInterface 41 天前 我还见过在 java 里写 kotlin 的 |
41 cvooc 41 天前 java 程序员特有的留着以后扩展用(然而并没有扩展) |
42 alienx717 41 天前 claude code 给我写啥,就是啥,我不挑 |
43 Cooooooode 41 天前 以前喜欢预留扩展,现在的工作基本是删除那些代码 |
44 aloxaf 41 天前 想起一个 Java 笑话:一个程序员遇到了问题,他打算用 Java 解决,现在他有一个 ProblemFactory 了 |
45 xz410236056 41 天前 看到 java 我就都明白了,干什么之前先来个接口 |
46 guanhui07 41 天前 JAVA 味道是这样的 |
47 jsq2627 41 天前 "Java 味" |
48 PaulSamuelson 41 天前 为了以后可能用到,做的预留。Linus 看了直接开骂。 |
49 jsq2627 41 天前 AI 时代,尽量把业务逻辑集中在一起,对 AI Agent 才是最友好的。可能要打破过去十几形成的最佳代码实践了。 |
50 willchen 41 天前 业务代码的话(通用的基础架构另说),就别过度设计了,产品分分钟打破你 |
51 midsolo OP @darksword21 确实有点,我从 Java 转 Go 的时候,大概好几个月思想才慢慢转变 |
56 akakidz 41 天前 单从这里看,我觉得都没问题,还要看具体场景 |
57 liaohongxing 41 天前 有用 lambda 的一律支持 ,支持第一种 |
58 wangguyu 41 天前 支持第一种,等要扩展的时候再复制一下代码改成第二种,没必要过度设计。 |
59 cubecube 41 天前 AI 都会 refactor 了,何必浪费时间绕来绕去。 |
60 simpleman 41 天前 问一下, 如果是内部的代码,有必要写成这样子吗? 业务拓展了内部重构不就行了? |
61 msaionyc 41 天前 这也是一种护城河 |
62 lscho 41 天前 java 仔是这样的,能理解 |
63 NoKey 41 天前 工作量,代码量,绩效巴拉巴拉的,老外有没有? 你写一行? 你这个月的代码量怎么这么少? 喊你把你做的事情,写个 ppt 讲一下 你说这里,我起了一个线程? 我这里运用了 xxx 模式,能有效 xxxx ,利于后续扩展 xxx 比一下?外行领导喜欢听哪个? 那么多公司,用户就几十上百人,你看看架构师要设计多大并发? 动不动就千人级,万人级,最后就那么几十人。。。 为啥。。。 卷呗 |
64 fkname 41 天前 最近看了下重构,这是典型的代码坏味道之夸夸其谈未来性 |
65 oczizx 41 天前 我之前组里就有个同事,无论怎样的业务代码在他手里都是一层套一层再套一层。遇到这种技术扎实的同事就偷着乐吧。。这种事这种人在 Java 上真的特别常见我只能说。。。。。 |
66 alexluo1 41 天前 via iPhone 过度设计增加心智负担,太累了 |
67 ultimate 41 天前 搁这开发 Spring 呢 |
68 y547679519 41 天前 职场新人是这样的,老手都不会提前优化,前面搞那么合理,以后技术的 KPI 不就没有优化空间了么 |
69 darkengine 41 天前 这个“以后”可能是 never /doge |
70 jorneyr 41 天前 这大概就是内卷的具像化吧。 |
71 lishere 41 天前 面向“面向对象编程”编程,去翻一翻百度的 paddle 系列代码,你会气吐血 |
72 Exception615 41 天前 @midsolo 过早优化是万恶之源 ------ 唐纳德克努特 |
73 redca 41 天前 炫技一点用没有,解决实际问题才是关键。 再牛的技术也要解决实际问题才可以。 这样多写代码,只能是浪费电,浪费时间, 当然公司如果按代码行数 kpi 那没得说, 建议在扩展一下~ |
74 WngShhng 41 天前 我记得之前在哪里看的,日本的程序员每个 if 都要包装一下,防止未来拓展,当时还被称为一种好的实践,好像是这篇: https://medium.com/@sohail_saifi/why-japanese-developers-write-code-completely-differently-and-why-it-works-better-de84d6244fab |
75 wu00 41 天前 虽然不用 java ,大概率选 2 - 不做任何设计先按流水代码写,后续继续迭代此处时再来做设计,实际上后续不管是自己还是其他人来接手的时候都是倾向于"复制粘贴"、"保持风格一致",谁 TM 有时间给你去做设计做重构,想多了!就跟到处打的 TODO 注释一样 - 别以为统计代码行数是互联网段子,如果你们公司在用项目/代码管理工具,那大概率会统计工时/代码,只是你不知道或者没明面上拿来做绩效 |
76 nicebird 41 天前 未来是多久?几个月内没有扩展需求,就选 1. |
77 kakki 41 天前 Java 讨人厌就是因为 Javaer 讨人厌,说的就是你国内同事。 |
78 RangerWolf 41 天前 我称第二种为 “防御性编程” |
79 twogoods 41 天前 所以你们最终的结论是啥?评论里也有不同意见的;拿你这个例子其实两种都可以,我觉得当时写成啥就啥吧别改了,但总有人拿着一个理由非要叫你改成另一种,codereview 最烦的就是这个。review 重点看思路和逻辑,看看有没有 bug ,风格这种不是特别糟糕的就别没事找事了... |
80 aecra 41 天前 就因为 javaer 这种样子,我到现在都不想继续学 Java ,每次都是开个头就受不了了 |
81 iyaozhen 41 天前 Java 魅力时刻 |
82 JobsHwang 41 天前 具体看写在哪个层级的应用。 如果是业务应用的门户层,那就第一种。 如果是业务核心系统,那就第二种。 这点代码都算心智负担的话,得反思下自己源码是不是看少了..... |
83 acerphoenix 40 天前 java er 净干些脱裤子放屁的事,心比天高,总认为写的代码要适应超高并发,多变的业务;命比纸薄,没啥用一两年就全废掉 |
84 levelworm 40 天前 via iPhone 扩展的代码等扩展的时候再改。但是很多程序员喜欢过度设计,也很难互相说服。只能说谁做决定谁大。 |
85 kkwa56188 40 天前 脱了裤子放屁, 放完了再把裤子优雅的穿起来,主打一个仪式感 |
86 twig 40 天前 这跟国内国外没关系吧…… |
87 jeesk 40 天前 via Android 没场景不好评价, 假设你的场景是启动应用就要执行一次,一个进程生命周期只执行一次,完全没毛病。 如果还要考虑任务队列,并发,那就要好好设计一番了。 那么第一种肯定没法用。 |
8 liyafe1997 40 天前 坐标欧洲,我跟你正好相反,现在当地同事老想着各种封装,一个类套一个类,搭一个非常完美的框架,各种 over design & over engineering 。有点怀念之前在国内工作,各种全局变量/指针满天飞,怎么爽怎么快怎么方便怎么来,以解决问题&产品 work 为首要目标。 |
89 dongdong12345 40 天前 扩展后把文档写清楚,让后来人接手时,通过文档就可以快速上手 |
90 RightHand 40 天前 via Android 支持老外,要承认自己的菜 |
91 hoolindao 40 天前 底层牛马写个代码还要鄙视来鄙视去。op 动不动就说同事炫技炫技的。结果人家也只是正常用一些接口抽象类什么的 Java 入门级的语法特性。笑不活。 |
92 thetbw 40 天前 支持第二种,线程能用得到的地方还挺多的,对于管理后台,我还加了个异步任务进度和可中断的设计,很多地方都用的到。 |
94 nekoneko 40 天前 第一种写法是出新需求时的写法. 第二种是在业务稳定且需要扩展时进行的重构. |
95 kelololy 40 天前 我倾向于第二种,当然具体看任务场景,评论说等扩展了再改,殊不知后来者大概率直接 copy ,然后堆屎山 |
96 ibearu 40 天前 奥卡姆剃刀,好的架构应该是演进出来的 |
97 woodfizky 40 天前 过度设计夸张点说就像横穿泥地都要先买个舟桥车然后架桥过去。。。哪怕只走那一次。。 不过工作中遇到的屎山代码更多的反而是每天都要横穿泥地,每次走都要新买一对靴子,还有可能买错码数(到处复制粘贴还不改好,不做封装和代码重用) 两种方式需要看项目实现的功能是怎么样的,原始需求是怎么样的,项目怎么发展过来的。 我个人觉得很多时候一个不是很复杂的需求一开始就没必要像 Javaer 搞那么重那么过度设计。。 只有需求比较复杂,有系统化的倾向的时候才开始做这种设计会比较好。 |
99 geminikingfall 40 天前 你们 Javaer 真的是。。。写法 1 在再改的时候很容易变成屎山,因为加代码的人一般会选择修改量最小的写法。写法 2 就纯属炫技,增加阅读难度。 |
100 woodfizky 40 天前 "为了以后好扩展",所以就预留接口等当前无用的代码量,应该只适用于目前正在实现的功能已经有明确的后续需求和系统设计的情况。 还有说什么领导喜欢这种什么"高内聚低耦合",已经系统化的需求和项目这么做没啥毛病,但是很简单的东西,大概率不会有后续需求和更新的情况,也这么干,那真的是浪费团队的时间,别拿职场糟粕去骗自己啊! |