程序员生存定律--成长路上常见的坑


1.“博”与“专”上的迷失
 
假设说一个人的学习已经聚焦,并且学习的内容和自己实际参与的项目也相吻合,那么是不是就没有问题了?很不幸,答案仍然是否定的,在任何一个子领域里,仍然需要进一步去考虑“博”与“专”的均衡。
 
对于软件开发而言,设计是再常见不过,再简单不过的一个词了。可如果把视角拔高一点就会发现,单以设计而论仍然是一个不可穷尽的领域,我们可以快速扫描一下和设计相关的部分概念:
 
(1)面向对象分析与设计
(2) 结构化分析与设计
(3) 模型驱动开发
(4) 契约式编程
(5) 面向方面的开发
(6)基于组件的开发
(7)元编程
 
有些时候方法论也会和设计牵扯到一起:
(1)测试驱动开发
(2)敏捷软件开发
 
如果感觉这个还不够多,那可以去Wiki上查编程的范式(paradigms)这个条目,那里列了47种范式,每个都和设计多少有点关系。
 
上述这些还只是说了设计,如果横向展开,那么在特定领域中必然还会牵涉到框架的选用、辅助工具的使用等等。这也就意味着,从博的角度来看,即使是在设计这样一个看似狭小的领域中仍然是没边界的。
 
与此同时,把一个API研究的再透,也是低值人群,因为这种深入理解和单纯会用某个API相比,从创造价值的角度看,差别不大。
 
这也就意味着对于大多数软件开发人员而言,要去寻找广博与精专间的均衡点:既不能闭上眼睛,也不能就用显微镜来看世界。而这一均衡点的价值则可用反木桶原理来说明:木桶原理说的是桶里的水是由最短的一块板决定的,但考量人的价值时却是适用于反木桶原理,即人的价值往往由最长的一块板决定。
 
考虑博和专的问题不能离开产品开发进行考虑,前面曾经提到过,产品开发往往和公司的现金流绑定的更紧,能为现金流贡献力量的技术才是有价值的技术。而产品开发本身事实上对博和专的程度提出了最基本的要求,这种要求往往具有迭代的特质。为了形象的说明这一点,这里举一个通用的例子来进行一点说明:
 
在第一次跌代里,往往需要达到两个最基本的目标。第一个目标是可以为产品贡献自己力量,但代码质量普通。这个目标如果达不到,一个人会失去自己的存在价值。
 
这时候最少需要了解某种语言(比如:C++)、某个平台(比如:Windows)、某个IDE(比如:VisualStudio)和某些业务相关的知识(比如:打印体系)。这个范围可以尽可能圈的小点,但用到的则要学透。比如:不管接触到那个框架,都要去了解它的内存机制、线程机制、异常处理组件构建和国际化处理这些全局性的机制,而不能只是了解某个接口怎么用。
 
这并非是很高的要求,没有这些就变成了“靠运气编程”,写完程序后还要祈祷他能跑起来。了解这些之后就可以负担起部分开发工作,否则的话只能做旁观者,没法参与到实际工作中来。
 
第二个目标是把事情做好,并能负担些层次更高的工作。这时候要比较深入的了解面向对象、结构化方法、设计模式、理解设计原则,并能把它们用好。至少要能判定,这个程序写的好,那个程序写的不好,同时面对需求能把工作进行下去。
 
前两个目标是基础,一般来讲学校中基础打的越好,这个阶段越短。达成这两个基本目标之后就可以结合情境来做进一步的选择,可以认为这是博与专选择上的第二次迭代。当然这时候也要谨记不要和实践分开。
 
完成上述两个层次后,可以有两个方向可供选择:
(1)可以进一步考虑专的问题,比如在特定领域里把知识深化下去。做驱动就要理解操作系统的核心机制,做打印的就要了解页面描述语言等,但这个时候要适当警惕边际效应。
 
