程序员生存定律--成长路上常见的坑
程序员生存定律这系列的目录在这里:程序员生存定律--目录
喜欢从头瞄的,可以移步。
------------------------------------------------------------------------------
前面讲到了程序员成为高手需要有一张地图,借助这样一张地图,程序员可以尝试成为架构师、Guru或者纯管理者。但这条路总是不会那么顺畅。
升级练功流的网文中总会给修仙的主人公设置下几大关卡,比如:金丹难成、元神难成、成了元神后还有天人五衰等等。没有这些关口,情节很难推动,所以仙侠类的网文几乎无一例外依赖于这类设定。这一传统甚至可以追溯到《西游记》和《封神演义》。
拿这个来对照程序员的增值道路,就会猛地发现,升级练功流也不完全是扯淡。不管走那条道路,程序员的修炼路上同样的也有三灾九难,要想成就高手,还是得一个个跨过去才行。如果一个程序员达到一定高度后再回头观望,那就会发现自己的同学、曾经的同事总是会因为这样那样的原因倒下去。这并不是一个简单的天道酬勤就可以敷衍的行当,下面就让我们来具体看看,究竟增值过程中可能遇到那些陷阱,掉到坑里又需要付出多大代价才爬的出来。
1. 学习失去焦点
软件行业里有几个经典的题目,每过一段时间就会被翻出来PK一下,比如关于编程语言优劣的比较等。其中一个经典题目是软件和数学的关系。
从结果来看,一派人认为数学是软件的基础,而另一派人认为数学和软件没什么太大关系,除非是在某几个特定领域里。如果你用心观察过这事情,你就会发现这事情特别有意思。
比如说:
2011年,CSDN转了一篇,叫:“数学是成就卓越开发人员的必备技能”的文章,在文末作者说:
那么,数学对所有事都有利么?这事情很难说,我对我现在的处境十分满意,或许你也如此,但这都和潜能有关系。如果你是协作世界的一名开发人员,你真的不需要数学。如果你乐于你的整个职业生涯是这样的:在工作时间中做企业CRUD应用,或在闲暇时间滑翔跳伞或极限水上滑板(或其他各种时髦的极客运动),也分配较多时间在Spring、Hibernate、Visual Studio或其它东西上。那些特殊的职位并没有真正限制你的潜力,你能变得极具价值,甚至可深入追求。但是如果你想为多样化的职业生涯而奋斗,想要有能力尝试几乎所有涉及代码的事,从信息检索到Linux内核。总之,如果你想成为一个开发人员、程序员和计算机科学家的完美组合,你必须确保你的数学技能达到标准。长话短说,如果你在数学方面有一定天赋,那在软件开发领域中所有的大门都是向你敞开的,如果没有,那你就安安心心地做CRUD型工作吧!
总的来看,这个作者认为数学很关键,得学。
而在2012年CSDN又转了篇文章,叫:编程需要知道多少数学知识?在文章里作者说:
数学和编程有一种容易让人误解的联系。许多人认为在开始学习编程之前必须对数学很在行或者数学分数很高。但一个人为了编程的话,需要学习多少数学呢?
实际上不需要很多。这篇文章中我会深入探讨编程中所需要的数学知识。你可能已经都知道了。
对于基本的编程,你需要知道下面的:
加减乘除—实际上,电脑会帮你作加减乘除运算。你仅需要知道什么时候运用它们。
模运算—模运算是用来计算余数,它的符号通常用%百分号来表示。所以23除以7等于3,余数是2。23 mod 7 = 2。
判断是奇数还是偶数的模运算—如果你想知道一个数是奇数还是偶数,用它mod 2来作模运算。如果结果是0,它就是偶数。如果结果是1,就是奇数。23 mod 2等于1,所以23是奇数,24 mod 2等于0,24是偶数。
对一个数作百分数运算,就是用这个数来乘以一个百分数。譬如你要得到279的54%,就是用0.54*279。这就意味着为什么1.0等于100%,0.0等于0%。
知道负数是什么。负数乘以负数等于正数。负数乘以正数等于负数。就这么简单。
知道迪卡尔坐标系统。在编程中,(0,0)代表屏幕左上角,Y坐标的正轴往下。
知道勾股定律,因为它是用来计算笛卡尔坐标中两点之间的距离的。勾股定律a^2+^2=c^2。(x1,y1)和(x2,y2)两点之间的距离等于((x1–x2)^2+(y1–y2)^2)。
知道十进制、二进制、十六进制。十进制就是我们通常用的十个数:0-9。通常认为这个十进制系统是人类发明的,因为我们有十个手指。
总的来看,这个作者认为数学不太关键,大多时候可以不学。
你如果持续关注这事儿,各种极端对立的观点绝对会吵爆你的头。但这事情其实不可能有结论,因为被对立起来的两极都是太大的概念。
比如说:如果把软件开发缩减为应用软件的开发,那争议性就会降低很多。
这里的关键问题是,假如一个人的目标是应用软件开发,却花了10年来学习数学,接下来在实际应用程序开发过程中,每天面对的是UI布局、IDE使用、圈复杂度控制、面向对象使用、设计模式的使用和类库的使用这类问题,那么这个人就会发现数学其实没啥用,他等价于因为失去焦点而失去了10年。
这里想表明的是,一旦误读了知识与目的间的因果关系,那么学习就会失去焦点,进而造成负效应,毕竟相对于人的可承受负荷而言,这个世界上的知识不是太少,而是太多。
一般的认识是只要学习就必然有所得,所以对人生的影响一定的是正面的。但实际上这个想法是偏颇的,尤其是在软件行业里。
在软件行业中,这种风险之所以异常突出,就在于前面提到过的软件的两个特质:更迭速度快和子领域众多。这两个因素导致软件相关的知识是爆炸性增长。
而避免“失去焦点”这一陷阱的第一关键则是分类:对软件开发进行分类,对软件所关联的知识也进行分类,形成自己的大局观和整体视图。
前文曾经提过集中对知识进行分类,对软件进行分类的方法,这里再补充一个对绕过这一陷阱有帮助的分类方法,它来自《软件成本估算:COCOMOII模型方法》这本书。
书里面把软件分成了下面几个类别:
终端用户编程(一般的应用程序) |
||
应用程序生成器(开发工具等) |
应用组装 |
系统集成 |
基础结构(OS,DB等) |
在进行分类的同时,书里还给出了一组数据,即95%的人从事的是终端用户编程。
这个分类的意义在于,通过它我们可以认识到每一类别背后隐含的知识需求其实不一样,程序员则要根据自己的目的设定焦点。再来看一个具体的例子:
算法领域中,最经典的书籍恐怕是Donald Knuth的《计算机程序设计艺术》。对此书的评价已经不止是高那么简单了,如:
这部多卷专著是公认的对经典计算机科学最权威的描述。几十年来,无论是学生、研究人员还是编程从业人员,本套书的前三卷都是他们学习编程理论、进行编程实践的宝贵资源。
这是一套集所有基础算法之大成的经典之作,当今软件开发人员所掌握的绝大多数计算机程序设计的知识都来源于此。
---Byte
那么是不是每个人都应该把这书读一读?这书的前三卷大致有2000页,上班的人都读通估计要1~2年这个样子。
至少在我来看,答案是否定的。具体情况要看你做的是那类软件,你人生的下一步在那里而定。
假设说一个人做的是终端用户编程(比如:财务类软件),并且目标也是在这个方向上继续深造,那么你读这书其实是在浪费时间。
这是因为在终端用户编程上,自己去写算法的机会非常的少,甚至可能没有。反倒是业务领域知识(会计知识)、OO、设计模式、甚至于估算这些知识都比研究算法更有价值。 既然如此,那么从务实的观点上看,为什么去学习不能在可见范围内创生价值的东西,而不是去学习立刻可以变现的东西。走极端的人会找出需要写算法的例子来反驳上述立论,但点不足以表征面,即使偶尔需要自己了解下算法,真就值得花那么多时间去学习么,为什么不尽可能借鉴现成的。
而在基础结构性的软件开发中,情形就不同,这时算法无疑是非常核心的东西。所以Google这类公司的面试中往往非常强调算法。
这里最关键的就是聚焦,聚焦的根本则是要在限定时间范围内创生价值。
从方法上讲,聚焦就是找到一个适合自己大小的区域,然后做深。才华横溢的不论,一般来讲,横向穿越和纵向穿越都不太行,除非已经基本穷尽当前的领域。纵向穿越是指从底层穿到上层(想想开发网络协议的和用网络协议的),横向穿越则指横跨太多的领域(想想从内核驱动跨越到信息管理软件)。
其实如果一个人真的拥有无限的时间资源,那么什么时间点学习什么就变得不太关键。但这是不可能的,同时一个人的学习时间远不像想的那么充沛。这点会在后面探讨。
在清楚自己的目标后,再配合前面提到的知识分类地图,那么避开这一陷阱的几率就大了很多。
2. 学习与实践相分离
喜欢看网文的很少有人会不知道起点,不过估计很少有人注意过起点给小说分类的标签。在网文小说里有很多个流派,其中一个叫做“扮猪吃虎”。这个流派的基本特征是很厉害的一个人要假装很菜,最后在关键时刻力挽狂澜。这个流派十分有人气,大概仅次于“升级练功”,而远高于“重生”、“转世”这类的流派。
网文是绝对的市场导向,所以这个现象可以从侧面说明很多人喜欢“扮猪吃虎”或者说潜意识里有着“扮猪吃虎”的情节。“扮猪吃虎”这事儿小说里看着很爽,但挪到现实里来很容易让人掉到学习陷阱里。更可怕的是,现实里有这种心思的人其实也还很多。
有时候会看到这样一种现象:很多人自学的东西和工作中用的东西完全没关系。比如:一边用着C#做Web开发,一边自己学习着C/C++做嵌入式。
这事并不一定不对,只能说非常危险,很可能会导致那样都没有高度。我们得承认当人生被错位的时候,往往只能这样来改变命运,这是没办法,也是正确的。但首先要认识到这样做是相当低效的,低效到一定程度后对的事情也并不一定有结果。
CSDN曾经做过一份薪酬统计(http://www.programmer.com.cn/5877/),这里面有三个与上述身在曹营心在汉现象有关联的结论:
一是73%的程序员对自己的薪资并不满意。
二是各个主流开发语言上的差异并没有想的那么大。虽然C#开发者中月收入小于5000元的比例最高,但5000~10000这个群体在主流开发语言上相差并不大。
三是平均来看,收入增长和工作年限正相关。当然认为到那个岁数工资自然就高了是很危险的。
对薪资不满意应该是程序员希望跨界的一个原动力,但收入和年限正相关,与语言非正相关却说明单纯从功利角度看跨界并不明智。因为假设一个人Java语言用过三年,C#用过三年,总的来看收入水平更可能处在三年的水平上,而不是六年的水平上。
软件是一种固化的思维,这就软件开发更多是一种实践而非是一种理论。软件开发内的很多领域,总体上看体现的是复杂而不是艰难,不论是前端开发还是驱动开发。
讲到到这里就有必要简单区分一下“复杂”和“艰难”。考试出题可以有两种方法:一是每道题都不是很难,但题量很大;一是题量很少,但每道很难。从结果来看,两类考试方法下,得高分都并不容易,但其难度的来源却并不相同,前者更多的体现为复杂,而后者却体现为艰难。
在软件行业里,除了一些专门的领域,比如图像算法等,软件开发则更类似于前者,所以经过培训后大部分人都可以做软件开发,进入门槛并不高。
解决艰难问题时,天分很重要;解决复杂问题时,练习很重要。所以软件开发的学习过程中,实践很重要,纯理论知识的权重较低,当然基本的算法复杂度还是要明白的。
这也就意味着脱离项目实践的学习投入产出比往往会差。比如说:编程中常见的多线程问题。如果单纯从学习的角度看,创建线程本身并不复杂,掌握各种线程同步方法(事件、信号灯、互斥量等)也并不复杂。写简单例子的时候,也很少会出错。但一旦落到具体的场景下,虽然多线程的本质没变,但没经验的人几乎一定会在涉及多线程的代码上导致一会儿出,一会儿不出的问题。
再比如说:你可能看了很多设计的书,但从来没有从头到尾写过什么程序,总是在既有代码上修修改改,或者只是完成几千行代码的小工具,那么你的设计知识是很难融汇贯通的,也还是无法很好的承担大系统的设计工作。
这点上有一个旁证,根据统计最多的Bug是由新手导致的。这从侧面说明,能做和能做好之间的鸿沟需要大量的实践来填平的。
在这样一种前提下,期望先选个工作,再自己学习,努力转行这样的想法是损失很大的。单纯从增值效能上看,解决这点很简单,除非必须放弃当前的工作领域,否则要以当前参加的项目为根基展开学习,这样才能比较好的调和学习和实践。
而除非一个工作领域过于偏狭,大多时候在编程语言(C#→C/C++)、不同领域间(图形处理→地理信息系统等)穿越损失可能更大。
至于如何在“博”与“专”间平衡,如何选中更适合自己的工作领域,将在后续章节里陆续谈到。
------------------------------------------------------------------------------
关于我自己的各种信息,在左边栏可找到,想了解下写这系列文章的人是不是骗子和大忽悠的可以瞄。
最后希望感兴趣的支持V众投,感觉上这应该是国内最靠谱的生活购物等的问答社区了吧,都是朋友给朋友做的答案,同时实行一人一号,一人一票制度,想找什么答案关注公众号:vzhongtou(左侧有二维码)就行了。