<audio id="audio" title="08 | 其它技能考察：见微知著，不可忽略的其它考察点" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/71/d9/71a11cdae37d79f9d991e49c22e661d9.mp3"></audio>

你好，我是四火。

关于怎样主导技术面试的问题，在前面几讲里，我们分别对算法和数据结构，以及系统设计这两个最常见的考察路径，做了重点讲解。

而在技术考察方面，还有一些常见的其它路径，比如面向对象的考察，还有针对测试能力的考察等等。

据我观察，近几年来大家对于软件工程师的全面性要求越来越高，早就不再是会写代码逻辑、会设计系统就可以轻松当面霸了，在这一讲中，我就介绍一些比较常见的其它面试路径。

## 其它工程技能考察

### 面向对象考察

严格说起来，多数情况下，这一点应该叫做代码设计能力考察，只不过面向对象是最常见的其中一个方面而已。从技术角度上说，它包含了两个方面：

1.**考察候选人代码层面的面向对象设计能力；**<br>
2.**考察候选人代码层面的综合代码组织的能力。**

先来说说上面的第1点。面向对象考察，尤其是对于入职没多久的程序员候选人来说，这是一个非常常见的形式。我们有时讲的代码层面的建模，其实就是通过面向对象的办法，把实际问题使用代码的类、方法等抽象来描述的过程。

既然重点是面向对象，这就意味着往往问题并不夹带复杂的算法逻辑，而面试官的重点也将放在代码设计的层面，能否将实际问题场景的核心抽象成一个又一个的类、方法和属性，安排它们之间的关系，并且应用合适的设计模式，作出合理的解耦，最终落地到代码上。

这种考察方式其实很考验候选人代码层面的设计能力，又和同为代码层面的算法能力有明显区别。我们也确实见到有一些候选人，他们虽然能够攻克复杂的算法，但是在代码设计和组织上却不尽人意。

<img src="https://static001.geekbang.org/resource/image/e7/83/e797df83c7a667c1ffe05654c09eb583.jpg" alt="">

再来说说上面的第2点，综合代码组织的能力。如果我们再站高一点看，其实好的代码都不一定非得是面向对象的，即便是过程式的代码，一样可以做好模块化、解耦，因此本质上我们考察的重点是候选人综合的代码组织能力。

另外，这样的面试也需要对编程语言的许多语言特性有准确的认知。比方说，如果面试题目明确指出了要求面向对象的方式来完成实现，那么除了代码设计层面，我们也能看出候选人对于封装、继承、多态等等一些现代编程语言基本特性的理解如何。

无论这一轮面试关注于上面说的哪一点，都要像我们前几讲介绍的那样，专注于具体问题的解决，即和候选人一起使用这些技能和工具解决实际问题，而不是单纯地做设计原则和设计模式理论和概念的问答。

事实上，**面向对象考察中，我观察到最常见的误区，恰恰就是纠结于设计模式。**说到底，代码层面的设计，最终目的是为了代码具备更好的可读性、可重用性和可扩展性。

因此，分层清晰，做到了良好的模块化、做到了合适的解耦，又留下了一定的扩展能力的代码，往往就已经是好代码了，不一定非得扯上某个著名的设计模式；反过来也一样，即便能够准确地说出某个设计模式的定义，它也不能作为对于代码设计能力的有力证明。

### API设计考察

现在对于很多大厂来说，业务都分得很细致，那么每一个团队往往都要维护若干个service，并且将业务能力通过API的形式暴露出来。在这种情况下，API的调用方就是团队的用户。

因为API的设计能力显得举足轻重，所以针对它的考察能够从相当程度上，看出候选人是否在代码接口和客户端与service的交互方面有一个平衡的理解。前者是对代码的理解，而后者是对系统的理解。

<img src="https://static001.geekbang.org/resource/image/19/2f/19f0e1d4ded01394b86cd79ffec3412f.jpg" alt="">