边际效应是说,你让一亩地从亩产500斤增加到1000斤可能只需要投入100块;让亩产从1000增加到1500可能就需要200块;让亩产从1500增加到2000则需要400块了。
 
一个典型的例子是对C++的学习,C++是公认的复杂,如果想做C++的律师,那么估计搞个10年可能够资格了,但问题是把时间都投在这个上,投入产出比可能不好。而停在那里合适则是个尺度问题,大致来讲是可以靠时间弥补的细节问题,并不适合专到最底层。比如对于100万行的程序,预先花时间去了解每一处细节,就有点过了。
 
(2)可以把博再推进一步,比如:熟悉专门领域的专业知识、熟悉多种既存框架的特性、熟悉提高用户体验的关键点。熟悉多种既存框架的特性的具体含义是:
 
设计某一种解决方案时,首先要考虑的就是是自己开发还是使用现有的模块。一旦决定使用现有的模块(包,框架等),那就要进一步考虑究竟用那个。
 
做这类工作时,如果没有一定广博的知识,做选择的时候就会特别的艰难。
 
假使说现在公司内部要导入一套项目管理系统,那么做决定的负责人必须至少考虑所有下面这些事情:
(1)自己从头造,还是用现成的做二次开发?
(2)用现成的,是用开源产品,微软的还是其他公司的?
(3)用微软的话,是用MSProject还是基于SharePoint,还是混合?考虑License费用的话真的划算么?
(4)用开源产品,有这么多选项究竟导入那一个?
(5)如果自己从头造,那么是基于微软的技术,还是基于LAMP这样的技术?
(6)使用什么框架?
(7)如果要做,用什么语言?
 
一个人很难精通上面所有的领域,但当做选择时,完全没有概念也是灾难性的。
 
此外,考虑博与专平衡点时似乎有一种特例,钻研特定算法的人,从一开始就只往专的方向发展,并不会考虑其他。比如:钻研TTS的人,可能几十年如一日只要专注于TTS就完了。
 
至于具体选择那个方向,则要根据自身情形来定。总的原则是要以当下工作为根基,以实用为目的甄选各种知识,并追求平衡点。
 
大致上讲,期望做技术专家的更适合前一个方向,而期望做技术管理的则更适合后一类方向。
 
学习软件工程的时机与必要性
 
简单来讲越是没实践经验的人越不适合学习软件工程,越需要规划整体把握全局的时候越需要学习软件工程。
 
软件工程中覆盖的元素非常繁杂,可以有管理、流程、开发模型、估算、分析设计方法等。这无疑会把知识面扩展的很宽,一旦没有根底,就很容易变成纸上谈兵,夸夸其谈。
 
在众多软件相关的知识中,软件工程绝对是很特别的一个。很多人很鄙视软件工程,说:我一看到软件工程的书就直接略过;与之相对应,很多人很推崇软件工程,会花很大的心思去研究敏捷、CMMI等。
 
刚入职场的程序员大致上是讨厌软件工程的,因为这东西离自己的实践有点远,并且主要是添加束缚。但既然更加复杂纷繁的历史都可以总结出规律,忽视软件开发的内在规律无疑的对有志于成为管理者的人是不利的。
 
真要学习软件工程,不太适合从抽象层次很高的教科书开始,而适合从《代码大全》这样与实际关联比较紧密的书籍开始。
 
在国内软件工程的落地似乎始终困难,软件工程相关名词始终在不停的变换(ISO,CMMI,敏捷等),但实际能落地起作用的却不多,这最终导致了一种吊诡的局面:刚对一个绝望,就开始对新的一个报以希望,并在这两个简单的步骤上做无限循环。这种状况也许有其更深层次的原因,比如生存压力过于强大导致工程力量的长远价值被漠视,进而使方法论并不为解决现实问题而存在,而是为了证书而存在。很难据此就说软件工程毫无价值。
 
2.错过人生中的好时机
 
