严格意义上,「做题」其实不属于「面试」。
但由于这是承上启下的重要衔接,故并入。

电面过后通常就是做题,其对应的英文有很多:

  • Coding exercise
  • Technical challenge
  • Coding challenge
  • Coding test
  • Home assignment
  • ...

# 类型

  • 算法主导型
    澳洲大多数公司的面试都不考算法,就算要考难度也不会太高。
    当然如果你是要面试 FANG 等,就当我没说。

    在我的求职期里,也只遇到 Canva 和 Servian 考察算法。
    它们都用 HackerRank.com,一个类似 LeetCode 的平台。
    该提供 CodePair (opens new window),在之后的「结对编程」面试中肯定会用到。

  • 项目主导型
    澳洲大多数公司都会采用这种方式考察候选人的综合素质。
    技术面试时,通常会在这基础上进一步探讨或添加/改需求
    以下内容基本也是围绕着这种类型展开。

# 侧重

在国内,一般都是现场面试的时候才会安排做题。
所做的题目一般是基本功或算法,而不可能做一个项目。
这有一个局限性:较难评估候选人在日常开发时的真实素养
在浮躁的风气下,有的人对造火箭倒背如流,却可能拧不好螺丝钉。
但我也非常感谢国内重视基本功的氛围,让我有资本弥补英语的短板。

在澳洲,侧重考察日常开发的最佳实践,说白了就是职业素养(逼格)
通常都是先让候选人在家做一个小项目,提交审阅后再决定是否面试。
项目需求往往看起来很简单,但想要做好,依然很花时间和心思
最负盛名的莫过于 Toy Robot,在 Github 搜索就有大把样例。
其他公司的题目或许可以在 Glassdoor 的面经中找得到。

# 要点

对很多闷骚的程序员而言,这是「show time」,炫技的好机会。
尤其是像我这种英语不好的求职者,这可能是唯一的拉分项了。
作为前端开发,我会从以下方面来展示自己的职业素养(逼格):

# README

这基本是 reviewer 对你的第一印象,必须重视。
套路可以参照流行的开源项目,例如 Express.js (opens new window)
请别忘了使用 Grammarly 等工具检查语法及拼写。

# Demo

对于可视化的项目,如果对方没有要求不允许公开,
那么,提供可直接在线访问的 demo 将会加分不少。
常见的免费静态部署平台有 Github Pages / Netlify 等。
当然也有用 CodeSandbox / ZEIT Now / Heroku 等的同学。

# 描述文件

对于前端开发而言,看 package.json 基本就可以看出端倪。
以下列举一些不利的案例:

  • 分不清 dependenciesdevDependencies
  • 9102 年了还在用 React v15 / jQuery.extend 的
  • npm scripts 没有考虑到跨平台的兼容性
  • 忘了声明依赖,或需要污染全局的依赖
  • 引入没有用到,或没有必要用的依赖
  • ...

同理,套路可参考流行的开源项目,如 redux/package.json (opens new window)

# 目录结构

如同某些开源的项目脚手架(Starter / Boilerplate),
在其文档中通常也会有 Project / Directory Structure 的讲解。

并不是说必须要在 README 中画出目录结构树,
但若对此你有自己的思考,则建议在 README 中写出来。
因为这很能体现候选人过去所接触项目的可持续性与可维护性。
尤其是对于 Create React App 所生成的高自由度项目而言更是如此。

对于简单的需求,业务代码几乎都是千篇一律的情况下,
项目的目录结构无疑就成了拉开差距的重要得分点之一。
例如,Redux 的使用,直接决定了开发效率与维护性。

# 提交记录

Git log 几乎是最快了解候选人职业素养的途径。
最好让 reviewer 只看 Git log 就能快速代入你的角色。
如果后期还有关于优化、重构的 commits,那就更稳了。

有关 Git 的最佳实践,请自行查阅相关资料,在此不再赘述。

# 代码风格

由于业界有各类 IDE、ESLint、Prettier、Git pre-commit hook format,
因此,目前大家写出来的代码基本都差不多,比较难看出白板素颜。
尤其是用到 React / Vue 等非纯 JS 的项目,区别就更小了。
只要对语言特性稍微熟悉点,没有满屏的 for 循环,
不要弄混 map 和 forEach,基本就没啥问题。
该注释的要写好,不该注释的别画蛇添足。

# 测试

常见有单元测试、集成测试。
如果有前端界面,可能还需要 E2E 测试。
如果涉及到后端,则可能还需要单独的 API 测试。

部分情况下是不要求写测试的,或者需求文档上注明「estimate time: 2h」的。
当然了,如果你愿意继续投时间,那不妨锦上添花,让你的项目充满诚意。
不过值得一提的是,写测试通常要比实现需求所花的时间精力要多得多。
如果你手头上还有不少其他公司的题目,则建议斟酌侧重,合理安排。

然而,对于崇尚 TDD 的公司,不写测试等于放弃。
并且,你还得关注代码覆盖率,追求 100% 是标配。
那么,我们应该如何获悉对方是否崇尚 TDD 呢?
简单,鉴于这逼格很高,职位描述上肯定会提到。

在国内,需求往往都堆不完,更别说写测试了。
求职期内,我如饥似渴地恶补了很多测试的知识。
这是很不一样的领域,并不如之前我想象中的简单。
写测试所遵循的规则、mock / stub 等,都是宝贵的经验。

对于之前比较少写测试,又没有开源项目经验的同学,
建议好好研读测试套件的文档,参考开源项目的套路。
例如,对于 JavaScript 而言,主流基本都是用 Jest。

