逃离天坑之后——谈谈技术路线该怎么走

作者:一位脱坑十年的长者

在象棋的江湖残局中,有一个名词叫做“摘帽”,用来表示先手一方破解了后手方的一步攻杀,局势趋于一种表面上的缓和。摘帽之后先手方虽然没有燃眉之急,但如果残局功力不足,仍然会一招不慎满盘皆输。

脱坑如摘帽。脱坑只是真正职业生涯的开始,未来的发展仍然充满着不确定性。我写这篇短文主要目的是帮助已经脱坑的朋友了解以下技术路线的前景——如果能帮助喜欢做技术的坚定信心,不喜欢做技术的尽早找到合适自己的发展路线,转转PM和EM,那我大概也算是胜发半篇nature了。

一、自学与科班

知乎上最近有个问题时不时就跳到我的时间线上对我大肆嘲讽:自学编程和计算机科班出身的差别在哪?-知乎

答案区基本已经变成了转行人士和科班人士的混战,看看热闹就好。

我希望非科班出身的同学要正视这个问题——和自己比,科班出身永远比非科班出身好;和别人比,非科班出身不能成为水平不行的借口。

科班出身的人用这个来bully你,是ta的不成熟。但是我们作为一个技术人员,不会,可以学;没接触过,可以研究;不懂,可以请教。借用公孙先生的一个句式:真正的猛士,敢于直面自己的不行。个人感受,人在放低姿态之后比较能够轻松愉快地学习,如果一直打肿脸充胖子,公孙先生自己就是个挺好的榜样。

扎实地掌握一个语言、几个库、几个框架,都是基础,这些是作为合格程序员的基础硬实力,同时也是最可替代的能力。「程序员是碗青春饭」这句话,并不是完全没有道理的——如果认为程序员要做的就是不停学新的框架然后用它们开发程序,那么三十五岁被退休大概也不能全部怪罪资本邪恶。

如果坚持走技术道路,你一定要逐渐习得进入下一个阶段的能力:

二、在组件(component)层面独立解决较为复杂技术问题的能力

系统的一个功能,一个接口,或者一个简单的微服务,我们大体上称为一个组件。

在这个层面上,需求的定义相对明确,然而往往技术细节并不明朗,需要工程师自己去研究解决方案,并且在必要的时候和其他服务、库或系统进行集成。

在接触软件开发的最初几年,面对这样的需求束手无策,或者需要很多老人的帮助和指导,是很正常的事情。但是随着知识和解决问题经验的积累,你要学会:

1.面对定义相对良好的有一定规模的需求如何进行分解;

2.如何利用现存资源降低造轮子的成本;

3.如果重造轮子不可避免:

a.对于高科技轮子在何处获取指导和资源

b.实现过程中如何保证质量和**可修改性** (以后单独讲)

4.开始关心系统的运维特性;

5.开始关心系统的非功能特性;

99.开始清楚地认识到自己是否适合一直走技术路线。

这个阶段是程序员会接触到很多细节的一个阶段,也是从初级程序员向中级程序员转变的一个重要阶段。如果能够survive这个阶段,那么基本上可以被称为一个合格的程序员了。

运行在这个层面的程序员,在面对问题时大概是这样工作的:

1.做出恰当的分解和估计;

2.分析各种技术的优劣,理解需求并且能够和PM、其他技术人员讨论trade off,并在高级程序员的合作下选用合适的技术;

3.实现中仍然需要较好的文档以及技术支持,较快地独立完成大部分开发工作,偶尔需要高级开发人员指导;

4.产品较为健壮,运维压力不大,并且能够适应需求的变化。

然而到了这个层次我们就"安全"了吗?我认为勤奋的程序员或早或晚都会到达这个程度,而这个世界上从来不缺少勤奋的程序员。所以在此之上我们还要进一步发展自己的技术实力。

很多人都感觉到接下来要发展架构能力,然而其积累并非一朝一夕可以完成,在那之前,我们还有两步要走:

三、磨练阅读代码的能力

阅读代码,不是跟风式的一上来就去读Hadoop,Cassandra等大型开源项目——除非是天选之人,否则这个阶段也不太能看得懂——而是说在工作中能够做到以下几点:

1.在文档不完整、不精确或者不正确的情况下,通过阅读代码库来对某个系统得到正确完整的理解;

2.在接手新的项目时能够快速找出重点主干,在代码为主,文档为辅的帮助下理解其实现逻辑及风格/范式(paradigm);

3.在缺少他人解说的情况下(如原作者已经离职),能够大致还原当初的开发场景,对一些看起笨拙的写法能够做出恰当的解释,在重构中能够区分可以大刀阔斧修改的和需要小心谨慎修改的部分;

4.在debug过程中,较少依赖debugger,较多通过阅读代码来定位问题。

代码是程序行为的source of truth(说还有配置的杠精先一边凉快去),文档因为代码迭代太快,或者因为程序员太懒,往往无法起到精确指导实践的作用。而阅读代码得到的知识,则是最具时效性的和逻辑上正确的知识。