没毕业的程序员或者刚毕业的程序员往往感觉空余时间比较充沛,还很苦恼不知道如何打发时间,但实际上一个人一生中可以用于充电的时间远比想的少。一旦错过时机,往往悔之莫及。
 
对于大多数人而言,人生就像个模板,小处还有偏差,大处却基本相同。
 
20~30岁这个阶段可以讲是黄金时期,这个阶段里,家庭负担较小,可以自由支配的时间较多。当然撞到了很特别的、需要疯狂加班的公司只能另算。
 
30岁之后因为娃娃出生等,家庭上的时间开销增加,个人可支配时间变少。其中很大一部分人还有很大可能会面对电视剧里常说的婆媳矛盾,让你每天心绪不宁。
 
40岁之后,家庭琐事会进一步增加,典型的上有老下有小。实在运气不好的自己也会生点病---颈椎病、腰间盘突出、胃病大概可以入选程序员的三大职业病。
 
50岁之后,时间上会再次解脱,但可惜的是自己也老了,时机不在。
 
如果把人生按照年龄画一条抛物线的话,40岁左右一个人可以达到的人生的顶点,未来再突破的几率则变小。从历史人物来看,大器晚成的不是没有,但真的很少。
 
用心观察就会发现,招聘启示里经常会注明年龄要在35周岁以下或者40周岁以下,除非是招聘高层。这反过来意味着如果没有到高层,人生会在40之前定型,之后有下滑危险(如遭遇不景气、公司倒闭等)。对程序员而言,这种风险尤其的大,因为很可能你辛苦掌握的知识体系被更迭掉了。
 
学习本身无疑的是需要顺应这种自然规律的。
 
很多人很大的一个错误在于,在黄金时期,没做什么积累,就顾得享受生活了,而一旦意识到积累的必要性时,却又受困于诸多琐事而欲振乏力,最终人生高度有限,并迅速走低。这就是现代程序员版的“少壮不努力,老大徒伤悲”。
 
基本上讲,35岁以前要把需要花大量时间,比较硬的技能,学习曲线陡的技能掌握,具备工作所需要的所有主要技能,而35岁之后则主要关注知识的更新和某些软技能。
 
学习时添水战术效率真的很差,每次点一根火柴烧水,一亿年水也烧不开一壶。同时,比较硬的技能(比如:DonaldKnuth的《计算机程序设计艺术》)往往是需要大块时间投入的,但年纪越大时间越呈现为碎片化,越难搞定硬的知识---先天就容易造就添水战术。比较软的技能,则可以用碎片时间来学习,比如:提高PPT的制作水平,提高表达能力。
 
如果能够安排好自己的时间和软硬知识的关系,那么就可以在特定基础上做积累,小步前进,使自己的价值越来越高。从这个角度看,年轻绝对是一种债务,大多数人必须在他没完全结束前,还掉所欠的东西。
 
那么具体来讲那些东西是比较硬的,要在35岁前搞定呢?这因目标而异,但下面这些项目应该具有非常高的通用性:
(1)精通一门最常用的语言
(2) 了解一个最常用平台的基本机制,比如:内存管理、线程机制等
(3)UML图和面向对象分析设计方法
(4) 设计原则,如:职责单一等
(5) 设计模式
(6)《代码大全》里讲的一切
(7)精读一个知名的,但有点规模的程序。这点上要感谢开源项目给我们提供了这么多优秀程序。但要谨防好高骛远,动辄挑战Linux内核,精读是关键。
(8) 累积一定的代码量,比如:独立的完整做过一个数万代码行的东西。这里的关键是完全自己打造,一定不要拷贝粘贴。
(9) 掌握基本算法和数据结构(可以不自己写,但至少要知道其复杂度和区别)
(10) 养成一种清晰的编码风格
(11) 有自己的专业(金融、高并发网站,图像处理,TTS等)
 
