今年上半年,我写过管理后台、小程序,也开始顺着接口改 Java 服务。回头看,真正改变我的并不是又记住了多少 API,而是一个很普通的优惠券需求:后台多两个选项,最后却要同时改保存、搜索、可用性判断和十处移动端展示。
那次以后,我才慢慢接受一件事:会写三个端,不等于理解了一条完整业务链路。
最开始,我以为这只是给表单加两个选项
需求不复杂:优惠券原来可以指定商品和类目,现在还要支持"排除指定商品"和"排除指定类目"。
如果只盯着管理后台,它几乎就是一道表单题:补两个枚举值,增加对应的选择区域,提交时把数据带给后端。
我一开始也很容易顺着这个方向想。直到继续往下追,才发现"排除"不是一个界面文案,而是一条必须贯穿全链路的业务规则。
后台能保存,只代表配置进去了。商品搜索还要知道哪些类目不能返回;领券和下单时,要重新判断当前商品是否命中排除条件;移动端收到新的类型值后,还要保证旧页面不会把它显示成错误状态。
最终,这个需求落到了三层:
- 管理后台负责让运营人员正确配置;
- Java 服务负责保存规则、查询商品并判断优惠券是否可用;
- 移动端负责兼容新类型,并在多个入口保持一致展示。
其中最让我意外的是移动端。表面看只是一处优惠券详情,真正搜索后却发现,券列表、领券中心、活动弹窗、新人礼、分享弹窗等多个组件都在解释同一个字段。后端增加两个值,如果其中一个入口还沿用旧判断,用户看到的就可能是另一套意思。
我上半年补上的第一课,不是 Java 语法,而是数据合同意识。
一个枚举值从数据库出来,要经过查询、服务判断、接口返回和页面展示。任何一层把它当成自己的局部字段,最后都会变成"这里正常,那里不正常"。
Java 最难的部分,不是把代码写出来
我以前主要写前端。学 Java 时,我最先关注的是 Controller、Service、Mapper 分别怎么写,参数怎么接,数据怎么查。
实际改需求后,我发现语法反而是相对容易补的。更难的是回答这些问题:
- 这条规则应该在保存时处理,还是在使用时判断?
- 搜索层已经过滤过,业务层还要不要再校验?
- 旧数据没有新字段时,默认行为是什么?
- 管理端显示正确,能否说明下单时也一定正确?
优惠券需求里,我既要改保存和更新逻辑,也要改商品是否适用的判断,还要让搜索请求支持排除类目。它们写在不同模块里,却共同决定一张券到底能不能用。
这让我对"后端"有了不同理解。它不只是提供一个接口,更像是在维护一份不会随着页面变化而走样的业务约定。
前端可以隐藏按钮,但隐藏不等于没有权限;搜索可以提前过滤,但过滤不等于最终校验;接口返回成功,也不等于业务状态已经正确。
这些判断听起来像常识,可只有真正顺着一次请求走完,才会知道自己之前把多少事情交给了想当然。
我上半年写得最有用的一段代码,可能是删掉的那几百行
六月做另一个活动需求时,我又踩了一个相反的坑。
这次不是少想了一层,而是想得太多。为了让方案看起来更完整,我提前加了统计面板、可疑行为记录和几组并不在原始需求里的结构。代码能解释,页面也能做出来,但它们没有解决当下最核心的问题,反而扩大了数据、接口和维护范围。
后来重新对需求,一次重构从后端删掉了 15 个文件里的 676 行,管理端又移除了 292 行统计相关代码,只保留每日上限和门槛开关。
以前我会把这种删除理解成"前面白做了"。现在看,它反而是上半年最重要的一次工程训练:实现得更多,并不自动等于方案更好。
提前设计当然不是错,但每一层额外能力都应该回答三个问题:现在是否真的需要?数据从哪里来?谁来验证它是对的?如果答不上来,它大概率只是让代码显得完整。
回滚让我学会把"改完"拆成几种状态
上半年的提交记录里有不少 Revert。有的是需求边界变化,有的是合入后发现影响范围比预想大,还有的是测试环境和目标分支并不一致。
这种记录不漂亮,却比一串整齐的成功提交更接近真实开发。
我以前容易把"代码已经改完"当成一个确定状态。后来才逐渐把它拆开:
- 找到了真正的代码入口;
- 修改只覆盖了预期范围;
- 语法、检查或构建通过;
- 目标环境运行的是这份代码;
- 真实业务路径得到确认。
前一层不能替代后一层。构建成功不能证明页面已经生效,接口返回 200 也不能证明优惠券真的选对了商品。
这套拆分也改变了我使用 AI 编程工具的方式。AI 很擅长帮我快速找到陌生类、补一段查询或解释调用关系,但它拿到的上下文永远可能少一块。如果我只问"怎么改",很容易得到一份局部正确的答案;先把页面、接口、服务和数据路径交代清楚,再让它参与分析,结果会稳定得多。
AI 提高了写代码的速度,也把验证责任更完整地还给了我。
所以上半年,我到底学了什么
如果按技术名词写,我可以列出 Vue、小程序、Java、搜索、数据库、Git 和 AI 编程工具。可半年后真正留下来的,并不是这张清单。
我学到的是:
- 遇到页面问题,先确认数据从哪里来,不急着在当前组件里打补丁;
- 遇到新业务类型,先画清它经过的保存、查询、判断和展示链路;
- 遇到"顺便做得更完整"的冲动,先回到原始需求和验收条件;
- 遇到构建通过或接口成功,继续追问它证明到了哪一层;
- 使用 AI 时,把它当成共同排查的工具,而不是替自己签字的人。
至于 Python、RAG 和 Agent,我没有把它们写进这份上半年成果里。那时更多是方向和兴趣,真正开始系统补这些内容,是后面的事。把"准备学"写成"已经掌握",会让总结好看一点,却不能帮我判断下一步该补什么。
现在再看上半年,我并没有突然变成一个所谓的全栈工程师。我只是从"这个页面怎么改",往前多问了几步:这条规则从哪里开始,经过了谁,最后由什么证明它真的成立。
对我来说,这比多会一门语言更重要。