牛券常见面试问题汇总
作者:程序员马丁
note
热门项目实战社群,收获国内众多知名公司面试青睐,近千名同学面试成功!助力你在校招或社招上拿个offer。
这一篇算是给牛券项目画个阶段性的句号。前面几章把领券、预约提醒、延时消息、结算规则、多线程优化这些核心流程都走了一遍,很多同学看完之后,私底下问得最多的,其实不是“代码怎么写”,而是“面试的时候,我到底该怎么讲?面试官会怎么问?这些细节怎么转成能聊得动的亮点?”
所以我干脆单独拎出一篇,把围绕牛券项目经常被问到的面试问题做个系统梳理:哪些点是高频问题,哪些细节稍微深挖一下就能拉开和普通简历的差距,哪些地方容易被面试官追问、又容易答偏。这篇不会再重复贴大段代码,而是站在“面试输出”的视角,把前面那些复杂的技术实现,压成一套可复用、能讲顺、逻辑自洽的问答思路。
如果你已经把牛券的主线文章看完,这篇可以当作一个总复盘;如果你是准备拿牛券项目去对标校招 / 社招面试,那这篇也可以当成“临门一脚”的提纲,帮你把项目里的知识点串成一段完整的故事。
创建优惠券模板责任链
1. 为什么要用责任链模式?
在没有引入责任链之前,创建优惠券模板的参数校验通常会写成下面几种形式:
- 在
createCouponTemplate方法里堆一长串if / else判断; - 或者抽一个
validateXXX(requestParam)大方法,里面塞满各种校验逻辑。
这种写法有几个明显问题:
- 职责不清晰、方法越来越臃肿:所有校验揉在一起,一个方法里既判断必填项、又判断格式、还要查库校验业务约束,导致方法越来越长,很难快速看懂「这一段是在干嘛」。
- 扩展性差,改动成本高:新增一个校验规则要么去改那段
if / else,要么继续往validateXXX里塞逻辑,很难做到「增加功能不修改原有代码」,违反开闭原则。 - 复用困难:某些校验逻辑(比如时间范围合法性、店铺是否存在等)本来可以复用到其他业务(比如修改模板、复制模板),但因为写死在方法里,想抽出来又很痛苦。
- 测试不友好:大方法里什么逻辑都有,单元测试要覆盖每个分支非常麻烦,也不方便针对某个校验规则单独写测试。
引入责任链后,把复杂的校验拆成多个「处理器」,每个处理器只关注一件事(比如非空校验、基础格式校验、业务校验等),既符合单一职责原则,又方便新增/下线某个规则,整体结构会清晰很多。
2. 执行创建 优惠券会走哪些责任链处理器?
例如:
- 必填项非空校验处理器
- 校验优惠券名称、优惠类型、有效时间、库存等是否为空;
- 类:
CouponTemplateCreateParamNotNullChainFilter。
- 基础格式与范围校验处理器
- 校验时间区间
valid_start_time < valid_end_time; - 校验库存必须是正数;
- 校验 JSON 字段结构是否符合预期、数值是否在合理范围内;
- 类:
CouponTemplateCreateParamBaseVerifyChainFilter。
- 校验时间区间
- 业务一致性校验处理器
- 校验店铺编号是否存在、是否属于当前登录用户;
- 校验商品编码是否存在、商品是否属于该店铺;
- 校验平台券/店铺券与来源、成本承担逻辑是否匹配;
- 类:
CouponTemplateCreateParamBizVerifyChainFilter。
- 扩展规则校验处理器(可选)
- 比如校验「同一时间同一店铺类似优惠活动是否超出上限」;
- 校验运营侧通用规则(如某些品类禁止打折等)。
每个处理器都实现统一接口 MerchantAdminAbstractChainHandler<T>,对外暴露一个 handler(T requestParam) 方法,责任明确、粒度清晰,后续想加某个新校验,只需要新增一个实现类接入责任链即可。