最近看到了一个“程序员能力矩阵”,深感赞同,原文在这里:Programmer Competency Matrix ,另外 XGuru 同学的翻译在这里:[译文]程序员能力矩阵 Programmer Competency Matrix
回想一年前参加技术面试的经历,当时公司要招聘 Senior Java Developer 从每个项目叫了几个人去做技术面试(考官)。官方的硬要求是 3 年工作经验、CS相关专业毕业。在技术面试之前他们已经通过了技术和英语的笔试(我们是外企、英语为官方语言)。其中技术笔试题分为选择题和简答题,HR 的 MM 会把选择题的分算出来,也会给简答题一个大概的分数(毕竟天天看这几道题),遇到回答的太不寻常又头头是道的才会找工程师确认一下。其实这套题很简单,主要就是 Java 语言和标准库的一些内容,涉及到 EE 的东西不多(10%),对应到“矩阵”中基本都是 Level 1 的内容,很少有 Level 2 的内容,所以我觉得即使全答对也不并意味达到了 Senior 的程度,但同时我也并不要求面试者答满分。
HR 的标准是正确率 60% 以上就可以参加后一轮的面试,坦白说我觉得这个标准定的太低了,所以在面试开始前我会再看一遍他答的题,如果其中有致命错误(例如完全不知道 ArrayList 内部是用 array 实现的)就直接让 HR MM 回绝了。“矩阵”里列了很多东西,对于 Senior 我也有一个类似的标准,但在短时间的技术面试过程中很难对这么多方面进行判断,于是我个人制定了一个简单的方法,并相对一致的应用在每一次面试中。但让我遗憾的是通过这个测试的人很少……
我的方法很简单,我认为一个 Senior Developer 或有潜质成为 Senior Developer 的工程师应该至少具有以下素质:
1. 可以在有提示的情况下写出相对比较完美的代码。
2. 能够辨识出设计中的潜在问题,并提出改进方案。(这里面有一个潜在要求:理解他人设计和表达自己设计的能力)
3. 知识储备以及对于软件开发的热情与激情。
为什么是“有提示的情况下”,这里有两个原因:1. 因为“程序员不在纸上写程序”,面试中我们在纸上写程序,我会忽略书写错误,但对会引起编译错误的代码我会给出提示(但不会扣分)。2. 提倡但不要求程序员一开始就能想的尽善尽美,注重不断改进代码的能力。对于完美代码不同人有不同的认识,这里我希望看到:严谨的代码风格(包括对齐、命名、缩进……)、清晰的逻辑、适当的防御性验证、正确的错误处理、以及可行的性能优化。所有这些都可以通过下面这段简单的程序来考察:
我会要求面试者为下面这个类写一个 equals 函数(如果你有兴趣,不要看答案,来写写看):
class Money {
float amount;
String currency;
}
一般的面试者(3年以上经验)都能够至少顺利的写出以下代码(在实际面试中也遇到过完全不能写代码的,但大多数都写的比这个好一些):
public boolean equals(Money money) {
if (this.currency == money.currency && this.amount == money.amount) {
return true;
} else {
return false;
}
}
如果有 IDE 的提示你会发现 equals 是 Override 来的,其参数类型应该是 Object。这里我会问面试者为什么参数类型是 Object 以及问什么不可以是 Money。这两个问题非常考量表达能力。
修改过的代码如下:
public boolean equals(Object obj) {
Money money = (Money) obj;
if (this.currency == money.currency && this.amount == money.amount) {
return true;
} else {
return false;
}
}
上面的代码没有对输入做适当的检测,如果传入的是非 Money 的对象程序会抛出异常,这里需要对参数类型作出判断:
public boolean equals(Object obj) {
if (!(obj instanceof Money)) {
return false;
}
Money money = (Money) obj;
if (this.currency == money.currency && this.amount == money.amount) {
return true;
} else {
return false;
}
}
一般人的代码都会写到这个程度,但是这里面还有很大的空间,这时我会给出一点提示,比如“你觉得比较逻辑会不会有问题”,很多开发人员都会意识到需求其实还不清楚,比如 currency 是不是大小写敏感的?amount 比较的精度是多少?我没有在一开始就告诉面试者所有的要求,是因为用户不可能在一开始就把所有的需求想清楚,程序员要有发现潜在问题的能力。。
...
if (this.currency.equals(money.currency) && Math.abs(this.amount - money.currency) < LIMIT) {
...
到了这里,程序的正确性算是足够了,性能上还有提升的余地,但很多面试者基本上都想不出来了。比如:如果传入的参数是对象本身则不需要作任何判断直接返回 true;如果 Money 类是 final 的则可以用 getClass() 替代 instanceof 获得更高的性能;另外,别忘了复写 equals 的同时必须要复写 hashCode !
代码写到这里算是差不多了,如果基础好上面的过程很快,然后我们可以就这个类的设计进行讨论,比如:这个设计有什么不好?应该怎么设计?如果引入汇率怎么办?
最后我都会惯例性的问两个问题:最近有在看什么软件技术的书/文章/网站?那本(或几本)技术书籍对你最有帮助?通过这两个我希望知道面试者是否有足够的学习兴趣和对软件开发的热情,以及面试者的技术储备、知识结构是怎样的。在面试中我发现大多数的面试者只看过很少的编程书籍,但几乎所有人都看过 Think in Java。另外还有一个很诚实的面试者告诉我“最近在看一个 Java 程序员面试的视频教程”。
真正有经验的开发人员可能会觉得上面的面试过于简单,但根据我的经验,即使标准降低到如此程度我们也很难招到合格的人,对此我也很无奈。刚刚开始作技术面试的时候,我问的问题主要是集中在算法数据结构等方面,但是后来上面反应问的过难(如果 hash table 算难的话),无奈只能降低标准。