# 拓展性

实现需求时,需要同时考虑之后可能会有的新需求或改动。
例如,能做成配置的就不建议写死,否则改起来会比较麻烦。

以老生常谈的 Toy Robot 为例,之后面试官可能会新增路障。
实现时充分考虑,留足余地,现场写代码时才能从容应对。

# 细节

常言道,「细节决定成败」,上文有多处都涉及到细节问题。
例如,前端的 Create React App / Vue CLI 直接就开箱即用。
因此,对于简单的 UI 组件需求,候选人的代码往往都差不多。
同质化如此严重的情况下,想要打动 reviewer,还得多关注:

  • 注重体验
    虽说做题通常都是玩具性质的项目,但越是简单就越不能随便应付。
    既要考虑用户体验(UX),又得关注 reviewer 的开发体验(DX)。
    可能只是简简单单的一个 loading,又或者是友好的错误提示。
    秉承「勿以善小而不为」的开发理念,才不会因小失大。
    因为 reviewer 真的会非常仔细地「挑」你的项目。

  • 精心引入依赖
    有的同学手头上有祖传纯手写的瑞士军刀工具函数库,
    每次新开项目的时候,总是喜欢复制一份,继承传统。
    但对于做题来说,还隐含考察你对业界主流的熟悉度
    倘若还是继续保持这种传统,恐怕就显得有点守旧了。

    招聘,不怕没经验,最怕就是对技术没热情,跟不上潮流。
    如今技术更新换代速度飞快,确实如逆水行舟,不进则退。

    例如,不求用 Ramda,但求也得用 lodash 而非 underscore。
    当然了,也不是说非要滥用某些库来证明自己可以跟得上主流。
    例如 JavaScript 原生 map 可以解决的就别引入 lodash.map 了,
    否则反而会显得基本功不扎实,对语言熟悉度不够,过度依赖库。

  • 性能优化
    例如,上面提到的 lodash,
    直接 import _ from 'lodash' 的后果就是引入整个 70 KB 的库,减分。
    但如果同时又引入 babel-plugin-lodash 来优化,那就是扮猪吃老虎,加分。

    虽说 Create React App / Vue CLI 已经默默地给我们做了很多优化,
    但倘若你还能精益求精、追求极致,相信 reviewer 也会被你的热情感动。

  • 生产环境下的安全性
    例如,过滤用户输入避免 XSS / SQL 注入,秘钥别直接写死在代码等。

  • ...(TODO:有待同行们补充)

# 实例

在此我也只能厚颜无耻地列举我所做过的题目(求轻喷):

你也可以在 Github 上按 Star 降序搜索,例如「Toy Robot」。

# 温馨提示

  • 合理规划好做题的时间,适当主动推动招聘流程
    由于做题很耗时间和精力,但不做题又没有下一步。因此,在职「骑驴找马」的同学,要合理利用好晚上和周末的时间。例如,周四电面过后,对方表示会「尽快」给你发题目,但等到周五中午你都还没收到。此时你就应该主动发邮件或致电询问,否则可能就白白浪费了周末的时间。如果对方拖到周一才给你发,你可能到周三才能完成,提交后他们 review 也要一两天,于是你的下一轮面试又得推到下周了。另外,期间可能还会有其他公司给你发题目,其后续的进度也会因此而被进一步阻塞。

    有的公司 Sleepy Monday + Happy Friday,一周能干活的可能真的只有二三四,因此更要抓紧。

    对于心仪的公司,适当 push 是非常有必要的。例如,Sportsbet 就是在我的 push 下赶制出 coding exercise,周末完成后,周一就直接安排面试了。否则,别的公司都发 offer 了,心仪的公司却还没到终面,这将非常的被动,毕竟任何的 offer 都有时效性。请务必争取紧凑,才不至于到最后各种拖 offer 损人品。

    有关如何拖 offer,我会在之后的 Offer 篇 中提及。

  • 做题应该有所侧重,争取优先提交心仪的公司
    例如,公司 A 先于公司 B 给你发题目,但倘若你更倾向于后者,那么你理应先做 B 的。因为 B 公司并不会等所有候选人都提交题目了,再统一安排面试。虽说 HR 口头上都是「take as much time as you need」,但实际上这是「先到先得」:做题越快,安排面试越快,发 offer 也就越快,过时不候。不要拖到人家都快发 offer 给别人了,你才刚提交题目,那最终的结果基本就是石沉大海。即便是你发邮件打电话询问,对方也只能找各种借口不安排面试,让你主动放弃。

  • 优先选择澳洲主流技术栈
    例如,前端在不限定技术栈的情况下,能用 React 就别用 Vue。有不少面试官压根就没用过 Vue,而且个别面试官还会有某种信仰情结,排斥其他技术栈。

  • Estimate time 仅供参考
    为了避免吓着候选人,招聘方对做题耗时通常都是保守估计。实际耗时可达三到四倍,甚至更多。

# 总结

将心比心,如果我是 reviewer,
我会更倾向于那些在实现需求过程中注入新 idea 的候选人,
最好还能让我学到东西,促使我有欲望和对方进一步交流探讨的。

而对于千篇一律,没啥亮点,只会按部就班根据需求完成题目的候选人,
可能就没有那么高的优先级了,我宁愿再等等,继续放长线、广撒网。
因为作为 reviewer,我更期待招进来的同事可以为团队注入新的活力,
能互相学习,促进交流与优化,并带来更多优秀的实战与管理经验。