背景
又到了大家喜闻乐见的面试题环节了,本次我们就面试真题还原展示一下本次字节跳动面试的具体流程。
我这次拼着我以后再也不面试字节跳动了,也要把这次发生的事情和大家好好说道说道。面试这件事情吧,面试评价本身它就很主观,面试也是一个互相选择的过程,所以就算是面挂了其实我一般也都是不太所谓的,只能说大家猿粪未到而已。
但是让人不爽的事情是预设立场,如果大家觉得都不太合适,那么早点放过对方多好啊。。另外就是面试过程中充斥着傲慢,以及整场面试中散发的吊诡。如果本身一开始大家都没有要对方的预期,面试流程就没必要继续向下进行了吗。当前市场行情又不好,然后折腾人心态,这样就是浪费大家的时间!我如果万一都押宝在一家公司,那么我不就凉凉了吗!
如果现实中遇到不公,你们怎么办? 一点寒芒先现,然后枪出如龙!忍一时风平浪静,退一步越想越气!本文附带强烈的主观色彩,如果让你感受到不适,建议不要继续观看了。
侦探流程梳理
我不是名侦探柯南哦,我只是把我自己现在收集到的一些东西翻出来而已哦。假设说如下的东西有一点没满足哦,我其实都没有你们想的这么不爽的,但是偏偏就是这个样子。另外我也交待下背景,我面的是他们一个质量保障部门下面的负责自动化测试的部门的一个Android研发的岗位哦。
- 三面面试官以前是在阿逼的测试大佬。
- 面试前他和我好几个同事呢打听过我在阿逼做的事情。
- 面试前他加过我微信,然后还表述了他们部门需要一个研发岗,有过简单的沟通(这里只是主观看法哦 过多我不做臆测了)。
就是面试过程中吧,我不知道是故意还是要避嫌啊,面试官全程都是装作不认识我的样子,甚至让我都觉得他应该在字节工作了很久的样子。如果不是因为我之前在阿逼见过他几次,虽然也没有打过交道,面试过程中我只是猜测是他,所以也没有说。接下来就是本次的面试内容了。
面试内容
好笑的事情是面试的时候是10.7号 ,但是之前9.26的时候我也加了一个同样组的人,我现在还是觉得他们应该不是一个人啊,太有意思了。