学习英语的时机和必要性
总的来看,程序员学习英语是一项投资回报率相对比较好的投入。从目标上来看,程序员未必一定要口语流利,但最低要达到阅读英文资料没有障碍的程度。这里面有一个微妙的事情,一旦英语阅读问题较大,查找问题会习惯用百度,这天然会限制一个人的视野。不是说百度自身有多不好,而是说英语的世界里有着更多更精彩的内容。不管喜欢不喜欢,我们必须承认一种现实,在IT的世界里英语是一种世界语,一方面是由于美国公司的强大,一方面则是由于开源选择了英语。这最终导致IT世界里的新动向、解决问题的小技巧、网站的架构等等都要到英语的世界里去找。在StackOverlow很容易找到各种小问题的答案,在Quora则很容易找到各种网站的架构。
 
从学习时机来看,这件事情特别应该在大学里面搞定,如果不行至少也要在毕业1~2年内达到阅读无障碍的程度,当然希望加入外企还需要额外的付出。从学习方法来看,学习外语真没什么特别的窍门,坚持并投入时间即可。
 
3.停止知识更新
 
对程序员的增值而言,人生里最大的陷阱也许是为安全的假象所欺骗而彻底的放松自己。这种状况在生存环境比较恶劣的情形下不太会发生,但在垄断企业或某一领域中绝对领先的企业里则容易滋生。发现自己是否停止知识更新了并不困难,比如:一年一本书没看,一年一点新知识没接触,一年中工作负荷基本不满等都可以成为一种信号。
 
这真的是温水煮青蛙,一旦到了三十几岁,并在这种环境中呆习惯了,那么再想跳出来,基本没可能。唯一能做的事情是,祈祷公司不要挂掉,公司也不要来场运动,进行人员的大换血。孔夫子说:日当三省吾身,这是很有必要的,至于认识危险后能否做点什么,那就是事在人为了。
 
(1)技术人员的知识更新
接触一个新的岗位后,大致要经历一个学习并逐渐胜任的过程,这个时间段里大多数人的学习热情是很高的。一旦基本胜任之后,事情就有了变化。
 
很大一部分人可能会感觉,反正工作也就用到这么些知识,学习其他的也用不上,因此开始把自己封闭起来,不太看书,不太看技术新闻。
 
这其实很危险,因为这种做法等于把自己绑死在当前这份工作上。而任何一个产品都有自己的生命周期,一旦一个产品的生命周期结束时,碰巧其所用的技术也已经过时,那么当事人就会很尴尬。因为产品可以结束,生活却还得继续。
 
这里面一个非常经典的例子是MFC。微软的这款产品的历史非常悠久,从1992年发布到2012年几近存在了20年时间。随着90后程序员的逐渐出现,马上这款技术就要变得比程序员的年纪还要大了。
 
即使到今天,很多桌面应用仍然是基于MFC开发的,这可以通过查看程序包的dll依赖来很容易的进行验证。MFC是一个很大的池子,有深度、有历史。想把MFC的类继承关系、消息机制、框架结构、RTTI、序列化都搞清楚还是要很花一点时间的。
 
现在我们假设一款庞大的企业应用是基于MFC开发的,一个程序员也通过几年的努力了解了MFC,了解了应用本身,并可以负担起Bug修正,新功能追加等任务了。
 
接下来这个程序员似乎没什么好学的了。因为MFC的更新几乎已经停滞,因此对MFC的学习几乎不需要花太多的时间了。现有代码也理清楚了,也不需要再花很多时间学习了。现有程序也比较好的满足了企业的需求,推倒重来的可能性几乎没有。
 
那这个时候这个程序员不需要学习了么?答案一定是否定的。
 
这里面蕴藏着一个天大的矛盾。
 
从企业的角度看,一定是需要一个团队来维持这个程序的开发的。但从个人的角度看,如果把所有的青春都耗费在老技术上,那么一旦老技术退出历史舞台,个人该何去何从?
 
