如何成为一个优秀的程序员?

Posted 赵广陆

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何成为一个优秀的程序员?相关的知识,希望对你有一定的参考价值。

目录


1 靠谱的程序员

复盘一下近几年开发的历程,那本质上来说,程序员的一个职业素养或者说优秀的程序员,简单来说就是两个字,靠谱。

那你是否靠谱?决定了offer能否发放给你,你不会对我们的企业或者团队会有致命的一些伤害。那因此什么是代表的是你是一个靠谱的程序员,我们如何去展现你的一个职业素养呢?那首先我将我那么多年的面试经验以及企业的用人标准,浓缩了一下所谓的一个靠谱的程序员所必须具备的三大素养,那分别是解决问题的能力,以及团队协作的能力,外加自我驱动的能力,那我们接下来就要分别结合这样的一个三点的能力,来为大家展示什么是一个靠谱的程序员。

2 解决问题的能力

那接下来我们首先来看一下三大素养之一的一个解决问题的能力。那首先我们需要定义清楚什么样的程序员是有一个好的解决问题的能力。

经常我们在面试的时候讲,我们要体现我们的软性素质,或者我们的面试官要求考察出面试者的一个软性素质,那我们是否有这样的一个标准,还是说我们可以结合一些主观的判断去判断这个人是否拥有好的解决问题的能力。

那如果说一旦有这些模糊或者清晰的标准去做判断,自然我们的程序员同学就可以在平时去训练自己这样的一个解决问题方式的一个思维方式,使得你能够在面试的过程当中凸显你的解决问题的能力。那首先我们来看一下什么叫好的解决问题的能力,

我在这边主要总结了三个要素,分别是快速定位深入分析取舍解决

那我们怎么去理解这样的三句话呢?那面试官在进行考察问题的时候,经常会以问题的方式去做考察点,比如说如果说线上发生了一个集群崩溃这样的一个问题,你会如何解决?

那从这样一个问题当中,我们可以逐步的去挖掘我们的程序员候选人同学他解决问题的一个能力和思路是怎么样的。

2.1 快速的定位

我们首先当线上也好,或者平时的工作当中也好,遇到了一些问题的话,我们需要去根据一些条件做一些快速的问题的出差和排查,比如说。如果说我们要去定位一些线上的问题,我们如何去快速的找出差错呢?

我们在线上,都会去根据一些业务的要求去配置一些报警,那我们可以根据这些报警的一个内容快速的去找出一些内容。比如说我们的接口耗时是否有明显的增加,哪些接口的耗时增加了我们的数据库的一个sql语句的慢,哪些慢sql导致了数据库的耗时的一个严重,我们的网络耗时是否增加,网卡的流量是否被打满,我们是否发生了JVM的out of memory的异常,或者jcc非常的频繁,那这些对应的所有的这些问题点都可以监控埋点的方式预先植入到我们的系统当中,以使得我们的系统在出现大规模的问题的时候可以。快速的去做一轮初筛,方便我们快速的去定位一些问题,然后等我们有了一些快速的一个初筛,大致的一个判断之后,没有时间再去深入的去做一些问题的查询,因为为什么?
我们的线上的集群已经出现了一个大规模的问题,一个优秀的程序员在线上出现问题的时候,第一个想到的并不是说我怎么去深入的分析这个问题,而是说我有没有什么快速的方式可以去做产线止血,防止问题的扩散,或者对用户的体验造成极为不利的一个品牌影响。

那因此我们是不是有一些快速止血的一个方案,比如说我们出山出来某一些接口有问题,我们可以做一些熔断的降级的策略,或者我们发现我们是因为大规模的流量导致整个的一个集群负载能力达不到我们的要求,是否可以做一些快速限流的一个策略,又或者说当我们发生了JVM的out of memory的时候,做一些快速的重启策略,就能够快速的使我们的系统恢复到一个比较可以接受的一个状态下,然后第三步需要做一些验证性的一个尝试。在经历了这些快速止血的策略堆上去之后,我们要验证一下问题是否得到缓解,或者是否问题得以完全的一个消除。因此我们需要做一些验证性的尝试,确认我们的这些快速止血的手段是恢复了我们的一个问题。那虽然说我们要求了大家做这样的一些模板化的一个操作,但是在实际产线当中发生大规模的一个集群崩溃的问题,往往是很难追踪,很难查询的。本质上来说,我们集群在经历了一个N多的开发的一个堆叠,以及我们的一个分布式微服务的扩散拆分之后,往往会造成许多级联的一个问题,比如说我、ABCDE5个服务互相级联调用,那这个时候如果说最后的源头是一这个服务产生的问题,在ABCD各个服务上面都会有不一样程度的一个表现,这样的话使得我们问题的分析和定位变得非常的困难。即便我们最终定位到了一服务本身的一个问题,在经历了一服务本身问题的消除之后,我们也难确保在问题发生期间,ABCD服务不会被诱发出其他自身的一些问题。因此我们整个的一个级联问题是最难解决的,这个就要求我们在做系统设计的时候,对边界的一个划分非常的重要,我们必须得明确我们的ABCDE系统互相工作职责的一个边界。

