别人写的代码看不懂,到底是谁的水平有问题

你突然看到某段代码用了工厂模式,第一反应可能是:有必要吗?直接new一个对象不行吗?干嘛「故意」增加阅读难度?

其实不是这样的,当你接触过的高手多了后,你会自然而然的认为:高手的代码,确实不太容易看懂,尤其你水平还不够的时候。

我不是说你菜,只是每个人都会经历过这个阶段的。关键在于,你得分清楚一件事:到底是代码本身写得烂,还是你的知识面暂时还覆盖不到这里。

你觉得没必要,可能是你还没遇到那个场景

如果你构造的对象只是简单地设置几个属性,确实没必要用工厂。直接用构造方法或者Builder就够了。

问题出在另一种场景:构造一个业务对象的过程本身就很复杂。

拿门店进销存系统中的物料盘点模块举例。创建一张盘点单据,需要做这些事情:

  • 根据模板ID去查盘点模板,拿到模板里配置的名称、类型、盘点日期规则
  • 调用编码生成服务,按照业务规则生成单据编号
  • 把提交过来的物料数据逐条转换成明细实体
  • 把以上所有数据组装成一个完整的聚合根对象

这不是简单地new一个对象然后set几个字段。整个构造过程涉及到外部服务调用、数据库查询、业务规则计算。如果这些逻辑散落在调用方的代码里,那每个需要创建盘点单据的地方都得重复写一遍。

用工厂模式封装这些构造逻辑,代码大概长这样:

Java 复制代码
@Component
public class StocktakingDocsFactory {
    private final CodeGeneratorService codeGeneratorService;
    private final StocktakingTemplateRepository templateRepository;

    public StocktakingDocsAggregateRoot create(SubmitStocktakingCommand command) {
        // 查询模板,获取名称、类型、日期规则
        StocktakingTemplate template = templateRepository.getById(command.getTemplateId());
        // 生成单据编号
        String code = codeGeneratorService.generate(ModuleEnum.STOCKTAKING);
        // 组装明细
        List<StocktakingItemEntity> items = buildItems(command.getMaterialList());
        // 构建聚合根
        return StocktakingDocsAggregateRoot.builder()
                .code(code)
                .name(template.getName())
                .type(template.getType())
                .items(items)
                .build();
    }
}

调用方只需要一行 factory.create(command) 就拿到了完整的聚合根对象。构造过程中涉及到的模板查询、编码生成、数据转换这些细节,全部被封装在工厂内部。

当你知道工厂模式就是干这个事情的时候,看到对应的代码会觉得很自然。 觉得绕,往往是因为你还没遇到过需要它的场景。

高手的代码都是精心组织过的

我带过的团队里,水平高的那几个人,写出来的代码有一个共性:都是有规划、有设计的。随意写代码,对他们来说是大忌。

你甚至会经常听到他们说这句话:不要这搞一个,那搞一个,要设计和规划的。

这基本是他们的口头禅了。

再看一个例子。库存系统里有一个库存调整的功能,不同的业务场景对库存的处理方式不一样:

  • 履约扣减:只减理论库存,不动实际库存
  • 期初入库:直接覆盖所有库存数量
  • 盘点调整:先改实际库存,再同步理论库存
  • 调拨/收货/报损:理论库存和实际库存同时增减

如果把这些逻辑全堆在一个方法里用if-else判断,那个方法会膨胀到几百行,而且每次新增一种场景都要在那坨if-else里再加一个分支。改的人心惊胆战,因为怕影响其他分支。

看看高手怎么组织这段逻辑。先定义一个策略接口:

Java 复制代码
public interface InventoryAdjustmentHandler {
    MaterialInventoryAggregateRoot execute(AdjustmentContext context);
    boolean isSupported(AdjustmentContext context);
}

每种场景一个实现类。履约扣减的处理器:

Java 复制代码
@Component
public class FulfillmentAdjustmentHandler implements InventoryAdjustmentHandler {
    public static final List<StatementType> TYPES = List.of(
            StatementType.PRODUCT_DEDUCTION, StatementType.PRODUCT_RETURNS);

    @Override
    public boolean isSupported(AdjustmentContext context) {
        return TYPES.contains(context.getStatementType());
    }

    @Override
    public MaterialInventoryAggregateRoot execute(AdjustmentContext context) {
        // 只扣减理论库存
        context.getAggregateRoot().fulfillmentAdjustment(context.getDTO());
        return context.getAggregateRoot();
    }
}

聚合根里的调用入口,通过Spring容器自动发现所有处理器,让它们自己判断是否适用:

Java 复制代码
public MaterialInventoryAggregateRoot adjustment(InventoryAdjustmentDTO dto) {
    Map<String, InventoryAdjustmentHandler> handlers =
            SpringUtils.getContext().getBeansOfType(InventoryAdjustmentHandler.class);
    handlers.forEach((key, handler) -> {
        AdjustmentContext context = new AdjustmentContext(this, dto, statementType);
        if (handler.isSupported(context)) {
            handler.execute(context);
        }
    });
    return this;
}

这种代码有一个特别重要的性质:它没那么容易被破坏。

新增一种库存调整场景,你只需要写一个新的实现类,实现 isSupportedexecute 两个方法。已有的履约处理器、期初入库处理器、盘点处理器,一行代码都不用动。