还是上面的例子,假设说一个人持续投入在这类开发上,当他45岁的时候,当前产品生命周期结束,世界变的只有移动开发和云端开发,那么只擅长MFC的他该何去何从?
 
如果真的如此,这个人就被逼到了死角里,人生很可能产生巨大滑落。所以一定不能认为所学足够而停止技能的更新与学习。
 
从具体应对措施来看,一是要参照知识的地图,横向扩展知识的广度,比如不只要盯着代码,也要了解业务;不只关注开发也关注一点估算;二是提升可流动性比较好的东西的掌握程度,比如:面向对象分析与设计,这样跨越到其他技术时就能够比较平缓的进行过渡。三是要争取轮换岗位,争取多种实践机会。
 
(2)管理者的知识更新
 
到现在为止大部分人认同,管理者是需要懂技术的。从逻辑上看“懂”基本上是不瞎指挥的前提,所以这可以称为中国版的“现场主义”,估计争议不大。
 
那关键问题就是究竟要“懂”到什么程度?
 
如果说两个人,一个选择了管理方向,一个选了技术方向。接下来要求管理方向上的人技术水平要和技术方向的一样,那么除非这个人特别天才,否则不太可能。正像前面所说,这是由于这两个方向的“Key”不同所造成的。
 
如果把目标设定为确保最终产品的成功,同时假设管理者有更高的决策权,那么管理者必须在下面这些方面有技术感觉。
 
从做产品来看,要想成功,有两个关键维度需要同时进行把握,一是产品的概念完整性的把握;一是用合适的手段去实现这个产品。
 
前一个话题很老,《人月神话》就有提及,但实践中却总是被人忘记。好的产品必须贯彻某一种统一意志,iPhone、微信又重新验证了这一个老的原则。机械拼凑的产品虽然融合了很多人的想法,但往往是平庸的,并且在项目执行过程中,往往是出错的根源。很像是虽然有法律,但每个人有自己的理解,各行其是这样一个状态。这种概念完整性是管理者第一个需要有所把握的事情,其次就是解决如何去构建产品这个问题。为达成这一目标在下面这几个方面上,管理者要有自己的理解,至少要有自己的原则:
 
下面简单列举几个比较关键的考量,这和前面论及的如何往博的方向发展有点重叠:
(1)使用现有产品还是自己开发
比如:那些模块适合自己搞定而那些购入就可以了。购入的时候要遵循怎么样的标准去选择。
 
(2)使用那种平台技术
比如:是使用微软的技术,还是开源的技术。
 
(3)现行架构是否可以达成产品目标
比如:在硬件加软件可以同时支撑的并发数目。
 
(4)代码可维护性如何约束
这要求必须熟练掌握一些原则性的东西,比如:什么信息隐藏、正交分解、抽象是否充分等。以及一些无歧义指标,比如:圈复杂度,单元测试的收益平衡。
 
(5)那些环节必须固化为流程,那些一定要团队自由决定
比如文档化要到什么程度才合适,不同阶段间什么是必须的输入输出。
 
......
 
假设说有人不这么认为,而是在做了管理后,表现出足够的惰性,不再持续更新自己的知识体系了,那么会发生什么事情?
 
这时候会很可能会管理倒置。即管理者是名义上的上级,但基本失去对现场的把握,所有的决策完全依赖于下属。得力下属不在,各种决定就只能靠瞎蒙,最终变成只会沟通的管理者---即使被食人族吃了也不会有人注意到,因为存在价值已经被无限稀释,变成了一个象征性的符号。也可能会和下属爆发激烈冲突。因为这类管理者没有自己的立场,上面有任务只能下压。结果同实际情况偏离万里,不具有可实现性,这类管理者无法对自己的上司陈述,也就只能向下转移压力。
 