这种能力是长期大量积累代码调试和阅读经验之后,最终获得的一种思维方式(大概可以称为人肉debugger吧)。其实这种能力人人都有,只是强弱悬殊,而且在水平达到一定阈值之前作用并不明显。

在获得了这种能力之后,一般的不明真相的小朋友看你工作,经常会觉得不可思议,比如说大家还在研究这个X系统的集成文档,你阴搓搓已经把prototype写好;你问了隔壁组同事一个问题,他说不明白,然后你很无奈去看了几分钟代码,然后说啊我知道了原来是这么回事……

但是这种能力也没什么可夸耀的,我认识的天资较好的朋友,科班出身,毕业一两年读代码就已经炉火纯青。而我,从大三转行开始花了大概七年时间才达到他当年的水平。

稍微偏个题。如果看到这里你觉得这不是你要的未来,那么我强烈建议探索一下产品和管理方向——纯技术有人喜欢有人不喜欢再正常不过,程序员转PM和EM也是正常操作。

在能够阅读大型代码库之后,很自然的,我们要利用这种能力来进一步强化自己的技术能力——对很多人来说阅读代码能力的获得是自然而然的,如果不能再构筑一道壁垒,我们就只是和野蛮生长的聪明人差不多罢了。

我的一个建议是阅读著名开源项目。个人对分布式系统有一点热爱,可以保证Cassandra,HDFS,YARN,Redis和Mongo都是值得一读的代码。有朋友说Chromium是非常优秀的客户端代码,我没有亲见,但是鉴于此人十分靠谱,在这里我也做一个推荐。关于读开源代码的问题在这里不展开讲了,后面有机会单独说说体会吧。

四、知识的T字形积累

我们在软件行业里面毕竟是后来者,除了实践中的学习以外,重新补充理论知识是必不可少的。毕竟真的猛士是吧,得承认自己不行。

离散,数据结构算法,操作系统,编译原理,数据库,网络之类的这些本科基础课程就不说了,即使不能达到本科扎扎实实学一遍的水平,跟着在线公开课撸一遍总是没错的,长期来看很多知识在日常的开发中都会时不时地出现一下。

工程上,在自己专精的领域周围,要有足够的外延。如果是做后端,那么对于现在主流的各种工具如数据库,流服务,存储,网络,负载均衡,工作流等等都要有大体的了解,明白它们的应用场景和局限性。AWS其实是一个特别好的后端技术索引,如果能把里面的各种服务都拿出来了解一下,再稍微研究一下对应的开源技术,知识面上就已经说得过去了。新手要注意的是不要拿个锤子就看什么都像钉子,各种技术有其适用性和限制,choose your weapon wisely。

扩展知识的广度一则可以扩展工具箱,在设计系统的过程中少走弯路,二则在对比各种不同系统的特性时,可以互相印证,掌握一些一般性的规律。

而另一方面技术深度的重要性不用多说。要提醒的是,技术的深度不仅仅是比别人多**知道**几个技术细节,比如ThreadPoolExecutor的默认策略有几种,C++的虚基类内存如何布局;也不仅仅是背了几章标准,读了几篇RFC——深度是从宏观的需求、应用场景,到架构和实现细节的全面掌握。具体深入学习的手段无外乎读好书,读优质paper,读代码,理解架构,实践——有条件的话,可以为开源项目做一些贡献。

在一点深入,同时在周边兼顾展开,这就是所谓的T字形知识结构。

在此基础之上,有意识地锻炼自己在相应领域的架构能力,假以时日,能不能成大器不好说,成个技术专家大概问题不大。

五、理解架构过程,尝试进行架构工作

我们日常做的设计和架构工作其实并不复杂,重点还是从需求出发,定义use case,转化/分解成可行的软件系统及其的设计,找到合适的工具和结构/算法来解决问题。

理解业务(business logic)、理解需求方没有说出来的潜台词,和所掌握的工具挂钩、正确衡量软件系统所需的特性、合理分解子系统,是做软件架构的一些基本能力。

发展这方面能力主要就是多观摩多思考,学习身边的高级工程师是怎么分解和转化问题的,主动积极参与到关于软件设计的会议和讨论中,对比自己和大牛思路上的差异,缺什么补什么。

更高级的工程师会以组织为整体考虑架构问题,和做具体架构的工程师讨论调整解决方案,令其符合整个组织的技术图景,个人感受,这些principal工程师务虚的事情会相对较多。既然是讨论纯技术发展,我们就到此为止吧。

----

希望这篇短文回答了一些朋友对于未来的疑惑,也回应了一些对技术人员职业发展的不实传言。没有对某些文章逐条地进行回应,是因为一旦开始争论,就容易陷入细节而无法关注宏观的大方向——不过也希望我讲的不是大而无用的废话。

时间所限,只能写到这个长度,以后有机会我会挑几个点展开来讲。

最后,本人脱坑十年整,弯曲某司Senior Engineer,先匿了。

没有更多推荐了,返回首页