在边界之上,容错设计,那什么叫容错设计?Google这家公司之所以伟大,出现问题的一个频次相较于其他互联网公司更小,并不是在于说它整个的一个系统设计有多么的复杂,而是因为它本质上来说,内部的系统设计都是基于容错设计的。我发起一行代码的调用,非常明确的可以知道说在未来的某一天,这一行代码可能会因为外部环境,比如网络,数据库,硬盘,甚至于代码自身或者说编译器自身会产生一些问题,因此我需要对我写下的这行代码做充分的一个容错设计,这样的话才能保证说当这行代码被外部的因素干扰导致问题的时候,可以快速的去做修复。`那因此我们其实做问题的快速定位的这些报警、止血措施,验证手段,本质上来说。

是需要去融入在我们平时的一个系统开发当中的,我写下每一行代码都需要完美地去实现,当我这行代码出问题的时候,我如何报警上来体现在哪一类问题上?当我这行代码发生问题的时候,我如何做快速的一个止血降级?当我这行代码出现问题的时候,我能够以什么样的方式去做尝试的一个恢复那?因此快速定位问题本质上来说是以我们所有的代码都需要在容错设计的前提下才能够达到的。试想一下,如果说你在解决问题的时候,什么线索都提供不了,什么内容都查询不到,甚至于连行日志都没有,那你是没有办法快速的定位问题的。

好,那讲完了这个快速定位问题之后,接下来要去深入的分析一下我们的一个具体的原因。虽然说看似我们的问题被定位了,然后我们故障得以缓解或者解决,那我们需要去能够有时间在产线上止血的情况下,可以有时间去深入分析我这个问题的一个具体原因是什么?

2.2 深入分析

比如说是不是我对应的这条查询的数据量太大了,是不是有慢sql,或者说我刚刚经历了一个什么样的发布,发布的代码有没有bug,或者说是不是我的接口被人恶意攻击,被刷了。那因此整个的这样的一个深入分析的一个具体原因,他深入分析都是为了去找到问题出现的触发条件,也就是本来我线上运行的好好的一个代码,突然出现了一些问题,一定是有触发条件的,可能是因为发布引起的代码变更,也可能是一些用户或者后台的一些操作导致了原本数据产生了一个变革和问题,又或者是产线上面被恶意用户给攻击了,那最后可以去总结一些原因。我们分析定位总结到一些问题的一个具体深度的一个原因,那最后我们需要去取舍的解决,也就是说我们需要去在问题的一个深入分析的一个原因基础上。做一个我们用什么样的方案可以解决什么样的问题,那这样的方案还会不会引入别的什么样的问题,我们后续该如何改进,那这本质上是一个方案取舍解决的一个问题。

2.3 取舍解决

我们所有的方案并不可能做到100%完美,都会牺牲某一步来得到成全。另一部就像我们分布式系统当中的cap原理,永远都是三个角只能选取两个,因此整个解决问题的一个最最困难的地方往往是我们没有一个100%对的一个标准答案,都会遇到各种各样的一个问题,哪怕方案是十分完美的,也会跟我们的时间和人力成本产生冲突。因此解决问题最后的一步,我们需要有充分的判断来做取舍,我放弃这个成全那个,来满足我最后的一个方案的一个解决落地。那我们接下来就拿一个case举例

当面试官问你有没有经历过产线上面的一些什么样的一个崩溃问题,然后你是如何解决的?那我们最好的一个方式是去举一个例子来验证我们之前做过的一些内容,然后来深入的让面试官感觉到你解决问题的能力是OK的。那我们对应的问题假设是,如果说我现在遇到了一个线上的系统突然崩溃,用户间歇性的没有办法登录到我的电商平台去做交易了,那这个时候我在N多久之前碰到过这样的问题,那我可以跟面试官详细的阐述一下我是如何解决的。首先当产线上遇到问题的时候,我需要有快速定位问题的能力,首先我们因为收到的一个用户的表现是无法登录交易,那因此我去排查了一下我无法交易的接口监控是不是有报错。

我们来对解决问题的能力尝试着举一个例子,那面试官在面试的过程当中,我会一味的去问你,你对应的解决问题的能力如何,而是会提一个场景的case,或者说直接问过往的项目当中有什么解决问题的一个非常亮点的经历吗?那这个时候你就要尝试着用我们刚才所说的这些思路去尝试着解决,举一下你历史上解决过一些问题的一个框架性的方法。

这就是我们当时现在可以来一起举一个例子读,对应的问题是我在之前的项目当中遇到过一个线上系统突然崩溃的一个问题,那个时候的表象是用户间歇性的无法做登录交易,那首先我们需要去快速的定位产线上的一个问题,由于当时的用户反馈是说我们没有办法去做交易了,而且是间歇性的。因此上来就直接排查了一下当时无法交易的接口的一个监控报错,发现的确整个的一个接口是处于一个报错的状态,内部错误信息是获取token异常,那由于我们获取token是需要走redis server做token的一个redis get的一个读操作,通过错误的一个日志和监控。查询到了当时的具体的错误是redis client无法获取redis server的一个链接,自然没有办法读取到Lisen的一个数据。然后我们和运维同学一起排查了我们当时使用的redis cluster server,某一台单机的一个CPU被打满了。

整个单机是处于一个故障的状态,由于并不是整个的一个radiusclassserver的一个整体集群的挂掉,所以说有的用户是可以交易的,而有的用户是不能交易的,那因此我们当时就可以简单的可以定位是这台redisclusterserver的一个单机的故障,然后我们当时关注到在这个racecastserver的这个单机上。同一个时间有大量的K做了一个写入的操作,我们排查下来是发现写入的接口登录的一个请求非常的巨大,
就导致不停的有大量的用户做对应的登录,导致这个toke nkey的一个写入操作变得非常的大,导致了整个的CPU被打满,那我们当时为了快速的止血产线上的一个情况。并没有深入的去排查为什么会有大量的登录请求过来,而是尝试快速的去重启了一下这台server,让客户端经历重连机制间歇性的故障得以恢复,那这个是属于快速定位阶段。然后我们需要去深入的去分析,为什么我们的一个登录接口的请求量会突然变得那么大

我们经过一些安全风控分析发现,当时巨大的登录请求被恶意的登陆接口刷了,肯主要是刷交易量,那主要的表现形式是同一个IP同一时间发起了大量的一个登录请求。这显然不是人可以操作得了的,因此被定义为是被恶意的刷token了,然后我们就开始做了一个异常流量的处理,我们在网络层面封杀掉了这样的一些同一时间发起大量请求的一些客户端的IP,至此故障得以完全的一个恢复。那在这个期间,整个快速定位问题通过重启的话,是间歇性的解决了对应的问题,而只有等把网络层的一个恶意刷的IP完全封杀之后,故障完全恢复。但是真的我们通过封IP就可以完完全全解决这样的一个防刷的一个问题嘛,那肯定是不行的。于是乎,在问题得以解决之后,我们尝试做一些复盘,是需要去做一些问题解决方案的一个取舍。首先我们认定我们在整个的一个系统是需要具备可以防刷的一个能力的。
怎么去具备这个防刷能力呢?我们就将方案定位在登录的一个token下发能力的一个限制上面,我们需要对同一时间产生大量对应登录IP下发的这样的一个登录token下发的这样一个IP进行封杀,但是这套方案可能会引入误伤,由于。net这样的特性,很多企业内部对外的一个出口IP都是同样的。那因此这样的一套方案的话,可能会误伤许多企业内网的一些同学,那于是乎我们最终没有采取这样的一套封杀IP的方案,而是可以使用验证码机制,也就是同样的一个IP在给定的一个时间段内发起太多次这样的一个登录的请求,我们需要去使用弹出一个验证码,但是这样的验证码的机制某些程度上面也会影响正常用户的体验。那因此对同一个IP跳验证码还是跳封杀,本质上来说是有一个预只需要去尝试做控制的。我们可以优先比如说在同一个IP1分钟内同时发起1000次登录的请求,那我们可以跳一个验证码来验证用户的一个操作是否合理,然后如果说在一分钟内发起了10万次这样的一个请求,

那显然是不合理的,我们对这个IP进行智能封杀,那后期的话,我们也可以考虑更多的一些安全风控的一个策略。来帮助我们找到风险的一个接入号。那以上这些就是我们举例的解决问题能力的case。

3 团队协作能力

首先我们还是要有一个明确的清晰的定义,主要整个的团队协作不同于我们历史上面所讲的一些,比如说开发链条的时候,你需要积极的参与以及积极的定位自己的问题,我们更多的抽象成了三种模式,首先第一个你的协作模式是否OK,第二个你的冲突解决的能力是否OK,第三个你主导项目的能力是否OK。以上三个都能够做的很好,你才能教你具备了一个完整的一个团队协作的好的能力。首先我们来看一下协作模式。

在整个的一个互联网大厂过程当中,我们由于微服务架构引入的一个特性,大家各司其职,因此我们在协作模式上面也需要得以升级,因为有可能跟你对接的并不一定仅仅只是你的上下游,而是会关联很多很多的人,因此我们在写作模式上面主要会分为这样的三种模式。

3.1 第一种模式:润滑剂模式

我把它定义为润滑剂模式,什么是润滑剂模式呢?就相当于是说在你整个的写作过程当中,你这个人是非常的nice,你是一个正面向上的人,并且无论是否是你的问题,你都乐于正面向上的去对对方做互帮互助,即便是对方做错了,你也不会去牵着别人。这种样子的一个润滑剂模式的一个合作态度,往往在企业内部会被定义为老好人类型。

并不一定否认,老好人类型本质上来说也不算是一个特别差的一个特质,但是在整个的一个互联网企业的一个运作过程当中,这样的一个润滑剂模式并不一定被所有的公司所认可。那也就是说,如果说你采取了润滑剂模式去做事情的话,许多整个团队内部的一些问题,或者协作上的一些问题不容易被高层关注。因为你做了太多本不应该属于你职责范畴内的一些事情,并且你因为是一个老好人的特性,很多人都有可能将对应的不应该属于你的工作范畴内的一些事情强压给你,

3.2 第二种模式:全责模式

第二种模式,也就是全责模式。就像微服务架构体系一样,我们在写作的时候需要去明确对应大家的一个边界,我们需要做一些大公无私的问题,就是你的问题是我的问题才是我的问题。在这样的一个协作模式下,整个的一个企业的流水线会变成一个规章制度下的一个冷冰冰的机器。在这样的一个合作模式下面,我们对应的整个的一个合作双方的一个关系,也虽然说是比较紧密,是比较配合的,但是本质上来说,如果说出了问题,就会采取互相推脱的方式,这也是近年来许多互联网大厂内部的一个内卷的一个主要原因。那因此我在这边详细推荐大家,如果说在面试的过程当中,我们需要采取混合的模式,也就是说你可以跟你的面试官去介绍你的一个协作模式上面,你期望的一个比较好的协作模式。首先我们每一个系统也好,或者每一个人也好,都需要有自己的一个明确的一个职责和边界,但是在合作模式上面,我们却可以不用太过于强调这个职责和凭借,我们仍然需要以正面向上,非常包容的一个态度去接受大家的一些问题,然后可以适当的去做对应的一个提点和提醒,但是我们的整个的一个合作态度还是正面向上的。

这个就是我主推的一个混合模式的一个协作模式的方法。

我们一般来说,我们遇到冲突都需要一个积极的一个态度去解决,我们在明确职责范畴的一个对应的一个框架的前提下,互相体谅,共同改进、进步。我们面试官经常会问,如果说你遇到了一个不顺心的事情,或者遇到了一些白的case,你会不会和别人吵架,那首先我们要回答我们面试官的是说,首先我们需要有一个明确的职责边界定义对应的这个问题到底是属于哪一方的。无论这个问题定下来是属于哪一方,只要明确的职责边界,我们都需要一个体谅、包容的态度去帮助对方去解决这个问题,而不是让冲突任意的一个升级,甚至于演化到大打出手的这样一个局面,最后也是非常重要的,我们除了营造一些良好的合作氛围之外。怎么叫你是一个具备很好的团队协作能力的一个人呢?那我们刚才所讲的协作模式也好,还有就是冲突解决也好,本质上来说你和那个人是一个平行的关系,但是我们现在企业大厂当中更看重的是你是否有主导项目这样的一个能力。主导项目的能力本质上来说也会被划分为团队协作能力的一个关键。因为我们在大厂内部需要有许多串联流程这样的一个人,比如说架构师需要去串联整个微服务系统的一个系统架构,我或者说我们的项目经理需要去对整个项目负责。在大公司内部非常赞成或者愿意培养一些能够具备主导项目这样的能力的人,因为他本身是技术出身,可有架构设计的能力和经验,而且他又能够在团队的一个协调过程当中起到非常好的作用,那因此主管也非常乐于去提拔曾经主导过项目这样的一个人。你如何去主导你的项目呢?首先我们这样的有一个虚拟的项目团队,共同为了某一个目标去完成这样一个项目,因此我们在团队协作的过程当中,首先是需要去明确我们的这个目标,我们的这个项目的交付时间点是什么样的,什么样的交付质量才是OK的,什么时候去做交付。

然后第二个,我们要有明确的一个职责分工,A做什么,B做什么,都体现在架构设计和细节设计的过程当中,我们都各司其职的知道对方能提供给我什么样的能力,我能提供给对方什么样的能力,以一种背靠背的方式去做合作。然后你作为主导项目的人,你需要有一些过程管理和结果导向,我们可以追寻对应的过程,通过晨会或者日会这样的一个方式去追过程,并且在最终拿到一些项目关键结果的一个结果内容。最后我们需要组织大家去做一些复盘改进,帮助我们在接下来的项目的过程当中能够做到更好。
这个就是我们主导项目第一个能力。总结一下,做为一个团队一员,我们如何来证明自己具备团队协作的一个能力?首先我们要明确我们协作模式是处于职责明确边界,但是整个就处于积极向上的做杰作,那我们在冲突解决的时候,要在明确边界的一个框架下面去做明确的职责划分,并且以一些乐观向上的良好的心态去解决我们的一个冲突。那最后如果说你要能够得到充足的成长,你需要有这样的一些能力和机会去主导你的项目。

4 自我驱动能力

我们首先来定义一下什么是好的自我驱动能力,我们面试者通常觉得自我驱动能力就是一个自我学习的能力,也就是说我平时看什么样的书,学了什么样的东西,我的技术提升了怎么样,毋庸置疑这是一个最基本的条件,那我在这边因此将主动学习作为了第一点,但是除了主动学习之外,我们还需要有积极承担和自我迭代的一个能力。那首先我们还是来先看一下主动学习,主要是面试官会问你平时在学什么东西吗?这种样子其实就是在问你是否有一个主动学习的能力。

比如说我可以简单的说,我最近在看书,zooKeeper相关的一些源代码和对应的官方文档,并且尝试下载玩了一下,我有什么收获是不是可以分享一下,这样的话面试官就可以觉得你是一个主动好学的人,自然你的潜力就会被定义为高。首先,主动学习主要包括了告诉面试官你最近主动学习了什么,有什么样的收获,是否可以简单的分享一下。

然后我们来看一下第二个,也就是积极承担。我们刚才所讲到在做团队协作模式的时候,需要去明确整个团队协作的一个边界,但是往往在高速发展的业务的一些互联网的大厂内,边界的一个建立的一个制度往往是跟不上业务的发展的,因为我们在快速业务发展的过程当中,往往会产生许多的一些工作量,这个工作量在边界模糊的一个场景下面,往往是a做,B做都可以。这个时候对于模糊的一个边界地带,我们怎么去解决呢?

现在在互联网的大厂内,许多的boss更希望关注的是在团队内部,你需要去在模糊的边界能够有积极承担责任的一个能力和特质,并且可以拿到结果。什么意思呢?在团队内部a做也可以,B做也可以,它是一个模糊地带,如果说你在你的面试官或者你的老板面前可以主动站出来,去多承担一些对应的任务,并且能够将对应的这些任务转化为你的一个工作的成果,那自然你在未来被授予机会的一个可能就更大,你在面试官眼中,你的一个加分项也就更突出,那因此一个自我驱动的一个能力,本质上来说可以分解为你在模糊边界地带可以积极的去承担一些额外的一个责任。

最后我们有一个叫自我迭代的能力,我们经常在互联网大厂当中被定一个叫复盘,比如说我们在产业上发现了一些问题,最后我们需要一个复盘来定责,定期复盘往往会被人认为是一个承担责任并且做惩罚这样的一个代名词。其实我在这边说的一个复盘并不是指的是这样的一个产生问题,故障的一个复盘,而是说我是不是在每次的一个工作任务结束之后,无论做得好还是不好,都需要经历一些自我迭代的复盘。我再比如说我做了某一个a系统的一个设计工作,并且落地之后发现了一些什么样的问题,那我经历过一些复盘,写了一些文档,并且在组内分享给了大家,防止大家做踩坑。并且对我自己的一个能力也有了一些质的提升。因此,整个的一个自我迭代的一个复盘能力,往往也是会被定义为自我驱动能力的一部分。

以上是关于如何成为一个优秀的程序员?的主要内容,如果未能解决你的问题,请参考以下文章

[转]如何成为优秀的程序员?

如何成为一个优秀的前端工程师?

如何成为优秀的程序员

如何成为一名优秀的程序员?

反思如何成为一个优秀的程序员

做到这些,你也能成为一名优秀的程序员