比方说，还记得[第7讲](https://time.geekbang.org/column/article/364712)中谈到的网约车系统吗？对于其中的Ride Service，我们就可以引导候选人完成类似如下的API接口设计表格：

<img src="https://static001.geekbang.org/resource/image/45/10/45583cb6594d716a3936abf5608da510.jpg" alt="">

假如说我们把这个提供API的模块当作一个黑盒，当它所有的API都已经清楚了，我们对于这个黑盒的功能，以及这个黑盒的用户怎样和它进行交互，这两件事情也就非常明确了。

上面这个API的设计，是从HTTP协议，或者说是从REST服务的角度来描述的，对于不符合这种情况的，或者候选人不熟悉网络协议，我们也可以简单从编程语言代码中方法签名的角度描述，说清楚方法的作用，入参、返回值和数据结构，以及常见的异常种类，其本质是一样的：

```
Response createRide(Request req);

```

### 测试能力考察

测试能力的考察，在某些北美的互联网大厂中更为常见。比方说，Google的工程师面试loop中，经常会单独放一轮由测试工程师主导的测试能力考察面试。

你可能会好奇，为什么这些大厂格外重视这点呢？

这里面的初衷是这样的，测试能力是对于一个具备全栈能力的工程师，所必须包含的一项重要素质，而这些企业的大多数负责开发的工程师岗位，都不会再匹配大量的测试工程师来完成项目，因此需要开发独立完成测试。

说白了，就是自己写的代码要自己测试，自己上线，自己oncall和修复问题，完成闭环。

对于测试能力的考察，有两种常见形式。

**第一种形式是针对已经完成的代码，做白盒测试。**面试官会期望候选人，能够拿着简单的测试用例来走一遍代码。之后也可能会提问，怎样设计测试用例才能将刚写的代码覆盖到，甚至要求写一小段单元测试代码，这是属于白盒测试。

白盒测试一般时间需求比较少，适合结合在每一轮包含编码的面试中，在编码完成后进行拓展。这种形式除了对于测试本身的考察，对于候选人在代码层面的理解也有着很明确的要求。

**而第二种形式，则是黑盒测试。**对于某一个产品，或者某一个功能特性，从黑盒的角度讨论，怎样才能做好它的测试。黑盒测试主要出现在单独的测试能力考察轮次，这种形式除了对于测试本身的考察，也要求候选人在系统和产品的层面有一定的理解。

举例来说，一个经典的黑盒测试能力考察的面试题是：

> 
如果你负责Google Map地图的设计，系统给出了从A点到B的通行路径，你计划做怎样的测试，来保证从A到B的路径这一结果是合理的？


两种形式，黑盒白盒虽然差异很大，但是很多独立完成测试的工程师所需要的重要素质，比如问题场景的分析能力和用例设计的能力，其实都覆盖到了。

### 项目与任务管理

我们再来说说项目管理与任务管理方面的考察。在很多大厂的面试中，有一轮经常是由PM来负责的，这个PM有时候是Project Manager，更多时候则是Program Manager，他们会比较关注项目、任务和软件工程的流程方面。

最常见的考察方法是问经历，即直接了当地询问候选人，当前团队中，项目是怎样管理的，产品是怎样上线的，任务是怎样管理的，优先级又是怎样排的。其中很大一部分都可以用询问行为型问题的方法来操作，而这部分我们将在后面重点介绍。

好，上面介绍了一些常见的工程技能的考察类型，但是还有一些其它类型我并没有逐一展开来细数，比如针对产品思维的考察，一些在招聘团队中的产品经理很喜欢这种形式，抛出一个问题，和候选人一起挖掘用户的痛点，从产品角度讨论设计等等。

## 行为型问题

最后我想介绍一下行为型问题（Behavior Question），这是一种非常流行的非具体技术考察方式。这种方式不光很多重视价值观、领导力的大厂愿意采用，其中很多招聘团队中的Hiring Manager更是特别热衷于它。

### 概念与逻辑

首先，我们必须要弄清楚一个概念，什么是行为型问题？

**行为型问题基本上是一类用来观察候选人过去在特定的工作情境下，是怎样解决困难并取得成功的问题。**

这里要求候选人所描述的情境，包含的内容非常广泛，可以是与内部同事之间的，可以是与外部客户之间的，可以是关乎项目和任务的，可以是业务决策方面的，也可以是具体技术实现上的。

无论哪一种，**这里面的逻辑是，候选人在过去遇到困难的时候，遵循的逻辑和采取的行为，这相当程度上反映了未来候选人将怎样应对类似的困难。**

如果你还觉得不太清楚的话，可以看看下面这个行为型问题的例子：

> 
你能否告诉我一个实例，让我了解你在工作中是怎样说服同事，采纳你的技术决策的？


从这个问题的回答，我们能够看出很多内容，譬如说，对于不同的技术决策，候选人是根据怎样的标准来评估优劣的，候选人是怎样和同事沟通的，等等。通过这样的问答方式，面试官可以看出候选人的许多品质，比如这个例子中，候选人对问题的分析思考能力，和同事的交流沟通能力，以及是否具备backbone（不轻易动摇）等等。

再比如下面这样的例子：

> 
<p>你在工作中是否遇到过不同意你主管（经理）看法的时候？你又是怎样处理的？<br>
对于预先订立的项目目标，你有没有遇到过未能按时实现的情况？<br>
对于在你做过的项目中的软件设计，有没有事后你觉得自己做错了的？</p>


### 原则与窍门

好，看完例子，我来总结一下，如果要向候选人提出行为型问题，有这样几个原则和窍门：

**第一，问题都是基于“过去”的**，或者说，我们希望知道的，都是活生生的，已经在候选人身上发生了什么事情，他抱了怎样的看法，又是怎样应对的。与之相对的是，“假如”型问题，比如：

> 
假如你觉得同事的code change给系统造成了一个很严重的隐患，但是他又拒绝修改，你该怎么办？


这样的问题当然有它的价值，但它就不属于行为型问题，也不符合前面所说的“过去反映未来”的逻辑来得到考察数据，以帮助我们对候选人做出评估。

为什么这么说？因为所有人是可以“假想”的，但是假想并不能像过去的“事实”一样反映他真的会那样做。

**第二，情境要包含冲突，如果可能，最好是一个棘手的冲突。**不是所有的行为型问题都要求包含“冲突”的，比方说：

> 
介绍一个你自己认为最为成功的项目，并说明为什么你觉得它是成功的？


这个问题本身就不包含明显的冲突，没有冲突就不利于我们知道，在“困难”的情境下，候选人是怎样应对的。当然，这样温和的问题可以进一步发散开去，引出更多尖锐的、包含冲突的问题，那当然是另一回事。

反过来，看看前面我前文中举的一些例子，比如“和主管看法不同”的例子，就隐含了一个和主管观点不一致的冲突。在面试双方能够顺利沟通的前提下，挖掘一些对于尖锐冲突场景应对的事例，可以很好地帮助我们了解候选人。

**第三，追问并达到一定深度。**这一点和前面几讲中提到的[第7讲](https://time.geekbang.org/column/article/364712)中怎样询问项目一样，我们当然不是希望事无巨细，但有深度的挖掘能在一定程度上帮助确认这些都是发生过的事实，而非随口应付而编造的答案。

**第四，尽量避免太过常见的问题。**这和技术问题的设计类似，面试都是可以提前准备的，一些太过常见的问题，可能会变成“背答案”，自然也无法得到真实的考察数据。

**第五，事先明确并聚焦考察的数据点，控制问题展开的进度。**一般采用行为型问题来进行面试的时候，我们可以逐步展开一个问题，并不断发问，但是需要注意的是，小心不要被候选人“拐跑了”，结果就感觉聊了很多，却没有什么有用的事实数据。

由于这种面试形式，并不像前面我们讨论一个“迷你项目”那样很容易看出其中的主线，因此我们需要很明确到底要着重考察什么，而不是和候选人“随便聊聊过去”。在得到自己想要的信息以后，可以先给讨论的问题收个尾，再开始下一个问题。

最后，我们来回想一下，对于一个行为型问题，**我们希望从候选人那里得到哪些内容？我觉得可以用“情境”、“思考”、“应对”和“结果”这样四个词来概括。**

也就是说，对于当时那种情况，候选人是怎样分析和思考的，于是采取了哪些做法，以及最后的结果如何。当然，在候选人的表达之后，根据内容我们可以从中提炼我们关心的考察数据，那完全是面试官的事了。

<img src="https://static001.geekbang.org/resource/image/e6/07/e63a51f2b647b14d6be40c2f79e57207.jpg" alt="">

总之，**对候选人的性格态度、沟通方法、处事风格等等与团队文化密切相关的要素，我们可以通过行为型问题做比较有针对性的考察，可以说这是对技术层面考察的一个非常必要的补充。**这样的形式并不需要花很多时间，非常精心地准备技术问题，而且讨论非常自由，对于没有工程师技术背景的面试官，更是可以比较顺利地采用，因此这种形式还是比较流行的。

## 总结与思考

在前面几讲介绍了针对软件工程师候选人的算法和数据结构考察，系统设计考察之后，在这一讲我讲解了一些其它工程技能的考察路径，并对于非常常见的一种非技术范畴的考察方式——怎样问行为型问题做了解读。

我要特别给你强调的是，行为型问题很有价值，但是我们还是要保证整个面试过程中，大部分的时间，还是要放在软件工程相关的技术考察方面，这一点我在[第2讲](https://time.geekbang.org/column/article/360268)的计划制定部分已经说过了。

<img src="https://static001.geekbang.org/resource/image/yy/f4/yye1f9165071ef95d6cb1d1e6ca797f4.jpg" alt="">

今天的主要内容就是这些。我想在最后留下一个问题，你能否在留言区和我一起讨论——在你的经历中，都有哪些我们没有介绍到的面试考察形式呢？

好，我是四火，我们下一讲见！
