工程师面试其实在问什么

来源:株式会社イズム的工程师面试问题示例

这篇文章表面上是在公开一组面试题和参考回答,但我读完之后觉得,它更像是一份“工程师成熟度清单”。面试官并不只是想确认候选人会不会写代码,而是在看一个人是否理解软件从需求到上线的完整生命周期,是否知道自己的代码处在什么上下文里。

这些问题可以粗略分成几类:

  • 开发流程:要件定义、基本设计、详细设计、编码、测试分别产出什么。
  • 上游能力:如何理解客户诉求、整理优先级、形成可确认的需求。
  • 设计能力:如何做模块拆分、分层、降低耦合、提高内聚。
  • API 与数据库:接口如何设计得稳定、一致、易用;SQL 是否只会 CRUD,还是理解 JOIN、聚合、执行计划与索引。
  • 质量保障:单元测试、集成测试、自动化测试和 CI/CD 是否真的参与过。
  • 工程表达:能不能把“我做过什么”翻译成“我为什么这么做,以及它解决了什么问题”。

我最有感触的是:这些题并不难在概念本身,而难在它们要求你把经验组织成因果关系。

比如“系统开发的一系列流程是什么”,如果只是回答“需求、设计、开发、测试”,其实没有太多信息量。更好的回答应该能说出每一步的目的、输入、输出,以及为什么它会影响下一步。需求定义不是写文档,核心是把模糊的业务诉求变成可讨论、可确认、可变更管理的边界。基本设计不是画图,核心是从用户视角和系统结构上定下大的形状。详细设计也不是把代码提前翻译成文字,而是让开发者在实现时少猜、少误解、少制造隐藏分歧。

再比如模块拆分和 SOLID 原则。很多人能背出“单一职责”“开闭原则”“依赖倒置”,但面试真正想听的不是术语,而是你有没有在复杂度出现时处理过它。一个类为什么要拆?因为它有多个变化理由。业务逻辑为什么不要塞进 Controller?因为 Controller 应该处理请求和响应,核心规则应该进入更稳定、更容易测试的领域对象或服务。依赖为什么要倒置?因为业务代码如果直接依赖数据库实现,测试和替换都会变得笨重。

API 设计也是类似。所谓 RESTful,不是把 URL 写得像某种格式就完事,而是让资源、动作、状态码、错误响应、版本管理这些约定形成一种稳定的沟通方式。一个好的 API 应该让调用方少猜,出错时知道发生了什么,未来扩展时也不至于把旧逻辑全部推倒。

测试和 CI/CD 的部分尤其现实。文章里的问题不是问“你知不知道 JUnit、Mockito、Postman、Jenkins、GitHub Actions”,而是问你能不能区分不同测试层级的目的,能不能说明自动化带来了什么实际收益。单元测试关注隔离和快速反馈,集成测试关注组件之间的数据流和接口协作,CI/CD 则把这些检查放进稳定的交付流程里,减少靠记忆和手工步骤发布的风险。

读到最后,我觉得这类面试题有一个共同的潜台词:你是否已经从“完成任务的人”开始变成“理解系统的人”。

前者关心代码能不能跑,后者关心需求为什么这样定、结构为什么这样分、接口为什么这样暴露、测试为什么这样覆盖、发布为什么这样自动化。前者讲“我写了某个功能”,后者讲“这个功能处在什么业务约束里,我如何选择实现方式,以及这个选择降低了什么风险”。

所以准备技术面试时,或许不应该只整理“标准答案”,而应该为每段经历补上几层解释:

  1. 当时的问题是什么?
  2. 我负责的边界在哪里?
  3. 我做了哪些技术选择?
  4. 为什么这样做,而不是另一种做法?
  5. 结果如何,有没有可观察的改善?
  6. 如果再做一次,我会如何调整?

能回答这些问题,技术面试就不再只是知识点抽查,而会变成一次对工程经验的复盘。甚至就算不为了面试,这也是一种很好的自我校准:我到底只是参加过项目,还是逐渐理解了项目为什么会变成现在这个样子。