严格意义上,「做题」其实不属于「面试」。
但由于这是承上启下的重要衔接,故并入。
电面过后通常就是做题,其对应的英文有很多:
- 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
基本就可以看出端倪。
以下列举一些不利的案例:
- 分不清
dependencies
和devDependencies
的 - 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:有待同行们补充)
# 实例
在此我也只能厚颜无耻地列举我所做过的题目(求轻喷):
- https://github.com/kenberkeley/tmdb-react (opens new window)
- https://github.com/kenberkeley/omdb-vue (opens new window)
你也可以在 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,我更期待招进来的同事可以为团队注入新的活力,
能互相学习,促进交流与优化,并带来更多优秀的实战与管理经验。