1
0
mirror of https://github.com/Snailclimb/JavaGuide synced 2025-06-20 22:17:09 +08:00
Java-Interview-Guide/docs/high-quality-technical-articles/interview/how-to-examine-the-technical-ability-of-programmers-in-the-first-test-of-technology.md
2022-06-20 10:18:14 +08:00

344 lines
22 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: 如何在技术初试中考察程序员的技术能力
category: 技术文章精选集
author: 琴水玉
tag:
- 面试
---
> **推荐语** :从面试官和面试者两个角度探讨了技术面试!非常不错!
>
> <br/>
>
> **内容概览:**
>
> - 实战与理论结合。比如,候选人叙述 JVM 内存模型布局之后,可以接着问:有哪些原因可能会导致 OOM , 有哪些预防措施? 你是否遇到过内存泄露的问题? 如何排查和解决这类问题?
> - 项目经历考察不宜超过两个。因为要深入考察一个项目的详情,所占用的时间还是比较大的。一般来说,会让候选人挑选一个他或她觉得最有收获的/最有挑战的/印象最深刻的/自己觉得特有意思的项目。然后围绕这个项目进行发问。通常是从项目背景出发,考察项目的技术栈、项目模块及交互的整体理解、项目中遇到的有挑战性的技术问题及解决方案、排查和解决问题、代码可维护性问题、工程质量保障等。
> - 多问少说,让候选者多表现。根据候选者的回答适当地引导或递进或横向移动。
>
> <br/>
>
> **原文地址** https://www.cnblogs.com/lovesqcc/p/15169365.html
## 灵魂三连问
1. 你觉得人怎么样? 【表达能力、沟通能力、学习能力、总结能力、自省改进能力、抗压能力、情绪管理能力、影响力、团队管理能力】
2. 如果让他独立完成项目的设计和实现,你觉得他能胜任吗? 【系统设计能力、项目管理能力】
3. 他的分析和解决问题的能力,你的评价是啥?【原理理解能力、实战应用能力】
## 考察目标和思路
首先明确,技术初试的考察目标:
- 候选人的技术基础;
- 候选人解决问题的思路和能力。
技术基础是基石(冰山之下的东西),占七分, 解决问题的思路和能力是落地(冰山之上露出的部分),占三分。 业务和技术基础考察,三七开。
核心考察目标: 分析和解决问题的能力。
技术层面:深度 + 应用能力 + 广度。 对于校招或社招 P6 级别以下,要多注重 深度 + 应用能力,广度是加分项; 在 P6 之上,可增加 广度。
- 校招: 基础扎实,思维敏捷。 主要考察内容:基础数据结构与算法、进程与并发、内存管理、系统调用与 IO 机制、网络协议、数据库范式与设计、设计模式、设计原则、编程习惯;
- 社招: 经验丰富,里外兼修。 主要考察内容:有一定深度的基础技术机制,比如 Java 内存模型及内存泄露、 JVM 机制、类加载机制、数据库索引及查询优化、缓存、消息中间件、项目、架构设计、工程规范等。
### 技术基础是什么?
作为技术初试官,怎么去考察技术基础?究竟什么是技术基础?是知道什么,还是知道如何思考?知识作为现有的成熟原理体系,构成了基础的重要组成部分,而知道如何思考亦尤为重要。俗话说,知其然而知其所以然。知其然,是指熟悉现有知识体系,知其所以然,则是自底向上推导,真正理解知识的来龙去脉,理解为何是这样而不是那样。毕竟,对于本质是逻辑的程序世界而言,并无定法。知道如何思考,并能缜密地设计和开发,深入到细节,这就是技术基础吧。
### 为什么要考察技术基础?
程序员最重要的两种技术思维能力,是逻辑思维能力和抽象设计能力。逻辑思维能力是基础,抽象设计能力是高阶。 考察技术基础,正好可以同时考察这两种思维能力。能不能理解基础技术概念及关联,是考察逻辑思维能力;能不能把业务问题抽象成技术问题并合理的组织映射,是考察抽象设计能力。
绝大部分业务问题,都可以抽象成技术问题。在某种意义上,业务问题只是技术问题的领域化表述。
因此,通过技术基础考察候选者,才能考察到候选者的真实技术实力:技术深度和广度。
### 为什么不能单考察业务维度?
因为业务方面通常比较熟悉,可能就直接按照现有方案说出来了,很难考察到候选人的深入理解、横向拓展和归纳总结能力。
这一点,建议有针对性地考察下候选人的归纳总结能力:比如, 微服务搭建或开发或维护/保证系统稳定性或性能方面的过程中,你收获了哪些可以分享的经验?
### 为什么要考察业务维度?
技术基础考察,容易错过的地方是,候选人的非技术能力特质,比如沟通组织能力、带项目能力、抗压能力、解决实际问题的能力、团队影响力、其它性格特质等。
## 考察方法
### 技术基础考察
技术基础怎么考察?通过有效的多角度的发问模式来考察。
**是什么-为什么**
是什么考察对概念的基本理解,为什么考察对概念的实现原理。
比如索引是什么? 索引是如何实现的?
**引导-横向发问-深入发问**
引导性,比如 “你对 java 同步工具熟悉吗?” 作个试探,得到肯定答复后,可以进一步问: “你熟悉哪些同步工具类?” 了解候选者的广度;
获取候选者的回答后,可以进一步问:“ 谈谈 ConcurrentHashMap 或 AQS 的实现原理?”
一个人在多大程度上把技术原理能讲得清晰,包括思路和细节,说明他对技术的掌握能力有多强。
**深度有梯度和层次的发问**
设置三个深度层次的发问。每个深度层次可以对应到某个技术深度。
- 第一个发问是基本概念层次,考察候选人对概念的理解能力和深度;
- 第二个发问是原理机制层次,考察候选人对概念的内涵和外延的理解深度;
- 第三个发问是应用层次,考察候选人的应用能力和思维敏捷程度。
**跳跃式/交叉式发问**
比如,讲到哈希高效查找,可以谈谈哈希一致性算法 。 两者既有关联又有很多不同点。也是一种技术广度的考察方法。
**总结性发问**
比如,你在做 XXX 中,获得了哪些可以分享的经验? 考察候选人的归纳总结能力。
**实战与理论结合**
- 比如,候选人叙述 JVM 内存模型布局之后,可以接着问:有哪些原因可能会导致 OOM , 有哪些预防措施? 你是否遇到过内存泄露的问题? 如何排查和解决这类问题?
- 比如,候选人有谈到 SQL 优化和索引优化,那就正好谈谈索引的实现原理,如何建立最佳索引?
- 比如,候选人有谈到事务,那就正好谈谈事务实现原理,隔离级别,快照实现等;
**熟悉与不熟悉结合**
针对候选人简历上写的熟悉的部分,和没有写出的都问下。比如候选人简历上写着:熟悉 JVM 内存模型, 那我就考察下内存管理相关(熟悉部分),再考察下 Java 并发工具类(不确定是否熟悉部分)。
**死知识与活知识结合**
比如,查找算法有哪些?顺序查找、二分查找、哈希查找。这些大家通常能说出来,也是“死知识”。
这些查找算法各适用于什么场景?在你工作中,有哪些场景用到了哪些查找算法?为什么? 这些是“活知识”。
**学习或工作中遇到的**
有时,在学习和工作中遇到的问题,也可以作为面试题。
比如,最近在学习《操作系统导论》并发部分,有一章节是如何使数据结构成为线程安全的。这里就有一些可以提问的地方:如何实现一个锁?如何实现一个线程安全的计数器?如何实现一个线程安全的链表?如何实现一个线程安全的 Map ?如何提升并发的性能?
工作中遇到的问题,也可以抽象提炼出来,作为技术基础面试题。
**技术栈适配度发问**
如果候选人(简历上所写的)使用的某些技术与本公司的技术栈比较契合,则可以针对这些技术点进行深入提问,考察候选人在这些技术点的掌握程度。如果掌握程度比较好,则技术适配度相对更高一些。
当然,这一点并不能作为筛掉那些没有使用该技术栈的候选人的依据。比如本公司使用 MongoDB 和 MySQL 而一个候选人没有用过 Mongodb 但使用过 MySQL, Redis, ES, HBase 等多种存储系统,那么适配度并不比仅使用过 MySQL 和 Mongodb 的候选人逊色,因为他所涉及的技术广度更大,可以推断出他有足够能力掌握 Mongodb。
**应对背题式面试**
首先,背题式面试,说明候选人至少是有做准备的。当然,对于招聘的一方来说,更希望找到有能力而不是仅记忆了知识的候选人。
应对背题式面试,可以通过 “引导-横向发问-深入发问” 的方式,先对候选人关于某个知识点的深度和广度做一个了解,然后出一道实际应用题来考察他是否能灵活使用知识。
比如 Java 线程同步机制,可以出一道题:线程 A 执行了一段代码,然后创建了一个异步任务在线程 B 中执行,线程 A 需要等待线程 B 执行完成后才能继续执行,请问怎么实现?
”理论 + 应用题“的模式。敌知我之变,而不知我变之形。变之形,不计其数。
**实用不生僻**
考察工作中频繁用到的知识、技能和能力,不考察冷僻的知识。
比如我偏向考察数据结构与算法、并发、设计 这三类。因为这三类非常基础非常核心。
**综合串联式发问**
知识之间总是相互联系着的,不要单独考察一个知识点。
设计一个初始问题,比如说查找算法,然后从这个初始问题出发,串联起各个知识点。比如:
![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/open-source-project/502996-20220211115505399-72788909.png)
在每一个技术点上,都可以应用以上发问技巧,导向不同的问题分支。同时考察面试者的深度、广度和应用能力。
**创造有个性的面试题库**
每个技术面试官都会有一个面试题库。持续积累面试题库,日常中突然想到的问题,就随手记录下来。
### 解决问题能力考察
仅仅只是技术基础还不够,通常最好结合实际业务,针对他项目里的业务,抽象出技术问题进行考察。
解决思路重在层层递进。这一点对于面试官的要求也比较高,兼具良好的倾听能力、技术深度和业务经验。首先要仔细倾听候选人的阐述,找到适当的技术切入点,然后进行发问。如果进不去,那就容易考察失败。
常见问题:
- 性能方面qps, tps 多少?采用了什么优化措施,达成了什么效果?
- 如果有大数据量,如何处理?如何保证稳定性?
- 你觉得这个功能/模块/系统的关键点在哪里?有什么解决方案?
- 为什么使用 XXX 而不是 YYY
- 长字段如何做索引?
- 还有哪些方案或思路?各自的利弊?
- 第三方对接,如何应对外部接口的不稳定性?
- 第三方对接,对接大量外部系统,代码可维护性?
- 资损场景?严重故障场景?
- 线上出现了 CPU 飙高,如何处理? OOM 如何处理? IO 读写尖刺,如何排查?
- 线上运行过程中,出现过哪些问题?如何解决的?
- 多个子系统之间的数据一致性问题?
- 如果需要新增一个 XXX 需求,如何扩展?
- 重来一遍,你觉得可以在哪些方面改进?
系统可问的关联问题:
- 绝大多数系统都有性能相关问题。如果没有性能问题,则说明是小系统,小系统就不值得考察了;
- 中大型系统通常有技术选型问题;
- 绝大多数系统都有改进空间;
- 大多数业务系统都涉及可扩展性问题和可维护性问题;
- 大多数重要业务系统都经历过比较惨重的线上教训;
- 大数据量系统必定有稳定性问题;
- 消费系统必定有时延和堆积问题;
- 第三方系统对接必定涉及可靠性问题;
- 分布式系统必定涉及可用性问题;
- 多个子系统协同必定涉及数据一致性问题;
- 交易系统有资损和故障场景;
**设计问题**
- 比如多个机器间共享大量业务对象,这些业务对象之间有些联合字段是重复的,如何去重? 如果字段比较长,怎么处理?
- 如果瞬时有大量请求涌入,如何保证服务器的稳定性?
- 组件级别:设计一个本地缓存? 设计一个分布式缓存?
- 模块级别:设计一个任务调度模块?需要考虑什么因素?
- 系统级别:设计一个内部系统,从各个部门获取销售数据然后统计出报表。复杂性体现在哪里?关键质量属性是哪些?模块划分,模块之间的关联关系?技术选型?
**项目经历**
项目经历考察不宜超过两个。因为要深入考察一个项目的详情,所占用的时间还是比较大的。
一般来说,会让候选人挑选一个他或她觉得最有收获的/最有挑战的/印象最深刻的/自己觉得特有意思/感受到挫折的项目。然后围绕这个项目进行发问。通常是从项目背景出发,考察项目的技术栈、项目模块及交互的整体理解、项目中遇到的有挑战性的技术问题及解决方案、排查和解决问题、代码可维护性问题、工程质量保障、重来一遍可以改进哪些等。
## 面试过程
### 预先准备
面试官也需要做一些准备。比如熟悉候选者的技能优势、工作经历等,做一个面试设计。
在面试将要开始时,做好面试准备。此外,面试官也需要对公司的一些基本情况有所了解,尤其是公司所使用技术栈、业务全景及方向、工作内容、晋升制度等,这一点技术型候选人问得比较多。
### 面试启动
一般以候选人自我介绍启动,不过候选人往往会谈得比较散,因此,我会直接提问:谈谈你有哪些优势以及自己觉得可以改进的地方?
然后以一个相对简单的基础题作为技术提问的开始:你熟悉哪些查找算法?大多数人是能答上顺序查找、二分查找、哈希查找的。
### 问题设计
提前阅读候选人简历,从简历中筛选出关键词,根据这些关键词进行有针对性地问题设计。
比如候选人简历里提到 MVVM ,可以问 MVVM 与 MVC 的区别; 提到了观察者模式,可以谈谈观察者模式,顺便问问他还熟悉哪些设计模式。
可遵循“优势-标准-随机”原则:
- 首先,问他对哪方面技术感兴趣、投入较多(优势部分),根据其优势部分,阐述原理及实战应用;
- 其次,问若干标准化的问题,看看他的原理理解、实战应用如何;
- 最后,随机选一个问题,看看他的原理理解、实战应用如何;
对于项目同样可以如此:
- 首先,问他最有成就感的项目,技术栈、模块及关联、技术选型、设计关键问题、解决方案、实现细节、改进空间;
- 其次,问他有挫折感的项目,问题在哪里、做过什么努力、如何改进;
### 宽松氛围
即使问的问题比较多比较难,也要注意保持宽松氛围。
在面试前,根据候选人基本信息适当调侃一下,比如一位候选人叫汪奎,那我就说:之前我们团队有位叫袁奎,我们都喊他奎爷。
在面试过程中,适当提示,或者给出少量自己的看法,也能缓解候选人的紧张情绪。
### 学会倾听
多问少说,让候选者多表现。根据候选者的回答适当地引导或递进或横向移动。
引导候选人表现他最优势的一面,让他或她感觉好一些:毕竟一场面试双方都付出了时间和精力,不应该是面试官 Diss 候选人的场合,而应该让彼此有更好的交流。很大可能,你也能从候选人那里学到不少东西。
面试这件事,只不过双方的角色和立场有所不同,但并不代表面试官的水平就一定高于候选人。
### 记录重点
认真客观地记录候选人的回答,尽可能避免任何主观评价,亦不作任何加工(比如自己给总结一下,总结能力也是候选人的一个特质)。
### 多练习
模拟面试。
### 作出判断
面试过程是一种铺垫,关键的是作出判断。
作出判断最容易陷入误区的是贪深求全。总希望候选人技术又深入又全面。实际上这是一种奢望。如果候选人的技术能力又深入又全面很可能也会面临两种情况1. 候选人有更好的选择; 2. 候选人在其它方面可能存在不足,比如团队协作方面。
一个比较合适的尺度是1. 他或她的技术水平能否胜任当前工作; 2. 他或她的技术水平与同组团队成员水平如何; 3. 他或她的技术水平是否与年限相对匹配,是否有潜力胜任更复杂的任务。
### 不同年龄看重的东西不一样
对于三年以下的工程师,应当更看重其技术基础,因为这代表着他的未来潜能;同时也考察下他在实际开发中的体现,比如团队协作、业务经验、抗压能力、主动学习的热情和能力等。
对于三年以上的工程师,应当更看重其业务经验、解决问题能力,看看他或她是如何分析具体问题,在业务范畴内考察其技术基础的深度和广度。
如何判断一个候选人的真实技术水平及是否适合所需,这方面,我也在学习中。
## 面试初上路
- 提前准备好摄像头和音频,可以用耳机测试下。
- 提前阅读候选人简历,从中筛选关键字,准备几个基本问题。
- 多问技术基础题,培养下面试感觉。
- 适当深入问下原理和实现。
- 如果候选人简历有突出的地方,就先问那个部分;如果没有,就让候选人介绍项目背景,根据项目背景及经验来提问。
- 小量练习“连问”技巧,直到能够熟悉使用。
- 着重考察分析和解决问题的能力,必要的话,可以出个编程题。
- 留出时间给对方问:你有什么想问的?并告知对方三个工作日内回复面试结果。
## 高效考察
当作为技术面试官有一定熟悉度时,就需要提升面试效率。即:在更少的时间内有效考察候选人的技术深度和技术广度。可以准备一些常见的问题,作为标准化测试。
比如我喜欢考察内存管理及算法、数据库索引、缓存、并发、系统设计、问题分析和思考能力等子主题。
- 熟悉哪些用于查找的数据结构和算法? 请任选一种阐述其思想以及你认为有意思的地方。
- 如果运行到一个 Java 方法,里面创建了一个对象列表,内存是如何分配的?什么时候可能导致栈溢出?什么时候可能导致 OOM 导致 OOM 的原因有哪些?如何避免? 线上是否有遇到过 OOM ,怎么解决的?
- Java 分代垃圾回收算法是怎样的? 项目里选用的垃圾回收器是怎样的?为什么选择这个回收器而不是那个?
- Java 并发工具有哪些?不同工具适合于什么场景?
- `Atomic` 原子类的实现原理 `ConcurrentHashMap` 的实现原理?
- 如何实现一个可重入锁?
- 举个项目中的例子,哪些字段使用了索引?为什么是这些字段?你觉得还有什么优化空间?如何建一个好的索引?
- 缓存的可设置的参数有哪些?分别的影响是什么?
- Redis 过期策略有哪些? 如何选择 redis 过期策略?
- 如何实现病毒文件检测任务去重?
- 熟悉哪些设计模式和设计原则?
- 从 0 到 1 搭建一个模块/完整系统?你如何着手?
如果候选人答不上,可以问:如果你来设计这样一个 XXX 你会怎么做?
时间占比大概为 技术基础25-30 分钟) + 项目20-25 分钟) + 候选人提问5-10 分钟)
## 给候选人的话
**为什么候选人需要关注技术基础**
一个常见的疑惑是:开发业务系统的大多数时候,基本不涉及数据结构与算法的设计与实现,为什么要考察 `HashMap` 的实现原理?为什么要学好数据结构与算法、操作系统、网络通信这些基础课程?
现在我可以给出一个答案了:
- 正如上面所述,绝大多数的业务问题,实际上最终都会映射到基础技术问题上:数据结构与算法的实现、内存管理、并发控制、网络通信等;这些是理解现代互联网大规模程序以及解决程序疑难问题的基石,—— 除非能祝福自己永远都不会遇到疑难问题,永远都只满足于编写 CRUD
- 这些技术基础正是程序世界里最有趣最激动人心的地方。如果对这些不感兴趣,就很难在这个领域里深入进去,不如及早转行从事其它职业,非技术的世界一直都很精彩广阔(有时我也想多出去走走,不想局限于技术世界);
- 技术基础是程序员的内功,而具体技术则是招式。徒有招式而内功不深,遇到高手(优秀同行从业者的竞争及疑难杂症)容易不堪一击;
- 具备扎实的专业技术基础,能达到的上限更高,未来更有可能胜任复杂的技术问题求解,或者在同样的问题上能够做到更好的方案;
- 人们喜欢跟与自己相似的人合作,牛人倾向于与牛人合作能得到更好的效果;如果一个团队大部分人技术基础比较好,那么进来一个技术基础比较薄弱的人,协作成本会变高;如果你想和牛人一起合作拿到更好的结果,那就要让自己至少在技术基础上能够与牛人搭配的上;
- 在 CRUD 的基础上拓展其它才能也不失为一种好的选择但这不会是一个真正的程序员的姿态顶多是有技术基础的产品经理、项目经理、HR、运营、客满等其它岗位人才。这是职业选择的问题已经超出了考察程序员的范畴。
**不要在意某个问题回答不上来**
如果面试官问你很多问题,而有些没有回答上来,不要在意。面试官很可能只是在测试你的技术深度和广度,然后判断你是否达到某个水位线。
重点是:有些问题你答得很有深度,也体现了你的深度思考能力。
这一点是我当了技术面试官才领会到的。当然,并不是每位技术面试官都是这么想的,但我觉得这应该是个更合适的方式。
## 参考资料
- [技术面试官的 9 大误区](https://zhuanlan.zhihu.com/p/51404304)
- [如何当一个好的面试官?](https://www.zhihu.com/question/26240321)