{T}

选择比努力更重要

0. 引言

面对那么多软件技术,总有一种"学不过来"的感觉,为此感到焦虑和担忧——尤其是对于全栈工程师而言,这个话题更是被放大了。颇为遗憾的是,不少相当有经验的 Web 全栈开发程序员,依然走在埋头苦干、不断堆积知识、单纯靠量取胜的路上。但学习是需要选择的,选择比努力更重要

1. 两个小故事

1.1 微软测试团队改革

陆奇是程序员从技术做起、进而翻身的典范。最初他入职雅虎时只是一个普通工程师,十多年后以执行副总裁的身份牵头打造了 Bing 搜索,还完成了几项意义深远的改革,其中一项就是合并开发和测试两个原本独立的部门,大幅裁剪专职测试人员,让工程师做更多的事。

一些擅长使用内部测试工具的工程师慢慢丢掉了工作,原因很简单:他们更多只是熟练工,缺乏技术上的竞争力。这听起来似乎只是微软内部组织架构变动和工具、技术栈封闭的锅,但其实合并开发和测试团队,对于许多软件公司特别是互联网公司来说,是一个基本不需要讨论的事情。除了一些面向互联网用户、交互较为复杂的团队还配有专职测试(也常外包给合同工),绝大多数团队都变成了软件工程师一肩挑的局面。对于大型互联网企业来说,工程师的全面性越来越强,是一个不可辩驳的趋势。

1.2 五轮面试

第二个故事发生在一场五轮面试之后的讨论会上,应聘者是一位有着超过 15 年 Web 开发经验的资深工程师。五个面试官产生了巨大的分歧:

  1. 招聘经理反馈非常正面:经验丰富、谈吐得当,leadership 层面没有问题;
  2. 技术负责人重点考察项目经验和系统设计,反馈也颇为不错:经验丰富,能从很多角度分析和思考问题;
  3. 其余三轮面试官反映大相径庭,主要问题出在白板代码部分:代码生疏、书写缺乏条理,有一轮没有写完代码,写完的两轮也是 bug 满地、问题频出。

最后争论之后达成一致:可以通过,但只能给一个比预期职位级别低一级的 offer。作为技术岗位的工程师,编码能力是硬指标。只不过私下里讨论,应聘者很可能有足够的编码技巧,只是一段时间没有写代码了,确实有些可惜。

从这两个故事中,可以提炼出工程师技术学习需要遵循的两条主要思路:

  • 技术是分级的:分短命和长寿,也分表面和本质。要学习各种技术,但要把足够精力放到长寿的技术以及技术本质上;
  • 基础知识和能力的训练需要长期坚持:无论是在工作中,还是工作以外。

2. 技术的分级

都听过"技术无贵贱"的说法,但这并不代表要"无区别"地学习技术。工程师最重要的就是"工程能力"——应用工程化的思想和技术去解决实际问题的能力。工程能力可以粗略分成四个级别,它们都必不可少:

工程能力分级

  1. 软能力:如沟通能力、学习能力和抽象能力;
  2. 模式和思想:如分而治之的思想、模块化的思维、客户端/服务端模式。这部分相当稳定,可能随着技术革新,一些以往不受重视的模式或思想被列为重点;
  3. 语言和平台:如 Java 语言、JVM 平台。这部分变化非常大,有的语言已经几十年,有的几年热度之后就消退了;
  4. 框架和库:差异非常大,总体来说基本是最短命的。如果要花费大量时间和心血去深究某一个框架和库,你会希望它要么相当有代表性和典型意义,要么有足够长远的未来。

应该明确的一点是:把几乎全部精力都投入到分级的右端——把大量时间花在记忆一个接一个的框架和库上,妄图靠数量取胜——不可取。有时更可悲的是,就连生硬的记忆本身也不讨好:有些还都是公司内部的框架和库,离开公司就一文不值了。

展开讲几个具体技术学习中的典型误区,本质上都属于不恰当的"选择":

误区一:过于关注配置使用,忽略原理和场景分析。 这最容易出现在迈入职场的程序员身上。老板命令下来,心里慌得很,就想着怎么把问题搞定。比如怎样配置整合 SSH(Struts、Spring 和 Hibernate)这类知识迷局:通过搜索、查文档、试错,花很长时间终于搞定问题,完成任务后却紧锣密鼓地接下一个任务。对刚才用到的技术付出了那么多,却只收获了一个小小的迷局的解,投入产出比低,而且人是很健忘的,这些具体配置只要不用很快就会忘掉,下次遇到类似问题又要重复这一行为。

误区二:过于关注编程语言的语法和语言技巧,忽略语言思考和书写时的思维模式。 比如 JavaScript 语言里有很多坑,有些是语言本身不良设计造成的,知道当然好,但不要因此沾沾自喜。对于写惯了 C++、Java 等后端静态语言的程序员来说,JavaScript 的异步编程、函数成为一等公民等颠覆以往思维模式的特性,才是学习这门新语言收获颇丰的地方。换言之,要写 JavaScript,就要写真正的 JavaScript——而不是写 Java,再按字面翻译成 JavaScript。

误区三:过于关注具体实现逻辑,忽略了设计的思考和权衡。 很多程序员热衷于研究源码,看完一个库再看下一个,甚至以读过源码的数量为荣。阅读源码当然是好事,但请不要认为研究源码的目的只是"知道怎么实现"。时间精力有限,读源码尤其耗时,既然要读就要读得有所收获:抓住主干,思考里面的设计思路(所谓"代码骨干"),忽略次要的边边角角。

误区四:直接学习模式和思想,脱离具体实践。 抽象的理论和概念,在没有实践的基础上很难真正"消化吸收"。最好的方法是动手做一做,如果时间有限,至少也要阅读和了解它们都被哪些具体技术以怎样的方式实现了。

3. 基础知识和能力

即便在同一级别的技术上,学习也应该有轻重缓急。项目中需要的技术当然要学,但心里需要清楚那些所谓的"基础"。很遗憾的是,有很多"基础"光靠工作中学很难有较大进步——比方说算法和数据结构。

数据结构、算法、网络等等都是基础知识,如果工作中的强化不够,工作以外的学习和训练还是需要的。如果你的基础不够扎实,特别是"非科班"出身,它就更加重要。比较好的一点是,这些相对于"设计能力""问题解决能力"等来说,还是要好学很多。

除了基础知识,还有基础能力,最重要的就是编程能力。值得庆幸的是大部分程序员都会在工作中有足够的编程时间,因此只要专注、带着思考去写代码,认真对待代码评审,编程能力是会随着经验的增加而逐渐提升的。

4. 小结

选择比努力更重要:技术是分级的,要把足够精力放在长寿的技术和技术本质上;基础知识和能力的训练需要长期坚持。同时,要警惕四个学习误区——只重配置不重原理、只重语法不重思维、只重实现不重设计、脱离实践学思想。对全栈工程师来说,技术广度固然重要,但深度与选择的能力,才是决定职业发展高度的关键。

至此,全栈工程模块的全部内容已经讲完。从 MVC 架构、网络协议与 Web 接口、数据持久化,到全栈团队的角色构成与个人成长路径,希望这些内容能帮助你在全栈工程师的道路上走得更远。