不管是那种,一旦到这种地步,其实是趋于失败,只能祈祷食人族不要来。
 
为什么中层管理者也要坚持知识更新?
在IT行业流传着一个很有名的关于食人族的笑话,这个笑话说的是:
 
两个食人族的人应聘进了某家大公司,公司人事主管知道这两个这伙每天都要吃人,于是警告他们:“如果你们胆敢在公司吃一个人,你们就会立即被炒掉!”两个食人族唯唯喏喏地答应,表示绝不会在公司吃人。两个月过去了,公司平安无事。
 
突然有一天,公司发现负责打扫公司卫生的清洁工不见了。于是人事主管非常气愤,找来两个食人族怒斥,并当场炒掉了他们。出了公司大门,一个食人族马上对另一个抱怨起来:“我一直警告你不要吃有在做事的人,你就是不听!我们两个月来每天吃一个经理,没人发现。你看现在吃了清洁工,他们马上就发现了!你真是个猪!”
 
这个笑话嘲讽的是某些大公司大企业病发作,人浮于事。大企业病的成因很难一下子说的清楚,但结果却比较明显,一定会导致较多人成为中层管理者。如果说成功的企业天然有感染大企业病的趋势,那无疑的中层管理者也天然有着膨胀趋势。从个人角度看,成为被食人魔吃掉也没有人在意的经历并非是什么好事,因为这意味着存在价值减弱,也不需要什么知识更新。一旦面临裁员这类事情,这个人很可能已经失去了面对残酷竞争的能力。



-------------------------------------------------------------------------------

前面讲到了程序员成为高手需要有一张地图,借助这样一张地图,程序员可以尝试成为架构师、Guru或者纯管理者。但这条路总是不会那么顺畅。

升级练功流的网文中总会给修仙的主人公设置下几大关卡,比如:金丹难成、元神难成、成了元神后还有天人五衰等等。没有这些关口,情节很难推动,所以仙侠类的网文几乎无一例外依赖于这类设定。这一传统甚至可以追溯到《西游记》和《封神演义》。

拿这个来对照程序员的增值道路,就会猛地发现,升级练功流也不完全是扯淡。不管走那条道路,程序员的修炼路上同样的也有三灾九难,要想成就高手,还是得一个个跨过去才行。如果一个程序员达到一定高度后再回头观望,那就会发现自己的同学、曾经的同事总是会因为这样那样的原因倒下去。这并不是一个简单的天道酬勤就可以敷衍的行当,下面就让我们来具体看看,究竟增值过程中可能遇到那些陷阱,掉到坑里又需要付出多大代价才爬的出来。 

1. 学习失去焦点

软件行业里有几个经典的题目,每过一段时间就会被翻出来PK一下,比如关于编程语言优劣的比较等。其中一个经典题目是软件和数学的关系。

从结果来看,一派人认为数学是软件的基础,而另一派人认为数学和软件没什么太大关系,除非是在某几个特定领域里。如果你用心观察过这事情,你就会发现这事情特别有意思。

比如说:

2011年,CSDN转了一篇,叫:“数学是成就卓越开发人员的必备技能”的文章,在文末作者说:

那么,数学对所有事都有利么?这事情很难说,我对我现在的处境十分满意,或许你也如此,但这都和潜能有关系。如果你是协作世界的一名开发人员,你真的不需要数学。如果你乐于你的整个职业生涯是这样的:在工作时间中做企业CRUD应用,或在闲暇时间滑翔跳伞或极限水上滑板(或其他各种时髦的极客运动),也分配较多时间在SpringHibernateVisual Studio或其它东西上。那些特殊的职位并没有真正限制你的潜力,你能变得极具价值,甚至可深入追求。但是如果你想为多样化的职业生涯而奋斗,想要有能力尝试几乎所有涉及代码的事,从信息检索到Linux内核。总之,如果你想成为一个开发人员、程序员和计算机科学家的完美组合,你必须确保你的数学技能达到标准。长话短说,如果你在数学方面有一定天赋,那在软件开发领域中所有的大门都是向你敞开的,如果没有,那你就安安心心地做CRUD型工作吧!

