从外企技术面谈起

ThoughtWorks

前言

近些年,国内某些大厂各种强制员工加班的新闻层出不穷。就在昨晚,跟一个学长交流的过程中,我叫他一起开黑,他却跟我说还在加班,让我先开,想想可能这就是自己毕业工作的样子…虽然我本人也想去大厂上班(主要是钱多但确实能力不足),但是相比之下,我也更愿意去外企上班。其中最大的原因是955工作制度,那样我就有足够的时间在周末去学习新的知识,另外也可以做我的自媒体,学习张哥,打造一个个人的IP。今天下午刚好面试了ThoughtWorks[1],只可惜结果不是很好,就在这里聊一聊自己的一些感受。

面试内容

面试的标题叫做结对编程[3],这是一种敏捷开发的方法,敏捷开发也是贯彻在这家公司的一种开发思维。而结对编程就是一个人在写代码(也就是面试者),另一个人在审查代码(也就是面试官)。

本次面试的内容是基于面试邮件中给出的一个购物车代码仓库[2]的源代码进行二次开发的,所有的开发都是针对需求进行的,由面试官给出需求,再由面试者现场进行需求的实现,也就是编码工作。这不仅考察了面试者的逻辑思维能力(对题目的理解程度以及团队配合交流等能力),也考察了对于语言基础知识的掌握程度。

技术面试主要是面试官给到我们三个需求,我们在代码的基础上写代码利用unittest进行单元测试最后在留几分钟时间来给面试者进行提问。

有一点值得说一说的是,ThoughtWorks的面试是很有时间观念的,不会提早也不会拖延,面试官会期间会跟你说明面试的时长的。

技术点

这点是根据你在简历投递的时候选择的方向来的,我所选的方向是Python,因此主要以Python的知识为主。细分的话主要有下面两个方面

  • Python(各种基础知识)
  • unittest (Python3自带的模块,一个单元测试框架)

需求1

思路

简单明了,直截了当,加一个判断分支,写好计算公式即可

面试官的第一个需求很简单,将购物车中以DIS_20的产品码开头的产品按八折计算价格,且需要按照20元一积分的情况按照给出的代码的基础上,可以模仿者着去写一个自己的功能函数。

这题比较简单,按照之前给出的参考样例代码就可以模仿着写出答案了,该题做对。

image-20210116224931963

之后是编写一个单元测试

image-20210116225624629

需求2

第二个需求是处理“买二送一”这种情况的处理

思路

联系日常生活的情况,来理解究竟什么是买二送一。也就是买两件和三件的价格是一样的,以此类推。。。

做这个题目之前,面试官先问了我知不知道TDD[4](Test-Driven Development,也就是测试驱动开发)的含义,好在我是修过《软件质量与保证》课程的人,这点虽说不是很熟悉但是还是有点了解的,立即回答是测试驱动开发,然后面试官又问了我对于这个的理解,然后还说这个需求我们先不着急去写代码,要用TDD的方法来进行开发,先讨论了一下对于这道题目逻辑上的理解,买二送一也就是买两件和三件的价格是一样的,另外你买四件只需要付三件的价格,买五件的和买六件的价格也是相同的。经过交流思路之后,面试官给出了三个测试用例,然后让我根据这个测试用例来编写代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def test_should_calculate_price_and_loyalty_points_for_one_buy_2_get_1(self):
products = [Product(PRICE, "BULK_BUY_2_GET_1_ABCD", PRODUCT)]
cart = ShoppingCart(CUSTOMER, products)

order = cart.checkout()

self.assertEqual(100.00, order.total)
self.assertEqual(20, order.loyalty_points)

def test_should_calculate_price_and_loyalty_points_for_two_buy_2_get_1(self):
products = [Product(PRICE, "BULK_BUY_2_GET_1_ABCD", PRODUCT), Product(PRICE, "BULK_BUY_2_GET_1_ABCD", PRODUCT)]
cart = ShoppingCart(CUSTOMER, products)

order = cart.checkout()