接下来我们就直接聚焦于面试的内容本身好了!
面试官
这样我们简单聊一下是分几个部分,第一部分就我做一下自我介绍之后,你做一下你的自我介绍之后,然后你再展开你的项目稍微聊一下,那之后你可以问我一些问题,然后当然中间我会问你一些问题,那这样我先做一下自我介绍,然后我这边是 TT 质量团队的做持续集成 的,然后目前来说其实我们整个团队其实分为几个部分,第一个部分流水线的建设,第二部分就是工具链的建设,工具链的建设其实包含服务端相关的这种质量项目或者质量或者效能相关的工具站的建设,也有客户端相关的这种宣传效能过程,然后其实是我现在工作全貌。这样把问题交给你,你可以开始你自己的自我介绍。
虾
面试官你好,我叫逮虾户,在b站这边客户端基础架构从事安卓开发工作,我主要其实负责的也是安卓这边的ci/cd相关的流程,然后我们是负责整个安卓的大仓的一个编译打包,还有一些pipeline卡口之类的逻辑,还有一部分就是全局的质量监控之类的也是我们这边在做的,然后我们的工作的内容主要是面向研发侧的,我们会去优化既有的研发工作体验,包括之前Gradle的同步速度和编译速度之类相关的逻辑也都是我们这边在负责了。
然后还有一些我们也会做一些质检相关的,比方说unit test 的支持,还有lint检查之类的逻辑,其实我们也都有做,然后大概的工作内容都是这些,然后我们也会去做一些类似全局周知之类的逻辑,就比方说SDK更新,然后需要通知到所有的业务人员之类的,也是我们这边做的,然后大概的工作内容就是这些。
面试官
我们简单的聊一个问题,然后它其实是一个比较难的问题,可能在每家公司都有发生过,你看看你对这个问题的看法是啥,然后如果让你治理的话,你怎么治理这样一个问题。因为随着现代的产品迭代,所以我们知道很多产品的需求在上线前都要跑小流量或者是跑实验是吧?这其实是一个现状。
但是像我觉得b站应该也是这样子的,但如果我们把这个话题倒回到比如说更大的一些公司,哪怕比如说阿里或者是字节或者是百度这样的公司,然后如果在这样的公司里面,它的实验就非常的多,因为同时迭代的产品需求是非常的多的,但其实对如果大量的产品需求再加大量的实验,还有大量的数据底层的建设,经常会出现实验中遇到各种形形色色的问题,最典型的比如说实验之间的互相干扰是吧?
第一个问题是如何解决实验之间的互斥问题?
还有比如说实验的效果跌了,然后影响了别的效果是吧?还有可能比如说实验的,比如说实验全选的范围不合理,或者是实验全选的指标数据,它不鲁棒就没办法证实它这个数据其实它是有效的或正向的,甚至还有可能会出现实验上用户的一些非常负面的消极反馈是吧?所以其实这些其实可能都是实验上可能引起来的一些功能的问题,性能的问题,或者是用户反馈或者产品使用上的一些问题,这其实是一个现状。
如果假设因为我看你其实工作了挺多年,假设你是一个实验这里的owner的话,你觉得应该从哪些方面去考虑去治理,然后你会做什么样的工具,然后你会联动什么样的团队?然后包括你的road map是什么样子的,我觉得这个问题其实你可以先理解一下,理解完了之后你其实没有必要立马回答,我们可以稍微考虑一下,因为它不是一个简单问题。
虾
但凡是一个正常点的面试官其实不都应该去发掘下候选人的优点,你做题也行吧,就是你也挑一些比较搭边的关系啊,和你负责的ci cd或者说我的面试内容有什么关系啊??????????
我刚听下来其实因为我暂时还没有想到具体的答案。
面试官
就是因为所以我给你5分钟到10分钟的思考时间,然后你尽量把你能想到的东西能够稍微抽象一下,然后再跟我聊,你先稍微想一下,然后可以先把麦挂掉,然后你知不知道麦地掉,你可以在单上写一写,完了之后我们再聊,好,现在是15:32,我们15:40的时候开始进。
面试官
我们时间差不多了,你可以打开你的麦。我听不到。
虾
我这边写了一下内容,但是我不太因为时间也比较紧张,我也不太确定是不是。
面试官
可能你可以把你想到的说一下,我们就看一下你这个思路是什么样。是吧?
虾
这部分真的就是以前都没怎么接触过,而且我们的线上合入的实验其实都是研发侧自己写的代码,我们cd只提供特定的开关字段而已。另外我这里摊牌,如果现在还是这道题让我回答,那么我估计回答出来的还是这么依托答辩。你可以喷我菜,没问题,这个我真的承认。我从头到尾没有说过我这次面试表现的很好,我是觉得我应该挂掉的。
我首先想到的第一点就是实验之间最好肯定还是一个相互割裂的状态才会比较好,他们之间最好是不要互相影响。
然后我的第一个点,所有的实验都应该是从一个稳定的release切片出来的,然后它应该是一个然后 Ci和CD测就是要保证实验的结果是不是都能被有效的验证,比方说是它的版本和需求之间的关联,然后因为对于实验来说,CD ci测可能做的更多的应该是一些。
面试官
当我仔细去复盘的时候吧,发现他对于ci的理解其实还挺狭隘的。
没有必要放在cicd上做, 因为其实cicd在每个公司它其实就是pipeline,其实更重要的是在上面去加工具,所以你不要围绕着CCD在这个逻辑去聊。
虾
然后我的看法应该从一个特定分支切出来之后,然后以这个点作为一个实验的基准,把相关的代码进行合入,可能要对特定的分支进行一些所谓的代码实验和需求之间的串联,我们要保证的是一个实验能和到能被验证在这个需求上。
然后这样第一点做到的所谓的实验之间不会互相影响。然后这个实验因为是一个MR,所以它应该是能被快速的接入到主干上去的,它能被CP到不同的实验的场景上去,然后重复的验证这个实验是不是还会有别的关联,它也是能快速被回滚掉了。
这个是我想到其中一点,然后另外可能需要对于产物做一些特殊的插入,它是如何关联到一些特殊的用户或者别的啥,就是能去确保这个实验的质量是相对ok的。然后还有一部分可能就是和CD侧相关,因为 CD侧能需要发布的就是一些关于用户的画像,人群比例之后还有分发量,还有一些快速能回滚验证的一些东西,这个可能是我这这么短时间内能想到的一些关于这些。
面试官
所以其实我汇总一下汇总一下你刚才说的这个东西,然后第一点你说的就是实验之间,你要确保相互隔离,隔离的话,其实你的要求就是版本和需求之间要做关联是吧?是吧?然后你的方式其实是需要从特定分支切出来一个基准,然后先做一下基线,完了之后对特定的分支,然后关联实验需求确保其实是能被验证的是吧?其实我觉得理解可能是可测性。第二个其实是发布阶段,或者你觉得CD阶段需要去做啥,然后其实我不是特别清楚这个要做啥就完成什么样的目标,这个我不太清楚。
虾
我的想法可能是把需求之间的一些关键点插入到产物中去,让他能被快速的买点库之间做一个简单的上报。
业务研发同学不太需要对于需求进行一些特殊的标识或者别的啥,就能快速的去将两件事关联到一起,因为灰度其实更多的是要验证一个功能,是不是能被快速的验证这样的一个。
面试官
我们换个话题就是说我们还是对实验相关话题换个问题,你觉得我们刚才的这个问题里面的这些问题,它背后的原因到底是什么?假设你觉得实验之间互相干扰的原因是啥?
虾
实验之间互相干扰的一个原因,我觉得可能还是切片不太稳定,因为如果我们是在同一个包内去触发了多个实验,确实是有可能出现一种互相干扰的情况。
面试官
而且不是现在所有的实验基本上都在一个包里面的,它不是实验,实验其实是区分的流量,但不是和包有关系的。
虾
等等有一个gap,因为我们内部如果是这种实验的话,我们可能是单灰,可能是会对一些特定的,我第一点描述了它其实是在一个稳定的基线上,其实再重新插入的一个代码,它并不会把它主动关联到总包的那部分环节上去。
面试官
通过什么方式控制。
虾
其实相当于我们会主动的切除一些这样的这样的实验分支出来,然后它其实是在上一个或上一个稳定版本之间重新CP出去的代码,然后可能是用这种形式是做的独立灰度。
面试官
也就是我理解每个包一个实验是吗?对。
虾
我们会保证这种独立的灰度是不会互相干扰的,只会插入一些相对来说比较小的。
面试官
但是如果我现在有30个产品,30个产品都在做实验的话,岂不是有30个包?
虾
我们中间其实大部分是在是既有的,现在是这么个做法,现在是如果是30个的话,我。
面试官
其实应该也可以做。
虾
因为相当于我们还是这3030个实验能处理还是要处理在同1个包上,但是它们之间会互相干扰。我这确实有点没什么思路。
面试官
这个问题我觉得是最有意思的,最能展示出面试官能力的问题了。
好行,我们跳过实验话题,我觉得你没有接触过实验,我们聊一下你比较擅长的编译。你现在其实比较擅长的是安卓相关的这种构建编译,然后还有包括一些质量上的治理是吧?我们从质量的维度来说吧?因为其实因为其实每家公司或者是每个APP在其实在线上,不管它是初期还是到了后期,它其实都是保证一定的崩溃率的,或者是闪退率是吧?崩溃,包括crash、AR这些东西是吧?然后其实有一个话题,如果到达一定阶段的话,你觉得如果我要持续的去优化和治理崩溃,你觉得应该从哪些思路上去走?
然后从质量的维度来讲,你一个假设你是我们把这个题这样换一个假设,你现在已经入职了自己了是吧?其实比如说你负责的一个话题,我们要降低TT的崩溃率这件事情,然后你会从哪几个维度来走,然后你下面可能有3个人或5个人,你会做什么事情,分解什么样的目标给他们,让他们来协助达成降低崩溃率这个目标。
虾
这几天和你们聊下来,更多的我可能还是会从测试的角度去思考整个问题,因为首先还是会尝试去对整个工程建立一些所谓的质量保证体系相关的pipeline,就是把整个能做自动化测试都尽量去做到自动化测试,然后能做unit test尽量都做到unit test。
这里我描述的问题一直都是以模块作为维度的,如果当一个模块接入到自动化测试流程之后他的稳定性再进行一个正反馈的基础上,那么我觉得这样就能反向推动别的模块也进行同样的尝试。
然后从整个工程上来说,我肯定会先建立出来的是一个更细碎的先是有对应的基线,检查所有的ut的检查和和pipeline准入的一个规则。可能是先从基架的同学先出发,然后先保证这部分的代码是都已经做完所谓的基准测试或者cAT(安卓自动化UI测试),然后在这个基础上我们已经生成了一份report之后,会把所有的report数据进行一个关联,然后将模块的稳定性和 MR平台或者 APM 台进行一个关联,就是比方说特定的模块,其实它的它的整体的在接入了cAT和UT之后,它的崩溃率反倒开始下降之后,这样倒是有能力去反推到整个工程去进行一个持续化的治理的效果,然后可能拆解我手下负责的那几个人去分发或者转包给对应的实际的研发对应的leader之类的,让他们去做对应的后续的ut,然后其中肯定还会涉及到一部分基建能力,就是我们需要能快速的去生成ut或者cAT的一个建设,就是质量上的能让一个模块能通过一些更简单的工具去生成好它的自动化测试的脚本之类的逻辑,让整个工程或者说整个模块之间能快速的去完成这个事儿,这样的话应该也是能保证一部分代码质量,因为如果去单纯的靠线上的收集,其实已经是相对来说比较缓慢的过程,我们更多的可能会把操作都左移到ci侧去做。
面试官
面试官自己已经开始跑偏了。他所设想的问题还是基于代码和研发之间的,而并不是一个代码和自动化测试相关的逻辑。所以谁有问题?APM难道不能细分到模块维度吗,很奇怪的思路。
所以我在复述一下你刚才的描述,第一个可能要建立ut的检查,然后这个东西其实反映在pipeline上,你要做一些准入规则的检查,第一个。
第二个是如果上了线之后,或者相关的模块的稳定性和class的关联,你会把class检查平台类似于比如说一些埋点的一些数据是吧?上报的一些数据和模块的稳定性关联起来,这个我理解其实应该是内部APM是吧?
虾
稳定性相关的事情要做的是关联不是,我开始怀疑我面的岗位是什么了!!!
这个是这样的,我可能是更多的是把APM平台和一个UT相关的质量进行一个关联绑定,他的基线一开始在APM平台上应该已经都定好了,比方说一个模块之间的崩溃率可能是在万一左右,然后它通过了我们的自动化测试pipeline,保证了它后续的一些质量,是在一个下降的状态。
可能是会做这两个的一个关联,让其实对应的研发同学是能感受到接入这个东西是有实际的效果和对他们的质量是有保证的情况下,其实我是认为能反向推导整个事情的,继续后续向下继续执行。
面试官
他想干嘛??
不过我也把这个问题再换个话题来说,你觉得崩溃造成崩溃的原因是什么?
虾
其实崩溃的原因大部分还都是以空指针那些为主。
面试官
难道他不知道能提早通过UT或者自动化测试能力发现一些问题的吗,后面所有的情况都是一样的。所以我一直想说的就是这个面试官一直存在预设立场,还有就是他的知识面是不是有问题?
你现在所有做的工作都是守,就是攻和守你做的守。所以崩溃的原因到底是啥?
虾
这个时候我一直以为我在UT上已经和他达成了共识,然后我们需要对一些更简单的逻辑,通过静态扫描的形式去完成。
个人看法,崩溃的原因大部分还都是以代码质量出问题,或者一般情况下来说都是空非空的问题,或者说是或者说是一些类型转换异常之类的,其实它都不算是一个特别那种复杂的问题,还都算是那种常规的开发问题。
将一部分简单的问题移动到合代码阶段去进行拦截,我觉得没有问题吧?
如果是用lint 或别的啥去确保,其实也是可以,但是这个过程是这样的,我的看法是我们没有办法特别快速的去建立好一套所谓的静态检查规则,就是因为它其实更多的lint收集其实是要和APM串联的,我们通过APM的数据收集到一些哪些比较容易发生的一溃,然后去做对应的代码质量保证。
通过这种手段其实也可以做到一部分,先于在准入阶段就能做到代码质量的一个过程。
面试官
卧龙凤雏,你写的代码有bug难道是测试的问题?
你觉得crash的原因大部分都是代码的问题是吧?
虾
大部分应该都还是代码的问题。
面试官
现在b站的崩溃率大概是多少?
虾
大概是在万1-2左右。
面试官
哪个机型上崩溃率最高。
虾
其实哪个机型上我现在好像还不太确定,因为好久没看这个数据了。
面试官
然后你猜一下。
虾
其实我们现在大部分的崩溃都是都是C++层的挂掉的,它并不是那种特定机型上挂掉的,因为其实也治理到所谓的深水区了,很多都是在使用时长特别长的情况下,然后它的播放器挂掉的这种情况。
面试官
之前在阿逼确实是有这么个东西的,我不知道是不是他主导的哦。leakcanary和腾讯TAPD需求平台的一个结合,埋点上报的逻辑还是我在端上开发的,但是因为这个东西其实仅仅只和TAPD关联,没办法直接阻断MR合入,所以大部分研发都不太关注这个问题。
大部分泄露为什么会挂?
虾
可能还是一些内存泄露之类相关的东西。 C层的代码可能就寄了。
面试官
所以内存泄漏有没有办法检查出来。
虾
Leak其实还是比较容易检查出来的,leak其实可以直接在开发阶段就已经发现内存泄漏的话。
面试官
怎么发现?
虾
其实现在既有的工具都还挺成熟的,都是基于 Gc的逻辑去找的, Canada其实就能做到对你的功能。
面试官
在修这个bug吗?
虾
在修,因为其实之前是会把对应的立刻分发到对应的研发上去,之前是有对应的串联的,但是因为它不是一个强规则,就是我们之前的所有的leak其实是其实都是 tapd生成对应的bug,然后指向对应的开发人员,然后看他们的心情和状态决定是不是修正,是这么一个流程,所以他没有到一个人MR入的一个阶段,其实就没办法反向推导他们去做一些修正。
面试官
你觉得应该推吗?还是不?
虾
其实是应该推的。但是是之前到没有到一个一定要改的状态,所以他们也就没有动力去做,但是确实是应该改。
面试官
应该改的最大的困难是什么?
虾
我们之前的困境其实是研发侧和测试测其实两个流程不太关联,导致因为我们在研发侧其实报了报给到测试,然后测试其实生成的平台它并不是一个m准阻断的一个流程,它更多的是一个产业需求的流转这么一个过程,所以研发就算知道了这个问题,其实他如果没有主动的去把改了,其实它就不会影响到它后续河马的一个流程,所以如果能从流程上直接阻断他的和路,其实也是能强制到他,一定要去把这些东西修了。
这个情况对,所以之前是可能倒是因为测试和和研发之间还是不是不一定是研发河马的流程之间还是割裂的,所以导致了这个问题。
面试官
所以你觉得其实是流程上的问题。
虾
我所有描述的细节都是这个东西没有办法让开发感觉到痛点,所以他本身不影响MR合入的情况下,又不是一定要改的问题,没有人会去修的。
也不完全算是流程上的,其实应该算是一个部门之间的割裂,如果这个诉求其实能反向推导到,合代码测其实可能就会去促进这个事的完成。
面试官
部门的隔离是吧?因为研发在面对这些问题,他们有足够的质量意识。
虾
其实当前我们是没有的。
面试官
为什么没有?
虾
刚刚泄露那个问题,因为研发侧其实他们有时候是明显的能感知到这个地方是存在内存泄漏的,但是对他来说其实泄露的风险并不是一个致命级别的,因为它不会直接影响到用户的使用,而是一个长因为相当于它内存涨了,但是用户没崩,它之间就没有一个重视的程度。
面试官
世界上最可怕的事情是不懂装懂,你听我讲一讲就知道为啥了?????
我们再问一下其他的一些问题行吗?你这还有打包是吧?主要是打包,然后现在在安卓的打包,然后速度怎么样?
虾
我们其实是等一下,我看一下我的之前的记录,我们其实应该是拆开了三部分的,其实第一个是针对研发侧的,研发侧的打包应该一天是一天是800多次,然后平均耗时应该是在三分多,三分钟左右。
面试官
三分多是打出包来还是什么。
虾
打出包能装上去?
那个过程。
面试官
也就是打就从拉代码到编译打包三分钟,对。
虾
你们仓库有多大?我们仓库大概现在是800多个模块。
面试官
800多个模块,三分钟之内也能拉下来吗?不是。
虾
我说的是三分钟之内打包完成,我们是跟你们差不多,我们其实也是有云编译的逻辑的,所以那部分打包都是在远程机器上,然后只是有一个传输过程,所以它不需要拉到所有的代码,而且我们其实内部也有非常大量的二进制缓存产物,所以这部分三分钟内其实是能打出一个打打出一个包的,然后它其实所有的代码的变更其实是能在打包过程中生效的。
面试官
他根本不懂,然后他其实也不听别人说的,但凡稍微有了解过一些都不至于会说出这样的问题,还是字节里面的ppt看多了吗?
你怎么样确保这些中间的缓存的时效性,还有比如说确定缓存会不会过期什么东西。
虾
其实我们当前是由get下去保证的,然后另外一个我们也会想想办法去提高所谓的模块之间的缓存的复用率。
因为我们缓存之前是只有一个简单的前置机械版本的概念,然后我们把前置基线版本的复杂度做了一次提升,就相当于它的计算其实是基于路径去计算,就是它的复杂度变高了,就是它变的概率会就可以可以变更的力度会变得更小,这样的话其实是能提高这部分的缓存命中率的。
另外一部分我们其实也在做上传的那部分的缓存命中率调整,我们在上传 Ai模块的时候,其实是会把它整个文件的MD5签名也进行一个上传,如果发现这个东西其实已经存在在服务器上了,所以就不会去进行一个覆盖,而用上次那个版本就直接进行传输了。
所以缓存复用率其实我们内部是做了一部分技术调整去提高它的复用率的,而且我们也会删除一些过期的相当于之前历史用的那些历史用的那些缓存,然后定期做清理删除。
然后即使即使当前的缓存失效了,我们也推通过Python的形式去快速的把缓存在重新生成好再刷一遍到服务端,所以这些能力我们现在当前都是有,所以我们对于缓存复用率其实还是做了挺多事的。、
面试官
有热点文件吗?有热点文件吗?
虾
缓存里面热点文件是指。
面试官
比如说那么一台机器,它的IO特别的高,市盈率,其实这台机器上有抗诉。
虾
这个倒没有,因为我们其实整套的缓存并不是那种编译缓存,其实更多的是要是模块的二进制缓存,就编译缓存是归编译缓存的,编译缓存是由当前的远程打包机来保证的,而那个模块的缓存其实是由我们的 Last去决定,相当于两边其实是拆开的。
面试官
整个构建编译这块,然后出包这一块我理解应该有个打包平台,有没有出过事儿。
虾
事故肯定还是有的。
面试官
你比较印象深刻的是会有哪个?
原因是啥?
虾
有一个挺有意思,之前是游戏那边有两两个MR,然后他们之间互相关联,他们两个单独拆开来是都ok的,然后合到一起就把整个主干搞炸了。
当天然后又到最后我们切总包的时间了,然后就整个打包机开始疯狂挂,然后我们当时应该是5点多开始去处理那个问题,一直处理到6点6:00 6:20,然后最后才解了那个问题,然后导致那天打包出包,大概延迟了大概一个多小时。
然后那天其实就做了一次 CS,然后那次其实对我来说还比较深刻。
面试官
他开始质疑主干开发模式了!!!!!
但我觉得其实这个原因问问题是可以靠pipelien去避免的
虾
简单的说,一个人用了B aar里面新增了A代码使用,一个人升级了B aar,B aar里面把A代码删了???然后是两个不同的MR,你就算有pre合入分支也会挂啊!!!!!!!!!!!!
为什么pipeline没有避免的?这个是我们拍片都跑过了,它都是ok的,但是它们之间是互相关联互相影响,他们没有办法,当他们在创建 m二的时候,就没把他们关联到一起去,但是他们的前后脚和入反倒导致了变异异常。
一个同学改了一个底层的are,然后另外一个同学相当于改了 a二里面的方法调用,然后然后两就是一个人是在之前的产物上进行调整的,另外一个人是在之后的产物上进行。
面试官
我其实当时就想说了,你最后的处理方式不就还是回滚啊,我们的处理方式这个时候是Lock主干,要么回滚,要么改完之后合入,让别人可以继续合代码。
然后这里这里面的逻辑就是一个人改了之后,另外一个人肯定会打包编译不通过,是这样子的吗?
对,为什么没办法预合,预合是可以解决,预合这个动作也是可以在发现的。
虾
做的,是这样的,我们其实并你。
面试官
可以和mr,但是不需要和mr,然后确保其实还是可以work。
虾
这个是我们流程之间有一点点差别,因为其实我们是是这样的,我们只是单一主干,我们只要往主干上合了,意味着这个功能被合入了。
Ok的,我们其实主干是一个是一个不稳定的研发分支,但是release是从主干的特定时间点开始切出来的,所以如果我们按照我们之后的一段流程去操作工作电路其实是没问题,我们在紧急时间点就把把影响的人骂回滚掉就可以了,但是就那天我们可能更多的是想尝试去修改,然后把那个东西改成好,然后就出的问题,它并不你说的是方案是可行的,但是在我们这边没有用这种愈合分支的一个方案去做。
面试官
但我发现能听到你们其实非常典型的主干开发。
虾
对我们是单我们是主干开发。
面试官
首先哦,我们是有一个后置的mr合入的后置检查的,当这个检查阻断之后就会影响合入了,一般情况下都是work的,但是当天因为真的非常巧合,两个mr合入间隔很短,而且各自的pipeline其实都是完全通过的。
你们主干开发的话,你们没办法确保主干的稳定性这件事情,或者你做pipeline这件事情,不是这你的第一要任是啥?不是主干稳定性吗?
虾
我们第一要认识是主干稳定性,我们其实主干正常来说是稳定的,它的 MR最主要原因其实是MR之间互相干扰导致的,它并不是说我们的主干不稳定,我们主干其实一直处于一个稳定可打包,定时会打包的一个流程中,所以整体上来说我们的主干就正常是正常是ok的,我们也有后置的 lock逻辑,如果一个代码和Rieu之后影响主干,我们是我们是能及时的发现到的,这些逻辑其实我们也有很多所谓的方法签名检查之类的逻辑都存在,但是只是因为那一天那个事儿比较巧合,它并不是说是一个高发的问题,它其实对我们出现这种问题的概率非常低。
面试官
CS的时候有TODOList吗?
虾
有,其实我们做了对应的尝试,我们对于这段链路其实是进行了修复的,然后其实我们后面的对于整个这种时间节点的工作流和打包机其实都做了一点调整,是想办法去把这个东西给解掉,然后让后续情况就不再出现这种问题。
面试官
行,好,我看你还有你sonar好像写的是错的。
虾
可能拼写出问题了。
面试官
protobuf 我看你其实是了解的是吧? Pb就是protbuf 。 Pb的压缩协议你清楚吗?
虾
我不太清楚,因为我主要负责的是我们工程的 protobuf 的拆分,我们内部的整个协议都是用PP去完成的,所以所以我们的protobuf的数量会比较大,然后我们是对这个东西进行了一个治理。
然后我们大概是把一个大而全的破8仓库拆成了大概140多个小的这种grab的工程,让让他们之间的依赖重新进行了一次梳理工程,其实不太需要依赖于他没有实际使用到的一个 Pb,然后让整个工程的质量会变得更小。
面试官
端上的proto是怎么更新的。
虾
我们是四端共享一个仓库去做的。我们有一个单一的photobuf的 bapi的一个仓库,然后每个工程都会去主动的去克隆小的子仓,然后把里面的一个特定的目录进行文件展开,就比方说里面会有一些更细碎的标识符标识,它是一个可以转化成一个模块的文件,就一个叫8点m的文件,然后把这个文件路径下的 path下面的所有的buf.yaml进行一次重新聚合,生成一个额外的gradle工程。
然后通过。
面试官
我说句不好听的,你懂个锤子!!!技术细节中的缓存复用情况,gradle插件的原理,文件walk操作的多线程优化,gradle相关的生命周期阶段等等!!傲慢,纯粹的傲慢!
我懂了行。我问个问题,比如说我在pb的时候我做了一个删除,我原来是13字段,我把13字段删掉了,我现在在14又把13字段又增下来了,然后原来是个 int,后面是个string,然后这个时候肯定会有问题,在端上会不会有问题。
虾
端上如果是实际有引用的话肯定会有问题,因为它编译就会挂掉。相当于我如果直接使用了字段,就是它的类型转化就会出现异常。
面试官
你是不是不会java啊!强类型语言不懂吗?
其实没有类型转换。
虾
它在原生比方说生成java的时候,它就是有一个强类型的,它是一个字符串或者一个 int值其实就是已经固化的,如果在比方说我直接使用了 int字段的时候,他其实要腮的类型是一个字符串就会崩掉,编译的时候就会炸,就这个时候是这样。
面试官
你不想了解你问干嘛呢?你以为你是ci 过pipeline吗,这里有变更呢,你就要run一下?
安卓工程kmp编译能力你做了些啥?
虾
我们是支持了这个能力,相当于我们要双端都要去复用一个 kmp的项目,就是你可以理解为proto一样,只是一个扩展性的工程,可以输出两份业务代码给到iOS安卓,然后安卓端这边接入和设计是我这边去写行。
面试官
我知道他想问什么问题,pipeline或者打包有没有什么手段可以监控apk体积增长,但凡是个人都做了好吧!
现在安卓的包体有多大?
虾
现在应该是在100 100兆左右。100多。
面试官
你觉得瓶颈在哪?如果再缩小保底的话。
虾
瓶颈其实是在我们的降本增效上,其实因为之前其实我们有一些模块就是属于那种动态下巴的这种过程,然后但是那一部分其实更影响我们的带宽成本,所以就把代码下发的那部分逻辑移动到了整个包体内,我们后续就不太关心包体,就意味着把。
面试官
所以你们也不是不关心包体是吧?
虾
对不是不关心,是因为如果会影响到我们的整个带宽成本的话,其实对我们来说带宽会比会比包体更过分,所以不是说不关心,而是有一部分本来要动态下发的模块,后面就会转成这种原生模块。然后但是持续治理的话,其实我们也是在做一些这么一个事儿的,然后我们其实更多的手段是通过那种混淆或者代码优化的形式去做的。
面试官
行,你现在的主要的任务其实还是在做这种包体,还是在做编译这些东西是吧?对。行,你觉得你自己特长是啥?
虾
特长其实我想我觉得反倒是一个业务,就是我现在主要其实都会去处理一些比较难的技术需求,可能现在更多的有时候会承担这么一个角色,比方说我们之前pb的那个东西,其实我们因为kmp的适应性要求,所以它必须要生成一个没有jvm的一个单纯的kotlin代码仓库。
面试官
插入一嘴,所有的面试过程中,仿佛你都是想佐证你这样的一个观点,但凡你有在上面我表述的内容中多聊聊呢。你有一点点东西真的深入的问过了吗?我知道你这个职级已经不太关心技术细节了,但是所有的卡口都是由这么一点点的技术细节来完善的。
我倒觉得其实你不太适合质量方向,我觉得你还是去找一找端上的一些,因为你自己的兴趣爱好其实和质量方向其实可能有点差异是吧?你自己有没有感觉到?
虾
从研发流程上来说,如果我一个做ci cd的人都不适合做这个,那么你觉得一个测试能完成的更好吗,关于谷歌对于整个工程质量的文章,不是80%的测试内容应该交给自动化测试来负责吗? 我也是开发,我之前在写业务的时候压根也就不太关心这个事情,毕竟国内要让这些跑起来能work都挺难的,但是我在阿逼起码也是尝试过的,虽然我没有推广成功,但是UT和cAT的能力我们都是有前瞻性的调研的,而且增量和全量都是支持的,这些都是后话。
其实是我倒觉得还好,那你先听我说啊,你说我们也会去做一些所谓的质量校验的一个逻辑,这些其实我们都会有写,因为我们的所谓的每日报告什么这些东西,其实都是能保证去整个apk的运行的,就是我们会去做这么一个类似兜底的事儿,去让整个工程是能处于一个可运行的状态。
而且其实如果没有人去做这么一件事儿,就没有办法保证整个业务的下限,然后而且整个推进的流程其实也是由我们部门去做的,然后我们其实就相当于一个更多的承接,承接一个研发流程和一个MR合录的角色。
所以其实我是反倒是挺享受这个过程,是因为我们其实也是需要去做做客服做别的啥的事儿,让整个代码能被核心主干我们也会去承担那么多东西,然后包括ut相关的逻辑其实也是我们去承接的,所以我倒觉得我可以去胜任这么一件事儿。
面试官
我理解你其实更多的还是从技术的方向的角色,然后能够赋能整个比如说研测流程或者是测试的流程,或者是研发的流程,他们的一些角色或工作或者是一些比较棘手和麻烦的点,是这样子的是吧?对。我问的问题基本上问完了,因为我们其实聊了也是这样,好像我看一下多久了,半个多小时应该半个多小时,40分钟应该40分钟,你有什么问题要问吗?
虾
这部分我是务实的啊,这部分内容其实是在以往的文章中有所表现的。有时候研发是能自我感觉到一个问题的测试的复杂度的,如果我们不提供工具给到测试,让他们自己写? 是谁有问题啊?
我还是想问刚刚那个问题。我其实很想听一下,你为什么觉得我不太是不太适合质量保证的这么一个工作,因为说实话我还是觉得让我做的话还是能做的相对来说比较不错的。是因为在我的工作流程中,我也会去主动去把整个研测流程进行一个串联,并不是一个单纯割裂出来的部门,包括我们在做一些技术改造的时候,比方说合规相关的逻辑和一些调试组件相关的逻辑,我们更多的相当于要去做一些颜色串联的一个流程,比方说合规的那个事儿,如果我们去不去不去做一些提前的调试组件,其实测试的同学就是很难感知到整个流程是不是能符合到上线预期的。
然后另外一些我们其实也是做了一些类似启动流程的一个链路梳理,能让测试端快速的去发现一些所谓的所谓的启动裂化的一些异常,就是让测试去反推整个研发流程的一个变更。其实我不知道从你那边看为什么会这个样子就。
面试官
从未见过如此厚颜无耻之人!
因为其实我不太了解你的工作,你刚才说了一大堆,那都是你面试中没有体现出来的。
然后我们假设这个事情我是这样认为的,比如说有两个事儿,第一个事我们在做质量保障的时候,或者是哪怕是或质量工具校验的时候,哪怕是cicd的时候是吧?比如说整个流水线上放什么样子的能力,或者是放什么样的工具是吧?你肯定要思考为什么会放这样的工具,但是问题是啥?你解决目标是啥?对是吧?
肯定是这个逻辑去走。比如说我刚才问过你是吧?问过你一个问题,就是快死的原因是啥是吧?如果你说空非空是吧?还有音响处理这两个问题,你觉得是用可以用lint来解决的话, lint能解决的概率大概有多高?然后如果没有link,工具或者是link,工具已经有了,但是没有解决,剩下应该怎么去解决?一个研发一个研发的告诉他,你应该写出更好的代码来,还是怎么样子的。
假设crash你应该研发什么样的工具。
虾
这个点我想说一下,我觉得看看我们是要把它藏起来,还是说这是一个。
面试官
不藏起来,我们这边没有藏,对我不知道。
虾
所以不藏起来的问题都要暴露,所以不藏起来的流程不太一样的,它更多的还是要想办法提早的能把它抛出来。
面试官
他开始遗忘我之前说的所有自动化测试流程相关的逻辑了。
怎么抛?只靠静态代码检查或者代码扫描?
虾
那边不是我也提了一嘴,我们可以通过自动化测试的逻辑去补充那部分能力。
面试官
啥意思? 还是他了解的自动化测试其实只是uiautomator或者他后面聊的monkey
就是自动化测试能覆盖多少场景呢?确实打开APP,然后看个视频。
虾
这部分才是我所描述的问题的核心,他不应该被提早到代码的MR阶段去运行吗?
我说的UT可能不是你想的那种,因为我说的更多的是研发自己去写的 ut的覆盖和 cAT的覆盖,那边其实应该是在一个pipeline卡口阶段就应该会触发的逻辑。它如果这个模块有变更有改动,然后触发到对应的ut,然后它都能处于一个通过的状态,其实它才是一个可以准入的流程。
面试官
我也问了你一个问题,哪个机型上的更多一点,好像操作系统的分布上其实大不相同的,所以ut解决得了吗?
虾
它能不能解决所有的场景,只能说是说是有一部分提早能发现的一个情况。
面试官
没,我们其实是围绕这个话题来讨论。
虾
这个阶段其实我还在尽量的平复我的情绪,尽量的和对方是说明我可能是设想的不够周到导致的gap,面试过程中,面试者其实并不了解对方的技术栈,所以我只能从以往的工作经验来总结所有的面试相关的逻辑。
我知道没有较真,因为我是一个研发,我是会考虑这些事,但是有时候如果我临场没有太想到,其实我可能就会蒙住。但是我觉得从我现在的角度,去看待这个事儿,我觉得可能这个是我能想到既有的最优的方案。
面试官
是吧?行好,你还有其他问题问我吗?可能没有了。可能没有了,对,随便问。
虾
随便问。如果。你认为如何能去解决这些奇怪的场景,比方说还是刚问题挂了,然后然后它又覆盖在不同的机型上,如果去跑。
面试官
crash 是吧?我觉得其实有几点,第一点。我觉得要便利。就不管是Activity是卡死了,我们其实肯定要有一种便利的方式,这种便利的方式要么就是盲点,要么就是其他的混沌什么东西的,对你这肯定会有。
虾
这个就我插一句嘴,我刚刚说的cAT其实是能覆盖到这个场景的,就是cAT就是原生安卓test是能覆盖到特别的这种场景,它其实就相当于在模拟的壳上去跑这样的一个东西,其实如果是机型覆盖率足够的情况下,我觉得是能靠得住这个场景的,这是它是不同于我刚刚说的ut的那部分,所以如果是这个角度的话,我刚说的反倒他可能反倒会比monkey和 Ui的东西更准确。
因为Monkey以及uiautomator其实是要更多的是由测试去写的脚本用例,而cAT的逻辑其实更多的是研发侧去主动的去写的。
面试官
在字节的话,用例这个东西是研发写的。
虾
所以我觉得如果是如果是能完全推进所谓的安卓自动化测试的话,就是所有的应该也是能去解决这个场景问题。
面试官
好行,你还有问题吗?
可能就没有了。没了是吧?对没了。好行,我们今天面试就先这样,行,然后如果有后续的话,后续hr那行。
我的总结哦
最后我是承认我面试发挥的不好,毕竟这个场景题真的是写的依托答辩,所以这次挂了就是我应得的。我也是把每一次面试当作是一次成长,这次我收获的内容是devops更多的是一个承担着的角色,他更多的是负责串联起整个工程体系,让研发测试交付部署的流程变得有序,而不是仅仅只是之前为研发测服务的工具而已。但是并不代表我认同最后这个面试官所说的,还是那两个字傲慢!
但是我想说的是面试官你之前也是从阿逼出去的,如果你走之前阿逼也是这个样子,那么你是对于业务有多不了解啊,和研发测这边到底是有多割裂啊,还是说你只是想切割和阿逼的关系?你当时作为ep的负责人咋就没有啥有效的手段呢?能让我继续这么为所欲为,还是我们本身就是一个割裂的状态啊!
另外其实最后我也想提出这么几个问题哦:
- 面试官对于什么是安卓自动化测试不太了解的样子,虽然我也只学习了几天,但是我知道起码这个东西和Monkey不是一码事。
- 我不知道他所说的monkey真的能解决所谓的稳定性建设,不知道在pipeline合代码阶段提早的进行发现吗。还是能自动通知到对应的研发改?如果万一他不跑monkey呢?
- 对方是做ci cd的,那么如果他自己都不从ci的角度去做卡口而是通过执行特定的工具链,如何能够保证合入之后是稳定的呢?所谓的质量保证左移的操作如何进行?
- 最后关于单主干开发模式,我想问下谷歌是不是这么执行的?难道他们就不是单主干的模型?科普下主干开发
- 面试的时候是可以直接和候选人说你不太适合这个岗位这种话的吗?我面到三面你说这种话不是显得很无能吗?
我其实想说的就是一个面试官始终就是一个公司的脸面,如果你在面试的过程中就带着一些非常主观的看法,我觉得对于双方来说都挺无语的。
尤其是我这个人最不能接受的一点就是你可以质疑我,但是你起码在告诉我这个问题的答案的时候,给我的是一个真的比我牛逼的方案把,不能是monkey把!!!