新来的同事接手这段代码,他能破坏的范围被限制在他自己写的那个实现类里。他不需要理解其他场景的处理逻辑,也不会因为改错了一行代码导致其他场景出bug。

这就是我说的「精心组织过」的含义。不是为了炫技,是为了让代码在多人协作、长期维护的环境下,尽量少出问题。

水平提升之后,你会觉得他写得真好

这个认知转变的过程,大部分人都会经历。

一开始看到策略模式、工厂模式,觉得绕,觉得不直观。明明可以if-else写在一起,为什么要拆成这么多类?

等你自己维护过一个屎山项目,在一个2000行的方法里找了一下午bug,改一行代码导致三个不相关的功能挂掉之后,你对「代码组织」这件事的理解会完全不一样。

你会开始理解:那些拆成多个小类、每个类职责单一的代码,不是为了好看,是为了让维护者不那么痛苦。你甚至会发自内心地觉得那个人写得真好。

更关键的是,你自己后面也会慢慢写出那样的代码。不是刻意模仿,是你理解了背后的道理之后,自然而然就会那样去组织代码。

这说明你成长了。

从看不懂,到看懂了觉得好,再到自己也能写出来。这是每个开发者技术成长的必经之路。

怎么判断是代码烂还是你水平不够

有些代码确实写得烂,看不懂不是你的问题。怎么区分这两种情况?这张表可以帮你快速判断:

维度 代码确实写得烂 你水平还不够
命名 变量名abc、temp满天飞,类名和功能对不上 类名长但语义精确,比如FulfillmentInventoryAdjustmentHandler
结构 一个方法500行,什么逻辑都往里塞 拆成多个小类,每个类只做一件事
模式 没有任何模式,全是if-else和重复代码 用了你不认识的设计模式(工厂、策略、模板方法等)
修改成本 改一行可能影响十个功能 新增功能只需加一个新类,不用动已有代码
一致性 同样的事情三个地方三种写法 整个模块的代码风格、组织方式高度统一

如果你对照这张表,发现让你困惑的代码在右边这一列全中了:类名虽然长但意思明确,结构拆得很细但每个类职责单一,用了你没见过的模式但改动时不影响其他地方。

那大概率不是代码的问题,是你的知识储备还没覆盖到这里。这不丢人,补起来就好了。

小结

代码组织这件事,表面上看是个编码习惯的问题,深一层想,它反映的是一个开发者对「长期维护成本」的认知水平。

写代码最容易的方式永远是把所有逻辑堆在一起,这样写得最快,当下理解成本最低。代价是后面每次修改都如履薄冰,因为你不知道改这里会不会影响那里。

高手选择多花一些时间做代码的组织和设计,把逻辑拆开、把边界画清楚、把扩展点留好。短期看起来代码多了、类多了、看起来绕了。长期看,每次改动的风险被控制在一个很小的范围内。团队的人来来走走,代码依然能稳定地演进下去。

看不懂这种代码,不用焦虑。先去了解对应的设计模式,理解它要解决的问题,再回来看代码,感受完全不同。等你有一天自己也写出了这样的代码,回头看看自己当初的困惑,你会觉得那就是成长的印记。


最近在知乎出了「应付6000万会员的秒杀系统专栏」和「几亿用户,百万并发的C端商品系统实战」专栏,感兴趣的可以订阅一下。至于知识星球的,可以搜:

  • 老码头的技术浮生录

它是一个能实际帮你解决难题的星球。有问题的,找知心的Sam哥,支持无限次语音一对一解决你遇到的难题。「另外后续我新写的所有对外的付费专栏,在星球内都是免费的,且可以拿到所有源代码。」

知识星球内后续将推出20+个付费专栏,覆盖电商全链路:

选购线 用户会员营销线 中后台
购物车服务 营销系统 订单系统
商品服务 用户系统 支付系统
菜单服务 结算服务

从前台选购到中后台结算,星球成员全部免费,后续新增也不额外收费。

我的知乎账号:

  • SamDeepThinking
相关推荐
IT当时语_青山师__JAVA技术栈1 小时前
动态代理深度解析:JDK与CGLIB底层实现与实战
java·后端·面试
吃不胖爹1 小时前
定时任务quartz案例
java
白露与泡影1 小时前
2026年Java面试最全避坑指南:从基础、并发、JVM到微服务,这一篇就够了
java·jvm·面试
Nyarlathotep01131 小时前
类加载机制(3):类加载器
jvm·后端
Mr数据杨1 小时前
【Codex】用APP绑定教程模块规范移动端接入指引
java·前端·javascript·django·codex·项目开发
熊出没1 小时前
02——从 Prompt 到 Workflow
java·前端·prompt
段ヤシ.1 小时前
回顾Java知识点,面试题汇总Day1(持续更新)
java·开发语言
Devin~Y1 小时前
大厂Java面试:Spring Boot + Redis/Kafka + Spring Cloud + JVM + RAG/向量检索(小Y翻车实录)
java·jvm·spring boot·redis·spring cloud·kafka·mybatis
Hello.Reader1 小时前
算法基础(九)——循环不变式如何证明一个算法是正确的
java·开发语言·算法