self.assertEqual(200.00, order.total)
self.assertEqual(40, order.loyalty_points)

def test_should_calculate_price_and_loyalty_points_for_three_buy_2_get_1(self):
products = [Product(PRICE, "BULK_BUY_2_GET_1_ABCD", PRODUCT), Product(PRICE, "BULK_BUY_2_GET_1_ABCD", PRODUCT),
Product(PRICE, "BULK_BUY_2_GET_1_ABCD", PRODUCT)]
cart = ShoppingCart(CUSTOMER, products)

order = cart.checkout()

self.assertEqual(200.00, order.total)
self.assertEqual(40, order.loyalty_points)

这里实际上需要测试的就是买一件商品时候的总价格,买两件商品时候的总价格,买三件商品时候的总价格以及用户积分的计算。

第二题需要考虑的情况很多,购物车的product列表中,可能有很多种商品(以DIS_20开头的或者以其他开头的),除此之外,以买二送一商品编码开头的商品也可能是不同种类的商品,这点也需要考虑到,经过几次尝试我发现我最开始的方向都是错的,后来我想到了用一个字典来存储不同种类的买二送一商品的数量,通过键值对的方式存储在字典里面,字典的键存放商品的名称,字典的值里面存放该商品的数量。面试官也肯定了我的这样的一个思路,但是在实现的环节,由于对于字典在平时用的比较少,Coding环节出现了问题,卡住卡了半天,白白浪费了很多时间。直接导致本次面试失败。。。

面试结束之后,我又仔细的思考了一下并查阅相关资料,我现在对于字典的使用有了了解

需求3

时间没来得及,需求3的题目我并不知道。。。

反问环节

作为面试了有二十多家公司的老油条,我还是知道需要问哪些问题的,这点可以去看看我的面试宝典[5]里面的最后一条

三个题目我做到了第二道题目,第二道题目的思路我已经有了,但是由于语言基础还是不够扎实,因此没有把代码写出来。估计大概率也是凉了。未来还是需要在基础知识上多花功夫,这也侧面说明了我在平时自学的时候,知识往往不成体系,另外也存在对于知识的实际应用场景不够了解,还是需要在实际项目中去锻炼对于知识点的灵活运用。

总结

总体来说,ThoughtWorks面试考察的内容并不难,并且虽然本人是双非二本出身,但是这家公司并没有因为自己的学历就直接把简历给pass(国内有些公司的招聘硬性要求直接是985/211,可把我们这些人给难倒了),从这点来看,外企还是很nice,但是你要说学历歧视,在哪家公司估计都会多少有些的。对于我们这些非名校出身的同学来说,只能通过不断提高自己的基础知识,才能够在学历没有优势的情况下和那些学历比较高的同学一决高下。接下来的寒假时间里面,我就需要不断的夯实自己的基础知识,力争在自己熟悉的方向达到专精的程度,另外总是在学基础也不是个好的训练方法,通过今天的面试来看,还是需要在实际的项目中去把自己所学习的数据结构给运用起来,不然学书本上的基础知识是往往是不知道这个知识点的应用场景的。

另外一点是,编码的规范性,函数有函数的命名规范,列表中各元素之间需要加上空格进行分隔,写功能之前先想一想单元测试用例的情况来避免编码时候出问题等。

image-20210116232503533

收获

  • 编码规范性
  • 对于基础知识的回顾与其实际使用场景的认识

Reference

[1] ThoughtWorks官网: https://www.thoughtworks.com/cn/

[2] 购物车代码仓库: https://github.com/techops-recsys-grad-hiring

[3] 结对编程 https://baike.baidu.com/item/%E7%BB%93%E5%AF%B9%E7%BC%96%E7%A8%8B/7526152?fr=aladdin

[4] TDD: https://baike.baidu.com/item/TDD/9064369?fr=aladdin

[5] 面试宝典 https://github.com/GuoXianSen/InterviewBible/blob/main/%E9%9D%A2%E8%AF%95%E5%AE%9D%E5%85%B8.md