总的来看,这个作者认为数学很关键,得学。

而在2012CSDN又转了篇文章,叫:编程需要知道多少数学知识?在文章里作者说:

数学和编程有一种容易让人误解的联系。许多人认为在开始学习编程之前必须对数学很在行或者数学分数很高。但一个人为了编程的话,需要学习多少数学呢?

实际上不需要很多。这篇文章中我会深入探讨编程中所需要的数学知识。你可能已经都知道了。

对于基本的编程,你需要知道下面的:

加减乘除—实际上,电脑会帮你作加减乘除运算。你仅需要知道什么时候运用它们。

模运算—模运算是用来计算余数,它的符号通常用%百分号来表示。所以23除以7等于3,余数是223 mod 7 = 2

判断是奇数还是偶数的模运算—如果你想知道一个数是奇数还是偶数,用它mod 2来作模运算。如果结果是0,它就是偶数。如果结果是1,就是奇数。23 mod 2等于1,所以23是奇数,24 mod 2等于024是偶数。

对一个数作百分数运算,就是用这个数来乘以一个百分数。譬如你要得到27954%,就是用0.54*279。这就意味着为什么1.0等于100%0.0等于0%

知道负数是什么。负数乘以负数等于正数。负数乘以正数等于负数。就这么简单。

知道迪卡尔坐标系统。在编程中,(0,0)代表屏幕左上角,Y坐标的正轴往下。

知道勾股定律,因为它是用来计算笛卡尔坐标中两点之间的距离的。勾股定律a^2+^2=c^2(x1,y1)(x2,y2)两点之间的距离等于((x1x2)^2+(y1y2)^2)

知道十进制、二进制、十六进制。十进制就是我们通常用的十个数:0-9。通常认为这个十进制系统是人类发明的,因为我们有十个手指。

 

总的来看,这个作者认为数学不太关键,大多时候可以不学。

你如果持续关注这事儿,各种极端对立的观点绝对会吵爆你的头。但这事情其实不可能有结论,因为被对立起来的两极都是太大的概念。

比如说:如果把软件开发缩减为应用软件的开发,那争议性就会降低很多。

这里的关键问题是,假如一个人的目标是应用软件开发,却花了10年来学习数学,接下来在实际应用程序开发过程中,每天面对的是UI布局、IDE使用、圈复杂度控制、面向对象使用、设计模式的使用和类库的使用这类问题,那么这个人就会发现数学其实没啥用,他等价于因为失去焦点而失去了10年。

这里想表明的是,一旦误读了知识与目的间的因果关系,那么学习就会失去焦点,进而造成负效应,毕竟相对于人的可承受负荷而言,这个世界上的知识不是太少,而是太多。

一般的认识是只要学习就必然有所得,所以对人生的影响一定的是正面的。但实际上这个想法是偏颇的,尤其是在软件行业里。

在软件行业中,这种风险之所以异常突出,就在于前面提到过的软件的两个特质:更迭速度快和子领域众多。这两个因素导致软件相关的知识是爆炸性增长。

而避免“失去焦点”这一陷阱的第一关键则是分类:对软件开发进行分类,对软件所关联的知识也进行分类,形成自己的大局观和整体视图。

前文曾经提过集中对知识进行分类,对软件进行分类的方法,这里再补充一个对绕过这一陷阱有帮助的分类方法,它来自《软件成本估算:COCOMOII模型方法》这本书。

书里面把软件分成了下面几个类别:

终端用户编程(一般的应用程序)

应用程序生成器(开发工具等)

应用组装

系统集成

基础结构(OSDB等)

 

在进行分类的同时,书里还给出了一组数据,即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(左侧有二维码)就行了
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值