码路指南


此文章所在专题列表如下:

  1. 码路指南:缘起
  2. 码路指南:怎样才算是编程高手?
  3. 码路指南:程序员的几个职场发展方向
  4. 码路指南:为何你成不了编程高手?
  5. 码路指南:在博与专之间取得平衡
  6. 码路指南:别错过人生中学习的黄金时期
  7. 码路指南:物质驱动与兴趣驱动
  8. 码路指南:保持内心的青春与理想


码路指南:缘起

 专治各种迷茫


我们这一代的父辈,大部分都不是程序员,没有从事编程的经验。以我自己来说,我是2000年初中二年级才接触的电脑,而那时候也正是个人电脑开始普及的时候,所以我是随着PC和互联网蓬勃发展而涌起的编程者大浪中的一员。由于可鉴的前车并不多,这朵大浪会如何走向,又会有多少人拍死在沙滩上,后继的浪潮我们又该如何正确看待,这些问题其实我们都是要想清楚的。毕竟我们最起码要生活,那么职业发展问题是个大问题。

我相信很多程序员都会有各种各样的迷茫,比如:

  • 我该如何入门?
  • 我该如何提高自己的编程水平?
  • 我的编程水平遇到瓶颈了,如何突破?
  • 为什么我努力看书学习,还是感觉没多大提升?
  • 我觉得我现在是专家,啥都做得出了!但其实你还是个编程新手
  • 我在公司里无晋升/加薪希望,该怎么办?
  • 我都过30岁了,还在编程一线加班,怎么办?
  • 等等……

这些问题我们都需要弄明白。如何自己想不明白,就需要外人点播一下。

我一直关注博客园的“理想流”(http://www.cnblogs.com/daoshi/),很欣赏他独到的思考,最近看到他出的书,还有写的“程序员生存定律(http://www.cnblogs.com/daoshi/p/3776814.html)”一系列文章,私以为对指导我们程序员的职业生涯有不错的帮助,于是拜读并加以排版整理,后续会再加入自己的一些看法,记录在“码路指南”这个专题里。希望更多人看到,也希望帮助更多人解决迷茫。


码路指南:怎样才算是编程高手?

高手的定义

一旦度过了初始阶段,做过了前面说的那些事情,那么一个人算是基本入行了,接下来的目标就非常简单,要在选定方向上成为高手。高手意味着专业,而在分工无限细化的年代里,专业则是生存、发展好最为重要的一个前提。

高手的定义和养成关键

我估计如果问100个人“什么样的程序员是高手?”,那答案会有100多个。因为同一个人还可能给高手下不同的定义。

在这里我们认为,在特定领域里能搞定大部分人搞不定事情的就是高手。从这样一个定义出发,我们会发现在技术人员和销售人员眼里,高手的内涵是有很大差异的。

纯技术人员更多的关注性能能不能提到极致,并发能不能处理的很好,内存溢出Bug能不能很快搞定,类库的机理熟悉不熟悉等等。而在销售人员的眼里,则在技术外还多看了些东西,比如业务流程熟不熟悉、使用性好不好、能否迅速对应变化、能否在限定工期和预算下搞定任务等。

考虑到职场和产品销售有着非常紧密的关系,我们这里使用后一个视角,而非是单纯的技术视角。

有几类本质上很不同的人都会被视为高手,比如说:

  • 能写出很牛的病毒的。这个不举例子,但当年读过CIH的代码,我是被其精巧给震住了。此外也许搞加密解密的也应该放在这个类别里。
  • 能把一堆3D图形放到64K的。以前专门有个比赛是干这个的,64K大小的EXE能给你放10几分钟很酷的3D动画,第一次见绝对会很震惊。
  • 能迅速调试出问题所在的。内存泄露、多线程同步这类问题往往让人纠缠很久也搞不定,但就是有人能很快的解决这类问题。
  • 能仅靠几个人就架起高并发网站的。新兴Web2.0网站如:Flickr,甚至还可以包括Google,在初期往往是几个人搞起来的,这些人名声不显,但绝对是高手。
  • 能主导开发出很牛的产品的。这个上可以想想Unix和Linux的作者等。
  • 能主持大规模软件设计的。这个往往更有商业价值,我们常说的Martin Fowler应该可以算在这个类别。
  • 能把一种语言研究的特别牛的。想想各个编程语言的创建者,想想C++的大牛们。当然创建某一门语言的也可以归到这个类别里。
  • 能开辟自己方法论的。比如搞CMMI的Watts S. Humphrey。
  • 能写出很牛的书的。比如:Windows平台下写了Windows核心编程的Jeffry Richard。
  • 能写出很牛的算法的。比如:Donald Knuth。
  • ……

这个表应该还可以加长很多,单以大家认可这个角度来看确实高手可以从各个方面冒出来。 

不管在那一方面,要想成为上面所描述的高手总是需要学习、思考、实践这些环节,这没什么可说的。但和软件相关的知识其实多如牛毛,完全不像小说里武功秘籍那么稀缺,几乎可以讲满地都是。这就使选择和集中成为难题。

软件的三个基本特征(技术更迭快、低介入门槛、多内部分野)就像铡刀一样,一旦选择出错,就会把个人的努力切的粉碎,一点价值也留不下来。而与此相对的,则是人的黄金学习时间其实并不多 —— 不过是毕业后的10年左右的时间。

曾经有人希望自己能够从事嵌入式软件的开发,因此给自己买了ARM板,自己在家里花了很多时间来学习并实践相关知识,最终却因为其他的原因进入了一家做网络的公司。这个人等价于被软件的内部分野较多,而彼此间技能流动性较差这样的一个特质斩了一刀,被斩掉的倒不是ARM板,而是自己一年多的辛苦投入。这种情况下强调学的知识将来有用是没有太大意义的,因为还有两刀在等着:如果你三年都不做这个,你今天学到的知识可能会被更迭掉了,同时由于你年纪增长了,可能也不太适合与大批新介入这个行业的人员进行竞争。 

这类事情使软件行业中的成为高手这事变得复杂了。

为了在成为高手这条路上走的顺畅,事实上有三个关键点:一是要有一张全局性的地图,以便选好方向;二是要知道都有那些坑,好绕开它,免得掉进去。三是要有足够的热情和动力,能坚持走下去。下面将分别从这三个方面来说明成为高手途径和方法,而这种途径和方法会因为具体目标不同而有所微调。


码路指南:程序员的几个职场发展方向

职场该如何走?

清代著名学者曾对知识地图的必要性做过非常精确的表述:

凡读书最切要者,目录之学也。目录明,方可读书,不明,终是乱读。

—— 王鸣盛,《十七史商榷》

目录即是地图。

对于软件开发的知识,我更愿意使用下面的的“地图”,这不一定是最合理的,但确实对归纳各种软件开发知识有所帮助。

1. 通用的领域知识

  1. 编程语言(C/C++,Java,C#,Python,Perl,PHP等)
  2. 框架和类库(Struts,Spring,OSGi的某个具体实现,MFC,Boost等)
  3. 平台(Windows API,POSIX,.Net Framework※1,Java API,C/C++ Runtime Library等)。恰如Jeffry Richter所说,大多时候可以从内存机制、线程机制、错误处理、异常处理、组件构建、组件组合等方面来进一步考察一个平台。
  4. 计算机体系结构(CPU指令,虚拟存储等)
  5. 数据库
  6. 实用技巧(调试方法,代码生成器等 )
  7. ... ...

※1 有的时候子类别间的界限并不是很容易界定,其中一个主要原因就是存在着像.Net Framework这样涵盖了过多内容的概念。

2. 概念和逻辑创建和优化

  1. 面向对象分析和设计/结构化分析和设计
  2. 设计模式
  3. 重构
  4. 契约式编程
  5. UML ※2
  6. ... ... 

※2  从形式上来看UML更近似于一种编程语言,但从其目的上来看也许归在这里是更合适的一种选择。

3. 专业领域知识

  1. 图形图像算法
  2. 网络协议
  3. 人工智能
  4. 数值/非数值类算法
  5. 财务知识
  6. 负载均衡
  7. ... ...

4. 关于软件的间接知识:

  • 需求开发和描述
  • 估算
    1. 估算法。比如,COCOMO, FP等。
    2. 估算术。比如,使用计数等原始办法。
  • 软件工程和方法论
    1. 轻量型方法论。比如敏捷。
    2. 大方法论。比如CMMI
    3. 综合分析。比如,《人月神话》,《人件》所做的工作。 

随着待解决问题越来越复杂,通用的领域知识中,几种技术往往会组成一种技术Stack,他们更需要被看做一组必须一起掌握的知识,比如:LAMP(Linux+Apache+MySQL+Python/PHP)。

当然上面罗列的远不是全部,这种罗列更多的是展示一种分类的方法。通过对这种分类方法的补充和完善,大多可接触到知识都可以被归入特定的类别,比如说:WinRT可以看做一种新的平台,HTML5则可以看做是一种语言等。

每个人可以根据自己的情形,参照上面的分类建立属于自己的地图,有点问题没关系,有就比没有要好很多。接下来依据这样的地图就可以选一条自己的线路,持续累积,寻求实践机会,最终就很可能会成为真正的高手。

而关于增值所需的动力,所要避开的陷阱,将下面陆续提到。

增值、读书与大局观

单纯从达成某一目的而言,读书往往非是绝对必要条件。

秦始皇把书一把火烧了,刘邦项羽一样造反并取得胜利。但读书无疑的可以加速一个人增值的过程,记不得是谁说过:实践无疑是人类最好的老师,但只靠实践来认知世界无疑也是愚蠢的。这是非常精辟的。除此之外,要想培养大局观,那就非读书不可。

每个人的亲身经历,在大的时空背景中往往只是一个简单的截面,这一截面中绝不会包含可以归纳出所有真理的事实,因此只依赖于自身的实践也就必然限定了一个人的视野。 这一点随着一个人的责任范围变大往往会体现为一种制约和限制。所以培根讲:有实际经验的人虽能够处理个别性的事务,但若要综观整体,运筹全局,却唯有学识方能办到。 

即使从实践来看也是如此,要想培养出一种大局观,那就非读书不可。而大局观往往是成为将帅之才的必要条件。

具体到软件而言,有一本很有名的书对培养技术的大局观有帮助:《代码大全》。至于专业性较强的书,反倒是可以根据自己的情景比较容易的选择,这里就不提了。

基于上面这样的一张地图,我们就可以具体的去考虑几条进阶路径。

路径一:由程序员而架构师

架构师是一个很火的职位名字,但你很难给它下精确的定义。

下面所陈述的一切是我个人的理解和体会,我无法保证它和其他人的解释完全吻合。因为架构师,乃至架构设计实在是一种非常模糊的概念,如果你用心去找,可以找到各种定义(甚至IEEE和SEI的定义也不一致),这就导致你只能参照别人,相信自己。

本质来讲架构设计也是设计,所以凡是做设计的都可以称自己为架构师。

当一个系统的规模变大的时候,设计上的决策就具有了特别的价值,并且也越来越需要专门的人来做,架构设计也就越来越像是一种特别的设计。比如说:考虑架构设计的时候,可能需要考虑选用什么样的数据库、选用那个开源框架、选用什么样的硬件平台,这些东西在小规模程序中往往是居于次要地位的。

假设说一个人已经掌握了一门或几门编程语言、面向对象、设计模式、能够很熟练的写出质量较高的代码,接下来他想成为架构师,这个时候他需要做什么?

我个人认为,这时候这个人首先要有一个“专业”。这个专业可以是“金融”,“财务”,“电商”,“管理”等等。这是一种属于某一专业的领域知识,而不是编程技术。如果把需求和最终的代码,看成描述同一事物的一体两面,那么设计始终是要架起这两者间的桥梁。而架桥的时候,怎么可能只知道一端而不知道另一端。

接下来是深化设计所需要的各种通用领域知识(UML、面向对象、性能确保等)。这时和一般所说的设计的一个关键区别是,那就是架构设计要分心思去考虑那些东西用别人的就好了,而那些东西要自己开发。而一般所说的设计技术中,比较侧重自己应该怎么干(面向对象、测试驱动等)。为达成这一目的,就需要对现有技术的优劣有相对比较清晰的认识,比如要能分清楚那些是成熟稳定的技术,那些是处在实验阶段的技术。Pinterest网站就曾经进行过下列这样的架构改进,在这样的改进过程中,不知道各种技术的优劣是代价很大的:

Pinterest 早期阶段:

  • Rackspace
  • 1 small web engine
  • 1 small MySQL DB

2011/1:

  • Amazon EC2 + S3 + CloudFront
  • 1 NGinX, 4 Web Engines (for redundancy, not really for load)
  • 1 MySQL DB + 1 Read Slave (in case master goes down)
  • 1 Task Queue + 2 Task Processors
  • 1 MongoDB (for counters)
  • 2 Engineers

2011/9:

  • Amazon EC2 + S3 + CloudFront
  • 2NGinX, 16 Web Engines + 2 API Engines
  • 5 Functionally sharded MySQL DB + 9 read slaves
  • 4 Cassandra Nodes
  • 15 Membase Nodes (3 separate clusters)
  • 8 Memcache Nodes
  • 10 Redis Nodes
  • 3 Task Routers + 4 Task Processors
  • 4 Elastic Search Nodes
  • 3 Mongo Clusters
  • 3 Engineers

2012/1:

  • Amazon EC2 + S3 + Akamai, ELB
  • 90 Web Engines + 50 API Engines
  • 66 MySQL DBs (m1.xlarge) + 1 slave each
  • 59 Redis Instances
  • 51 Memcache Instances
  • 1 Redis Task Manager + 25 Task Processors
  • Sharded Solr
  • 6 Engineers

2012/10:

  • Amazon EC2 + S3 + Edge Cast,Akamai, Level 3
  • 180 Web Engines + 240 API Engines
  • 88 MySQL DBs (cc2.8xlarge) + 1 slave each
  • 110 Redis Instances
  • 200 Memcache Instances
  • 4 Redis Task Manager + 80 Task Processors
  • Sharded Solr
  • 40 Engineers (and growing)

摘自:http://highscalability.com/blog/2013/4/15/scaling-pinterest-from-0-to-10s-of-billions-of-page-views-a.html

这个过程比较真实,大家可以参照着想想如果自己来主导,那还欠缺什么。

最后一点要说的是,做架构设计已经相对于在做技术管理工作,至少要适当涉猎估算并能做出合适的任务分解,这样一旦日程紧张,则可以通过增加人手等手段来在质量、成本和进度之间进行均衡。

由于知识面已经扩的比较大,架构师在具体某个专业领域上的深度可能会有所欠缺,比如:在做一款电子消费产品时用到了TTS,但架构师不一定能很好的了解TTS的算法---这是CodeGuru的领域。

架构师所需要达成的最终目标可以形象的描述为:产品经理考虑用户和市场建立了一个模型,那么架构师要能把这东西映射到技术的世界里来。如果是在互联网行业,那么在你的主导设计下要可以做出高并发的网站。换到其他行业也与此类似,从产品的的角度往回看,架构师要能解决和技术相关的所有问题,主导完成商业上有价值的产品或项目的开发工作。实现手段上倒并无限制,可以是购买,可以是组织人员进行开发,只要能平衡短期和长期利益,解决特定的问题即可。

路径二:由程序员而CodeGuru

与架构师相对应,在某些智力密集型的程序中,也需要技能高超的程序员,这种程序员往往被称为Guru。

这条路线里,程序员并不把自己擅长的领域扩的太宽,但在指定领域上会挖掘的很深。驱动、字库、图形库、算法库、OCR等都偏向于这一领域。

假如说,一个程序员在掌握基本语言之后,想往这个方向发展,那么需要的技能和架构师差别很大。比如:一个人如果想往驱动方向发展,那么就需要了解CPU的基本结构、内核调试方式、操作系统中与相应驱动所对应的机制、硬件侧的规格、通讯协议等。

这时候很可能由于程序规模并不十分庞大,面向对象、设计模式这类东西没有太大发挥空间,而是需要处理的是大量或麻烦或艰深的细节。

2013年1月,ITeye发布了一条信息说:Intel面向学生免费提供 C++ 开发工具,并简单的介绍了一下是那些工具免费向学生提供:

  1. Intel C++ Composer XE,其中包括:
    • Intel C++编译器(高度优化的编译器) 
    • Intel数学核心函数库(高性能数学库) 
    • Intel线程构建模块(C++任务模型、最流行的C++并行方法) 
    •  Intel集成性能基元(多媒体基元库) 
  2. Intel Advisor XE(推荐的并行开发建模方法)
  3. Intel VTune Amplifier XE(非侵入性的性能分析工具)
  4. Intel Inspector XE(先进的线程和内存调试工具)

看到这张列表,我们可以思考下要开发这类工具需要什么样的程序员。上面这些工具的开发都属于高难度的工作,和开发大规模的MIS系统完全不同,如果不是某方面的专家,基本不太可能负担起相应的责任。而这类领域则正是Guru的天下。

路径三:由程序员而纯管理

纯管理工作和技术管理工作可以用是否接触乃至编写代码来区分。纯管理工作往往需要把精力放在预算编制、人员职业路径、考评、度量、流程改善这些工作上。一定程度上讲,这等价于和编程工作说拜拜,当然前提是你得有编程经验,有一些通用领域知识和概念创建乃至逻辑优化的知识,否则的话和程序员没法沟通,进而给工作造成障碍。

从需要读的书来看,这时候可能要看过PMBOK,《项目管理修炼之道》,《管理的实践》,《基业长青》等等。

但如果一个人认为想做管理要从PMP开始,那大概是还没太明白管理这项工作的本质。管理本身是一种借势,虽然有技术性的一面,比如要理解挣值曲线这类,但这方面知识其实并没有想的那么复杂 —— 至少没有C++11复杂,只要有时间正常智商的人都可以在不太长的时间内掌握。所以如果你想做管理,并使用了和学习C++语言一样的方法,那基本上是偏离了方向。

抛开机缘这类东西不论,做好管理工作有两点很关键:

  • 一是要把技术工作做的相对比较好。这好像有点学而优则仕的意味,但大多时候人们更愿意相信“将军起于行伍,宰相拔于州郡”,而不愿意相信单只会耍嘴皮子的人。过度务实的人容易迷失于道路,过度务虚的人则容易飘的太高而丧失根基。管理者正应该身处在这两者之间的一个平衡点。
  • 二是要能够借势。要情商比较好,能把很多人组织在一起。这个时候要知道那些东西需要规则化,那些东西需要灵活把握。过度偏向规则是教条,过度偏向灵活则是人治,平衡点始终要根据具体人员的状况,工作特质这些不可改变的事情来把握。这有点微妙。但即使程序员这个群体相对简单,但并不能推翻先人后事这类规则。这不知道是不是东方特色,当你想做管理并想推进事情的时候,终究要理清人际上的关系,否则就和可能会欲速则不达。这点会在后面进一步展开来谈。

下面我们来看一个具体点的例子,这个例子出自郭致星老师的博客,是一个学员的真实疑问(文字上有修饰),X入职后的现状如下:

开发部现在26个人。基本组织架构是由开发组、需求组、测试组、运维部四个部门组成。需求组的人收集需求,再通过系统指派给开发组,进行开发。开发组的文档严重缺乏。

现在公司内有技术总监和开发部经理的岗位。眼下全公司就X一个项目经理,目前是跟着开发部经理,在熟悉一个核心系统,由于没有任何文档的遗留,所以现在是相当于一个开发人员在开发一些实际的功能,一边开发一边熟悉现有系统。

现在X并没有项目的实际权力,而且整个项目组也只有开发部经理,加上2个开发,再加上1个测试和X共5个人。其中X和其中一个开发都是新来的。

与此同时,业务部门在搞一些流程,但还没做完,没有在开发部进行实施。工作气氛比较沉闷。技术总监和开发部经理,都是技术型的人,比较偏向技术,平时工作也多偏向于具体执行。

在使用一个Redmine系统进行项目管理和BUG跟踪。

这里的系统大部分都类似于产品线制,属于需要长期开发维护的,需求源源不断的来,相应人员也就需要不停的做,没有版本制度,也没有计划和规划。

系统现在主要的问题是性能问题。 

问题就是在这样的一种环境下,X应该如何开始自己的管理工作?

这类问题通常并没有唯一答案,但确实有些通行的手段可供参考,最终做不做的好和个人能力乃至环境关联很紧:

  1. 了解现有系统的状况,包括规格、代码规模、代码质量、代码内部结构、工作流程、问题所在等。比如说:很可能这类系统缺乏一种整体设计,是靠单纯的增加代码的量堆积出来的,代码冗余非常厉害,数据库的表也创建的比较随意。
  2. 了解人员。包括人员的能力水平、工作意愿状况、性格。
  3. 了解公司。尤其是公司的运作风格,有的公司偏人治有的公司偏于规则。短期对这类现行秩序要考虑如何顺应,而不是如何改变。
  4. 对当前系统的状况和人的状况有所把握后,要对愿景进行描画,比如在功能上做那些改善,对速度做如何改善,目标的高低要适度,要能获得上司和下属的支持。这时候还要能平衡短期和长期目标,既不能长时间投入没有产出,也不能有产出但进步不可见。在这一步骤里最典型的忌讳是急功近利的做超出自己影响力范围的事情。比如:目标与现有人员的能力完全不匹配或者完全不顾及对销售可能产生的影响而单纯的做系统的优化。最理想的情形是,连续达成几个目标,提升自己的影响力。
  5. 搞清楚团队成员和公司的的基本诉求,在取得成绩的同时尽可能双赢的扩大自己的影响力,目标是确保团队的执行力。
  6. 逐步导入基本流程,使项目上轨道。但流程不能成为成绩的借口。
  7. 接下来进一步的规划愿景,看能否取得更大的成绩,比如:挑战是否能做出真正有特色比较优异的产品。

在不同类型的公司里,对应手段上会有不同。比如在规范性比较强的大公司,第4,5两步的权重就会比较低。在上述这样的场景下,PMP这类书籍中所提到的种种技术手段诚然是必要的,但和人打交道的部分(老板、直属上司、下属)往往会对最终的结果产生更大的影响,这是管理工作与纯粹技术工作不同的地方。

码路指南:为何你成不了编程高手?

成长路上常见的坑

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

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

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

学习失去焦点

软件行业里有几个经典的题目,每过一段时间就会被翻出来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这类公司的面试中往往非常强调算法。

这里最关键的就是聚焦,聚焦的根本则是要在限定时间范围内创生价值。

从方法上讲,聚焦就是找到一个适合自己大小的区域,然后做深。才华横溢的不论,一般来讲,横向穿越和纵向穿越都不太行,除非已经基本穷尽当前的领域。纵向穿越是指从底层穿到上层(想想开发网络协议的和用网络协议的),横向穿越则指横跨太多的领域(想想从内核驱动跨越到信息管理软件)。

其实如果一个人真的拥有无限的时间资源,那么什么时间点学习什么就变得不太关键。但这是不可能的,同时一个人的学习时间远不像想的那么充沛。这点会在后面探讨。 

在清楚自己的目标后,再配合前面提到的知识分类地图,那么避开这一陷阱的几率就大了很多。

学习与实践相分离

喜欢看网文的很少有人会不知道起点,不过估计很少有人注意过起点给小说分类的标签。在网文小说里有很多个流派,其中一个叫做“扮猪吃虎”。这个流派的基本特征是很厉害的一个人要假装很菜,最后在关键时刻力挽狂澜。这个流派十分有人气,大概仅次于“升级练功”,而远高于“重生”、“转世”这类的流派。

网文是绝对的市场导向,所以这个现象可以从侧面说明很多人喜欢“扮猪吃虎”或者说潜意识里有着“扮猪吃虎”的情节。“扮猪吃虎”这事儿小说里看着很爽,但挪到现实里来很容易让人掉到学习陷阱里。更可怕的是,现实里有这种心思的人其实也还很多。

有时候会看到这样一种现象:很多人自学的东西和工作中用的东西完全没关系。比如:一边用着C#做Web开发,一边自己学习着C/C++做嵌入式。

这事并不一定不对,只能说非常危险,很可能会导致那样都没有高度。我们得承认当人生被错位的时候,往往只能这样来改变命运,这是没办法,也是正确的。但首先要认识到这样做是相当低效的,低效到一定程度后对的事情也并不一定有结果。

CSDN曾经做过一份薪酬统计(http://www.programmer.com.cn/5877/),这里面有三个与上述身在曹营心在汉现象有关联的结论:

  • 一是73%的程序员对自己的薪资并不满意。
  • 二是各个主流开发语言上的差异并没有想的那么大。虽然C#开发者中月收入小于5000元的比例最高,但5000~10000这个群体在主流开发语言上相差并不大。
  • 三是平均来看,收入增长和工作年限正相关。当然认为到那个岁数工资自然就高了是很危险的。

对薪资不满意应该是程序员希望跨界的一个原动力,但收入和年限正相关,与语言非正相关却说明单纯从功利角度看跨界并不明智。因为假设一个人Java语言用过三年,C#用过三年,总的来看收入水平更可能处在三年的水平上,而不是六年的水平上。

软件是一种固化的思维,这就软件开发更多是一种实践而非是一种理论。软件开发内的很多领域,总体上看体现的是复杂而不是艰难,不论是前端开发还是驱动开发。

讲到到这里就有必要简单区分一下“复杂”和“艰难”。考试出题可以有两种方法:一是每道题都不是很难,但题量很大;一是题量很少,但每道很难。从结果来看,两类考试方法下,得高分都并不容易,但其难度的来源却并不相同,前者更多的体现为复杂,而后者却体现为艰难。

在软件行业里,除了一些专门的领域,比如图像算法等,软件开发则更类似于前者,所以经过培训后大部分人都可以做软件开发,进入门槛并不高。

解决艰难问题时,天分很重要;解决复杂问题时,练习很重要。所以软件开发的学习过程中,实践很重要,纯理论知识的权重较低,当然基本的算法复杂度还是要明白的。

这也就意味着脱离项目实践的学习投入产出比往往会差。比如说:编程中常见的多线程问题。如果单纯从学习的角度看,创建线程本身并不复杂,掌握各种线程同步方法(事件、信号灯、互斥量等)也并不复杂。写简单例子的时候,也很少会出错。但一旦落到具体的场景下,虽然多线程的本质没变,但没经验的人几乎一定会在涉及多线程的代码上导致一会儿出,一会儿不出的问题。

再比如说:你可能看了很多设计的书,但从来没有从头到尾写过什么程序,总是在既有代码上修修改改,或者只是完成几千行代码的小工具,那么你的设计知识是很难融汇贯通的,也还是无法很好的承担大系统的设计工作。

这点上有一个旁证,根据统计最多的Bug是由新手导致的。这从侧面说明,能做和能做好之间的鸿沟需要大量的实践来填平的。

在这样一种前提下,期望先选个工作,再自己学习,努力转行这样的想法是损失很大的。单纯从增值效能上看,解决这点很简单,除非必须放弃当前的工作领域,否则要以当前参加的项目为根基展开学习,这样才能比较好的调和学习和实践。

而除非一个工作领域过于偏狭,大多时候在编程语言(C#→C/C++)、不同领域间(图形处理→地理信息系统等)穿越损失可能更大。

至于如何在“博”与“专”间平衡,如何选中更适合自己的工作领域,将在后续章节里陆续谈到。

码路指南:在博与专之间取得平衡

平衡最合适

 “博”与“专”上的迷失

假设说一个人的学习已经聚焦,并且学习的内容和自己实际参与的项目也相吻合,那么是不是就没有问题了?很不幸,答案仍然是否定的,在任何一个子领域里,仍然需要进一步去考虑“博”与“专”的均衡。

对于软件开发而言,设计是再常见不过,再简单不过的一个词了。可如果把视角拔高一点就会发现,单以设计而论仍然是一个不可穷尽的领域,我们可以快速扫描一下和设计相关的部分概念:

  • 面向对象分析与设计
  • 结构化分析与设计
  • 模型驱动开发
  • 契约式编程
  • 面向方面的开发
  • 基于组件的开发
  • 元编程

有些时候方法论也会和设计牵扯到一起:

  • 测试驱动开发
  • 敏捷软件开发

如果感觉这个还不够多,那可以去Wiki上查编程的范式(paradigms)这个条目,那里列了47种范式,每个都和设计多少有点关系。

上述这些还只是说了设计,如果横向展开,那么在特定领域中必然还会牵涉到框架的选用、辅助工具的使用等等。这也就意味着,从博的角度来看,即使是在设计这样一个看似狭小的领域中仍然是没边界的。

与此同时,把一个API研究的再透,也是低值人群,因为这种深入理解和单纯会用某个API相比,从创造价值的角度看,差别不大。

这也就意味着对于大多数软件开发人员而言,要去寻找广博与精专间的均衡点:既不能闭上眼睛,也不能就用显微镜来看世界。而这一均衡点的价值则可用反木桶原理来说明:木桶原理说的是桶里的水是由最短的一块板决定的,但考量人的价值时却是适用于反木桶原理,即人的价值往往由最长的一块板决定。

考虑博和专的问题不能离开产品开发进行考虑,前面曾经提到过,产品开发往往和公司的现金流绑定的更紧,能为现金流贡献力量的技术才是有价值的技术。而产品开发本身事实上对博和专的程度提出了最基本的要求,这种要求往往具有迭代的特质。为了形象的说明这一点,这里举一个通用的例子来进行一点说明:

在第一次跌代里,往往需要达到两个最基本的目标。第一个目标是可以为产品贡献自己力量,但代码质量普通。这个目标如果达不到,一个人会失去自己的存在价值。

这时候最少需要了解某种语言(比如:C++)、某个平台(比如:Windows)、某个IDE(比如:Visual Studio)和某些业务相关的知识(比如:打印体系)。这个范围可以尽可能圈的小点,但用到的则要学透。比如:不管接触到那个框架,都要去了解它的内存机制、线程机制、异常处理组件构建和国际化处理这些全局性的机制,而不能只是了解某个接口怎么用。

这并非是很高的要求,没有这些就变成了“靠运气编程”,写完程序后还要祈祷他能跑起来。了解这些之后就可以负担起部分开发工作,否则的话只能做旁观者,没法参与到实际工作中来。

第二个目标是把事情做好,并能负担些层次更高的工作。这时候要比较深入的了解面向对象、结构化方法、设计模式、理解设计原则,并能把它们用好。至少要能判定,这个程序写的好,那个程序写的不好,同时面对需求能把工作进行下去。

前两个目标是基础,一般来讲学校中基础打的越好,这个阶段越短。达成这两个基本目标之后就可以结合情境来做进一步的选择,可以认为这是博与专选择上的第二次迭代。当然这时候也要谨记不要和实践分开。

完成上述两个层次后,可以有两个方向可供选择。

1. 可以进一步考虑专的问题,比如在特定领域里把知识深化下去。做驱动就要理解操作系统的核心机制,做打印的就要了解页面描述语言等,但这个时候要适当警惕边际效应。

边际效应是说,你让一亩地从亩产500斤增加到1000斤可能只需要投入100块;让亩产从1000增加到1500可能就需要200块;让亩产从1500增加到2000则需要400块了。

一个典型的例子是对C++的学习,C++是公认的复杂,如果想做C++的律师,那么估计搞个10年可能够资格了,但问题是把时间都投在这个上,投入产出比可能不好。而停在那里合适则是个尺度问题,大致来讲是可以靠时间弥补的细节问题,并不适合专到最底层。比如对于100万行的程序,预先花时间去了解每一处细节,就有点过了。

2. 可以把博再推进一步,比如:熟悉专门领域的专业知识、熟悉多种既存框架的特性、熟悉提高用户体验的关键点。熟悉多种既存框架的特性的具体含义是:

设计某一种解决方案时,首先要考虑的就是是自己开发还是使用现有的模块。一旦决定使用现有的模块(包,框架等),那就要进一步考虑究竟用那个。

做这类工作时,如果没有一定广博的知识,做选择的时候就会特别的艰难。

假使说现在公司内部要导入一套项目管理系统,那么做决定的负责人必须至少考虑所有下面这些事情:

  • 自己从头造,还是用现成的做二次开发?
  • 用现成的,是用开源产品,微软的还是其他公司的?
  • 用微软的话,是用MS Project还是基于SharePoint,还是混合?考虑License费用的话真的划算么?
  • 用开源产品,有这么多选项究竟导入那一个?
  • 如果自己从头造,那么是基于微软的技术,还是基于LAMP这样的技术?
  • 使用什么框架?
  • 如果要做,用什么语言?

一个人很难精通上面所有的领域,但当做选择时,完全没有概念也是灾难性的。

此外,考虑博与专平衡点时似乎有一种特例,钻研特定算法的人,从一开始就只往专的方向发展,并不会考虑其他。比如:钻研TTS的人,可能几十年如一日只要专注于TTS就完了。

至于具体选择那个方向,则要根据自身情形来定。总的原则是要以当下工作为根基,以实用为目的甄选各种知识,并追求平衡点。

大致上讲,期望做技术专家的更适合前一个方向,而期望做技术管理的则更适合后一类方向。

学习软件工程的时机与必要性

简单来讲越是没实践经验的人越不适合学习软件工程,越需要规划整体把握全局的时候越需要学习软件工程。

软件工程中覆盖的元素非常繁杂,可以有管理、流程、开发模型、估算、分析设计方法等。这无疑会把知识面扩展的很宽,一旦没有根底,就很容易变成纸上谈兵,夸夸其谈。

在众多软件相关的知识中,软件工程绝对是很特别的一个。很多人很鄙视软件工程,说:我一看到软件工程的书就直接略过;与之相对应,很多人很推崇软件工程,会花很大的心思去研究敏捷、CMMI等。

刚入职场的程序员大致上是讨厌软件工程的,因为这东西离自己的实践有点远,并且主要是添加束缚。但既然更加复杂纷繁的历史都可以总结出规律,忽视软件开发的内在规律无疑的对有志于成为管理者的人是不利的。

真要学习软件工程,不太适合从抽象层次很高的教科书开始,而适合从《代码大全》这样与实际关联比较紧密的书籍开始。

在国内软件工程的落地似乎始终困难,软件工程相关名词始终在不停的变换(ISO,CMMI,敏捷等),但实际能落地起作用的却不多,这最终导致了一种吊诡的局面:刚对一个绝望,就开始对新的一个报以希望,并在这两个简单的步骤上做无限循环。这种状况也许有其更深层次的原因,比如生存压力过于强大导致工程力量的长远价值被漠视,进而使方法论并不为解决现实问题而存在,而是为了证书而存在。很难据此就说软件工程毫无价值。

码路指南:别错过人生中学习的黄金时期

保持知识更新

错过人生中的好时机

没毕业的程序员或者刚毕业的程序员往往感觉空余时间比较充沛,还很苦恼不知道如何打发时间,但实际上一个人一生中可以用于充电的时间远比想的少。一旦错过时机,往往悔之莫及。

对于大多数人而言,人生就像个模板,小处还有偏差,大处却基本相同。

  • 20~30岁这个阶段可以讲是黄金时期,这个阶段里,家庭负担较小,可以自由支配的时间较多。当然撞到了很特别的、需要疯狂加班的公司只能另算。
  • 30岁之后因为娃娃出生等,家庭上的时间开销增加,个人可支配时间变少。其中很大一部分人还有很大可能会面对电视剧里常说的婆媳矛盾,让你每天心绪不宁。
  • 40岁之后,家庭琐事会进一步增加,典型的上有老下有小。实在运气不好的自己也会生点病---颈椎病、腰间盘突出、胃病大概可以入选程序员的三大职业病。
  • 50岁之后,时间上会再次解脱,但可惜的是自己也老了,时机不在。

如果把人生按照年龄画一条抛物线的话,40岁左右一个人可以达到的人生的顶点,未来再突破的几率则变小。从历史人物来看,大器晚成的不是没有,但真的很少。

用心观察就会发现,招聘启示里经常会注明年龄要在35周岁以下或者40周岁以下,除非是招聘高层。这反过来意味着如果没有到高层,人生会在40之前定型,之后有下滑危险(如遭遇不景气、公司倒闭等)。对程序员而言,这种风险尤其的大,因为很可能你辛苦掌握的知识体系被更迭掉了。

学习本身无疑的是需要顺应这种自然规律的。

很多人很大的一个错误在于,在黄金时期,没做什么积累,就顾得享受生活了,而一旦意识到积累的必要性时,却又受困于诸多琐事而欲振乏力,最终人生高度有限,并迅速走低。这就是现代程序员版的“少壮不努力,老大徒伤悲”。

基本上讲,35岁以前要把需要花大量时间,比较硬的技能,学习曲线陡的技能掌握,具备工作所需要的所有主要技能,而35岁之后则主要关注知识的更新和某些软技能。

学习时添水战术效率真的很差,每次点一根火柴烧水,一亿年水也烧不开一壶。同时,比较硬的技能(比如:Donald Knuth的《计算机程序设计艺术》)往往是需要大块时间投入的,但年纪越大时间越呈现为碎片化,越难搞定硬的知识 —— 先天就容易造就添水战术。比较软的技能,则可以用碎片时间来学习,比如:提高PPT的制作水平,提高表达能力。

如果能够安排好自己的时间和软硬知识的关系,那么就可以在特定基础上做积累,小步前进,使自己的价值越来越高。从这个角度看,年轻绝对是一种债务,大多数人必须在他没完全结束前,还掉所欠的东西。

那么具体来讲那些东西是比较硬的,要在35岁前搞定呢?这因目标而异,但下面这些项目应该具有非常高的通用性:

  • 精通一门最常用的语言
  • 了解一个最常用平台的基本机制,比如:内存管理、线程机制等
  • UML图和面向对象分析设计方法
  • 设计原则,如:职责单一等
  • 设计模式
  • 《代码大全》里讲的一切
  • 精读一个知名的,但有点规模的程序。这点上要感谢开源项目给我们提供了这么多优秀程序。但要谨防好高骛远,动辄挑战Linux内核,精读是关键。
  • 累积一定的代码量,比如:独立的完整做过一个数万代码行的东西。这里的关键是完全自己打造,一定不要拷贝粘贴。
  • 掌握基本算法和数据结构(可以不自己写,但至少要知道其复杂度和区别)
  • 养成一种清晰的编码风格
  • 有自己的专业(金融、高并发网站,图像处理,TTS等)

学习英语的时机和必要性

总的来看,程序员学习英语是一项投资回报率相对比较好的投入。从目标上来看,程序员未必一定要口语流利,但最低要达到阅读英文资料没有障碍的程度。这里面有一个微妙的事情,一旦英语阅读问题较大,查找问题会习惯用百度,这天然会限制一个人的视野。不是说百度自身有多不好,而是说英语的世界里有着更多更精彩的内容。

不管喜欢不喜欢,我们必须承认一种现实,在IT的世界里英语是一种世界语,一方面是由于美国公司的强大,一方面则是由于开源选择了英语。这最终导致IT世界里的新动向、解决问题的小技巧、网站的架构等等都要到英语的世界里去找。在StackOverlow很容易找到各种小问题的答案,在Quora则很容易找到各种网站的架构。

从学习时机来看,这件事情特别应该在大学里面搞定,如果不行至少也要在毕业1~2年内达到阅读无障碍的程度,当然希望加入外企还需要额外的付出。从学习方法来看,学习外语真没什么特别的窍门,坚持并投入时间即可。

停止知识更新

对程序员的增值而言,人生里最大的陷阱也许是为安全的假象所欺骗而彻底的放松自己。这种状况在生存环境比较恶劣的情形下不太会发生,但在垄断企业或某一领域中绝对领先的企业里则容易滋生。发现自己是否停止知识更新了并不困难,比如:一年一本书没看,一年一点新知识没接触,一年中工作负荷基本不满等都可以成为一种信号。

这真的是温水煮青蛙,一旦到了三十几岁,并在这种环境中呆习惯了,那么再想跳出来,基本没可能。唯一能做的事情是,祈祷公司不要挂掉,公司也不要来场运动,进行人员的大换血。孔夫子说:日当三省吾身,这是很有必要的,至于认识危险后能否做点什么,那就是事在人为了。

1. 技术人员的知识更新

接触一个新的岗位后,大致要经历一个学习并逐渐胜任的过程,这个时间段里大多数人的学习热情是很高的。一旦基本胜任之后,事情就有了变化。

很大一部分人可能会感觉,反正工作也就用到这么些知识,学习其他的也用不上,因此开始把自己封闭起来,不太看书,不太看技术新闻。

这其实很危险,因为这种做法等于把自己绑死在当前这份工作上。而任何一个产品都有自己的生命周期,一旦一个产品的生命周期结束时,碰巧其所用的技术也已经过时,那么当事人就会很尴尬。因为产品可以结束,生活却还得继续。

这里面一个非常经典的例子是MFC。微软的这款产品的历史非常悠久,从1992年发布到2012年几近存在了20年时间。随着90后程序员的逐渐出现,马上这款技术就要变得比程序员的年纪还要大了。

即使到今天,很多桌面应用仍然是基于MFC开发的,这可以通过查看程序包的dll依赖来很容易的进行验证。MFC是一个很大的池子,有深度、有历史。想把MFC的类继承关系、消息机制、框架结构、RTTI、序列化都搞清楚还是要很花一点时间的。

现在我们假设一款庞大的企业应用是基于MFC开发的,一个程序员也通过几年的努力了解了MFC,了解了应用本身,并可以负担起Bug修正,新功能追加等任务了。

接下来这个程序员似乎没什么好学的了。因为MFC的更新几乎已经停滞,因此对MFC的学习几乎不需要花太多的时间了。现有代码也理清楚了,也不需要再花很多时间学习了。现有程序也比较好的满足了企业的需求,推倒重来的可能性几乎没有。

那这个时候这个程序员不需要学习了么?答案一定是否定的。这里面蕴藏着一个天大的矛盾。

从企业的角度看,一定是需要一个团队来维持这个程序的开发的。但从个人的角度看,如果把所有的青春都耗费在老技术上,那么一旦老技术退出历史舞台,个人该何去何从?

还是上面的例子,假设说一个人持续投入在这类开发上,当他45岁的时候,当前产品生命周期结束,世界变的只有移动开发和云端开发,那么只擅长MFC的他该何去何从?

如果真的如此,这个人就被逼到了死角里,人生很可能产生巨大滑落。所以一定不能认为所学足够而停止技能的更新与学习。

从具体应对措施来看,一是要参照知识的地图,横向扩展知识的广度,比如不只要盯着代码,也要了解业务;不只关注开发也关注一点估算;二是提升可流动性比较好的东西的掌握程度,比如:面向对象分析与设计,这样跨越到其他技术时就能够比较平缓的进行过渡。三是要争取轮换岗位,争取多种实践机会。

2. 管理者的知识更新

到现在为止大部分人认同,管理者是需要懂技术的。从逻辑上看“懂”基本上是不瞎指挥的前提,所以这可以称为中国版的“现场主义”,估计争议不大。

那关键问题就是究竟要“懂”到什么程度?

如果说两个人,一个选择了管理方向,一个选了技术方向。接下来要求管理方向上的人技术水平要和技术方向的一样,那么除非这个人特别天才,否则不太可能。正像前面所说,这是由于这两个方向的“Key”不同所造成的。

如果把目标设定为确保最终产品的成功,同时假设管理者有更高的决策权,那么管理者必须在下面这些方面有技术感觉。

从做产品来看,要想成功,有两个关键维度需要同时进行把握,一是产品的概念完整性的把握;一是用合适的手段去实现这个产品。

前一个话题很老,《人月神话》就有提及,但实践中却总是被人忘记。好的产品必须贯彻某一种统一意志,iPhone、微信又重新验证了这一个老的原则。 机械拼凑的产品虽然融合了很多人的想法,但往往是平庸的,并且在项目执行过程中,往往是出错的根源。很像是虽然有法律,但每个人有自己的理解,各行其是这样一个状态。这种概念完整性是管理者第一个需要有所把握的事情,其次就是解决如何去构建产品这个问题。为达成这一目标在下面这几个方面上,管理者要有自己的理解,至少要有自己的原则:

下面简单列举几个比较关键的考量,这和前面论及的如何往博的方向发展有点重叠:

  • 使用现有产品还是自己开发
  • 比如:那些模块适合自己搞定而那些购入就可以了。购入的时候要遵循怎么样的标准去选择。
  • 使用那种平台技术
  • 比如:是使用微软的技术,还是开源的技术。
  • 现行架构是否可以达成产品目标
  • 比如:在硬件加软件可以同时支撑的并发数目。
  • 代码可维护性如何约束
  • 这要求必须熟练掌握一些原则性的东西,比如:什么信息隐藏、正交分解、抽象是否充分等。以及一些无歧义指标,比如:圈复杂度,单元测试的收益平衡。
  • 那些环节必须固化为流程,那些一定要团队自由决定
  • 比如文档化要到什么程度才合适,不同阶段间什么是必须的输入输出。
  •  ... ...

假设说有人不这么认为,而是在做了管理后,表现出足够的惰性,不再持续更新自己的知识体系了,那么会发生什么事情?

这时候会很可能会管理倒置。即管理者是名义上的上级,但基本失去对现场的把握,所有的决策完全依赖于下属。得力下属不在,各种决定就只能靠瞎蒙,最终变成只会沟通的管理者---即使被食人族吃了也不会有人注意到,因为存在价值已经被无限稀释,变成了一个象征性的符号。也可能会和下属爆发激烈冲突。因为这类管理者没有自己的立场,上面有任务只能下压。结果同实际情况偏离万里,不具有可实现性,这类管理者无法对自己的上司陈述,也就只能向下转移压力。

不管是那种,一旦到这种地步,其实是趋于失败,只能祈祷食人族不要来。

为什么中层管理者也要坚持知识更新?

在IT行业流传着一个很有名的关于食人族的笑话,这个笑话说的是:

两个食人族的人应聘进了某家大公司,公司人事主管知道这两个这伙每天都要吃人,于是警告他们:“如果你们胆敢在公司吃一个人,你们就会立即被炒掉!”两个食人族唯唯喏喏地答应,表示绝不会在公司吃人。两个月过去了,公司平安无事。

突然有一天,公司发现负责打扫公司卫生的清洁工不见了。于是人事主管非常气愤,找来两个食人族怒斥,并当场炒掉了他们。出了公司大门,一个食人族马上对另一个抱怨起来:“我一直警告你不要吃有在做事的人,你就是不听!我们两个月来每天吃一个经理,没人发现。你看现在吃了清洁工,他们马上就发现了!你真是个猪!”

这个笑话嘲讽的是某些大公司大企业病发作,人浮于事。大企业病的成因很难一下子说的清楚,但结果却比较明显,一定会导致较多人成为中层管理者。如果说成功的企业天然有感染大企业病的趋势,那无疑的中层管理者也天然有着膨胀趋势。从个人角度看,成为被食人魔吃掉也没有人在意的经历并非是什么好事,因为这意味着存在价值减弱,也不需要什么知识更新。一旦面临裁员这类事情,这个人很可能已经失去了面对残酷竞争的能力。

码路指南:物质驱动与兴趣驱动

编程驱动力是什么?

在国内普遍有一个很特别的现象:高中像打了鸡血一样使劲学习的人,到了大学往往会放松下来,跑去享受生活了,大学里打游戏、打牌、临考冲刺的大有人在。

这倒也在情理之中,高中不学真考不上大学,考不上大学真就完蛋了;大学不学,只要能毕业,大致还能找到工作。但人生是场长跑,稍一停顿,后面的人就嗖嗖的窜到你前面了,虽然你不一定能看得到到底是谁。这很像龟兔赛跑,但为了避免不成为那只兔子,单靠口号层次的主观意愿是不行的。

停下来的人其实很多,有的人停在了大学里,有的人停在了小有成绩之后,而为了持续前行而成为高手,那首先要给自己找个动力源,而要想找到动力源,那么首先要拷问自己的内心,知道自己为什么上山学艺,为什么要成为高手。

纯物质上的驱动力

如果回看历史就会发现历史记下名字的人(孔子、商鞅、汉武帝、李白、王安石等等),往往具有一个共通的特征:他们具有澎湃的生命力,绝对不是每天混混日子的人,虽然生命力的表现往往不同。

这似乎和好人坏人,理想高尚与否无关,必须的只是这个人要有所执著,并持续的运用你的脑力、体力去做某件事情。而一个人要想有所执著,那就必须有一种持续存在的驱动力。

在这个时代里,对于大多数人而言第一驱动力无疑是物质及金钱,但这似乎只可以做起点而不能做终点。这就和梁山好汉一样,最开始没准只是为了大碗喝酒,大块吃肉,可聚了义之后,则要考虑替天行道,除暴安良这类比较高端一点的事情了。

组织行为学中的研究佐证了这一结论,美国人的研究显示,当年薪超过40000美元后,薪资将不再是工作满意度的核心支撑因素。在中国估计相差不大,20万以上年薪的人,往往需要寻找其他的驱动力。否则这个时候程序员会处在一种瓶颈状态:基本物质需求得到满足(比如:住房、汽车等),但更高一层的物质需求又很不现实(比如:别墅、游泳池等)。

这个时候单纯的物质支撑会让生命力变的萎靡,人也就会变得无可无不可,工作中即不会很高兴,也不会很不高兴,每天也只是例行公事。接下来人生就会开始下滑,倒霉的话还会失业。等到困境真的来了,再想振作,却没那份儿心力了。

在2012年11月,新闻报导百度总裁李彦宏在公司内呼唤狼性,排斥小资。具体来讲,呼唤的是敏锐的嗅觉、不屈不挠奋不顾身的进攻精神,群体奋斗,排斥的是信奉工作只是人生的一部分,不思进取,追求个人生活的舒适的态度。这事情的是非很复杂,这里略过不提,反倒是百度这一行动本身说明公司里确实容易存在一种生命力萎靡的状态,这点甚至让CEO忍无可忍。

兴趣的力量

如果说纯物质上的驱动有一定局限性,那么兴趣又如何?

当问及一个人为什么从事软件开发时,很多人会回答是:兴趣。但人们这么表达的时候可能并没有意识到常说的这种兴趣是一个不怎么靠得住的驱动力。这种兴趣往往是一种一时的好奇心,而不是与自己性格特质相契合,可以用来给生命解闷的那种兴趣。

总的来看,兴趣可以分为两个层次:一个是浅层次的。比如看到一个游戏比较酷可能想玩玩,看别人写博客,自己也写几篇;另一种则是深层次的。比如:爱因斯坦你不让他思考,他可能感觉活着就没什么意思了。

找到后一种兴趣的人是幸运的,但大多数人并没有这么幸运,所以一般所说的兴趣都是前一种,尤其是即将毕业和刚毕业不久的人。

真正做软件产品的时候,牵涉的往往是大量比较繁琐的细节,大多时候脏活、累活、苦活远比看上去风光的活,有趣的活多。具体一点讲就是,可能需要面对比较垃圾的既存代码,可能要面对不怎么负责的同事,无理的需求变更,十分紧张的日程等。除非你做的是很高端的研究。

这些东西本身并非是很有趣的,它们很快会让初始时的一点夹杂着好奇心的,浅层次的兴趣消耗殆尽。最初印象和实际的偏差很可能是造成某些程序员提前退场的一个主要原因。

这种原生态的兴趣消失后,又没有其他支撑点的话,人就越来越会像机器人,并可能会厌恶自己的生活。因为每天大部分时间都花在工作上,而工作本身又是如此的无聊。所以故事到兴趣这里并没有结束,还需要继续找寻驱动力。

当然很可能以兴趣为出发点而找寻其他,最终反倒又回到起点,这是人生常态,倒不值得惊讶。

兴趣、体力与智力

人和人之间的体力往往相差不大,但智力的差异却往往不可以道里计。所以一个经验丰富的老农半天种一亩地,一个不太熟练的忙和一天大致也可以搞定一亩地。

纯体力上不太拉得开人的差距。而智力则不一样,人的智力容易有数量级上的差异。前苏联著名物理学家、诺贝尔获得者朗道将世界上的物理学家从一级到五级分为5个层次,每个层次的贡献差一个数量级。朗道认为自己是2.5级,获得诺贝尔奖后,才把自己生为1.5级。就不用再考虑5级的物理学家和普通人的差异了。

我个人感觉,越是靠近体力一端的工作越不可能兴趣驱动,而越靠近智力一端的工作越可能是纯兴趣驱动。恰如我很难相信干重体力活的人是因为兴趣一样,我也很难相信爱因斯坦不去做以色列总统而选择继续研究物理不是因为兴趣。

程序员的工作在这两个极端间,所占跨度较大,但产品开发也许是中间偏左,完全的兴趣驱动估计很难。即使是兴趣驱动,也不是我喜欢游泳,我喜欢吃小笼包这个层面的兴趣。

物质驱动和兴趣驱动,看起来貌似都不是特别靠谱,那么什么驱动力才能使人生永动呢?


码路指南:保持内心的青春与理想

理想驱动编程

如果说物质和单纯的兴趣不足以成为一种长久的驱动力,那么无疑的我们需要继续去寻找一种可以使人生永动的势能。

很多一部分程序员其实是认识到了技术更迭这样的特征时刻在掏空自己立足的根基的,但很多的人在这种时候并不是采取积极的态度去面对,而是会试图欺骗自己,给自己一种安全的假象。比如可能会告诉自己,反正公司短时间没问题,把手里的事做好就行了。让自己那么辛苦干什么?这在某些有点年纪生活相对安稳的程序员身上比较常见,这很可怕,有时候会把自己逼到死角里。摆脱这种状况当然需要一定的危机意识,但更关键的是要找到一种使人生永动的势能。

据说美军的麦克阿瑟将军非常喜欢一篇名为《青春》的散文,在占领日本期间日本人在美军总部发现了这篇散文,于是这篇文章很快变得很流行,在商界大佬(如松下幸之助等)间流传甚广。那《青春》这篇散文说的究竟是什么呢?我们来一起看一下:

青春不是年华,而是心境;青春不是桃面、丹唇、柔膝,而是深沉的意志,恢宏的想象,炙热的恋情;青春是生命的深泉在涌流。 

青春气贯长虹,勇锐盖过怯弱,进取压倒苟安。如此锐气,二十后生而有之,六旬男子则更多见。年岁有加,并非垂老,理想丢弃,方堕暮年。 

岁月悠悠,衰微只及肌肤;热忱抛却,颓废必致灵魂。忧烦,惶恐,丧失自信,定使心灵扭曲,意气如灰。 

无论年届花甲,拟或二八芳龄,心中皆有生命之欢乐,奇迹之诱惑,孩童般天真久盛不衰。人人心中皆有一台天线,只要你从天上人间接受美好、希望、欢乐、勇气和力量的信号,你就青春永驻,风华常存。 

一旦天线下降,锐气便被冰雪覆盖,玩世不恭、自暴自弃油然而生,即使年方二十,实已垂垂老矣;然则只要树起天线,捕捉乐观信号,你就有望在八十高龄告别尘寰时仍觉年轻。 

—— 塞缪尔-厄尔曼德

文字非常优美,但意思并不深奥。青春是一种进取的精神,是一种远离颓废追逐理想的状态。我个人非常认同这种观点。

人的思维和欲望具有无边界特质,只要在未来和现在之间制造一种差距,那么就会产生无尽的势能,人也就会不断的前行。而制造这种差距的最佳素材往往只能是理想

大多数人可能误解了理想和道德间的关系,但实际上理想并非是一个高尚的词汇,与善恶无关,更与宏大与渺小无关。

鲁智深说:平生不修善果,专爱杀人放火,这也可以是种理想,只要你可以承受它所带来的负能量并不感到痛苦。物质需要、成就需要、权利需要、归属需要这些动机理论中经常提到的东西,乃至前文提到的兴趣都可以成为理想的素材。所以反过来讲,理想是什么似乎并不关键,关键是要有,并且你真的可以很狂热的投入去做,这就可以产生一定的势能。

对与天生对代码狂热的程序员而言,这并不是什么问题;但对大多数人这种理想往往并不在程序之内,而在程序之外。这时候很可能需要叠加几类东西才能给自己蓄积足够的势能:物质的需求、成就的渴望、不安全感的驱离、技术上的追求等都是不错的素材。

当然这是个人的私有领域,最终只能由个人做出选择。 

这里最后想说的是有理想、有斗志不一定会成功,但无理想、无斗志几乎一定会铸就平庸和失败,因为细致想来世界本身归根到底是理想主义者的。

这可以通过一个简单的逻辑游戏来做点证明:

意识决定行动:个人意志决定个人行止,组织意志决定组织行为 → 理想主义者个人意志更为鲜明,自我意识强烈,而无理想的个人意志薄弱,愿意随波逐流 → 意识强者上位 → 处于组织核心地位的是理想主义者 → 无理想的人不论在个人层面还是组织层面都沦为追随者 → 从资源掌控的角度看理想主义者掌控世界。

对这事而言,理论其实不关键,选择与坚持非常关键,但还是把它们放在这里,供大家参考。

动机理论与人生势能

如果把我们前面提到的“势能”做细致分解,那么你可以得到各种各样的动机理论。动机理论却真的可以解释现代人种种行为,因此在这里对其做一点介绍。

1. 马斯洛的需求层次理论 

动机理论里最有名的可能是马斯洛的需求层次理论,即:

  • 生理需要:包括觅食,饮水,栖身,性和其它身体需要。
  • 安全需要:保护自己免受生理和情绪伤害的需要。
  • 社会需要:爱、归属、接纳和友谊。
  • 尊重的需要:自尊、自主和成就感;地位、认可和关注等。
  • 自我实现的需要。

2. ERG理论:

  • 存在需要(Existence):与马斯洛的生理、安全需要相似。
  • 关系需要(Relatedness):与马斯洛的社会及地位需要相似。
  • 成长需要(Growth):与马斯洛的自尊及自我实现需要相似。

3. X理论和Y理论:

X理论持下面四种假设:

  • 员工生来不喜欢工作,只要有可能,他们就逃避工作。
  • 由于员工不喜欢工作,因此必须采取强制和控制措施,或采用惩罚威胁他们从而实现目标。
  • 只要有可能,员工就会逃避承担责任,并寻求正式的指令。
  • 大多数员工把安全感视为高于其他所有工作相关因素,并且没有雄心壮志。

与之相反,Y理论持四种积极的人性假设:

  • 员工视工作如同休息、娱乐那样自然。
  • 如果员工承诺完成某个目标,他会进行自我引导和自我控制。
  • 通常人们都能学会承担责任,甚至会主动寻求责任。
  • 人们普遍具有做出创造决策的能力,并不仅仅是管理者才具备这种能力。

如果把X理论和Y理论对应到IT行业,那么提倡人件和敏捷的基本是基于Y理论,而提倡CMMI和大棒加胡萝卜的基本是基于X理论。

4. 双因素理论(two-factor theory)

也被称为激励-保健理论(motivation-hygiene theory)。这个理论认为激励和让人不烦(保健)是两码事情。满意与不满意不是对立的两极,满意对立的是没有满意,而不满意对立的则是没有不满意。简单来讲管理质量、薪金水平、公司政策、工作环境这些被认为是保健因素,他们不产生满意,只产生不满意或没有不满意两种状态。要想激励员工必须在晋升、个体成长上有所作为。

5. 麦克莱兰的需要理论

这个理论把人的内在需要归为三类:成就需要、权利需要和归属需要。成就需要是一种追求卓越、获取成功的需要。权利需要则是一种控制他人行为的需要。归属需要则是建立良好人际关系的需要。

6. 认知评价理论

这个理论比较神奇。他认为工作本身的乐趣是已经是一种内在的奖励,而外部奖励反倒会降低动机的水平。这听着比较抽象,但意思是如果总是用奖金配合绩效考核来激励员工,那么个人由于兴趣而从事某项工作的动力就会降低。这很难理解,但确实也有证据来支持这个理论。

7. 目标设置理论

由于很多公司会做目标管理,所以很多程序员对这一理论反倒不陌生。这一理论大意是说:明确而具体的目标有助于提高个人效能,目标的挑战性、针对目标的反馈都在此基础上进一步提高目标的效果。

8. 自我效能理论

这个理论走到极端就是常说的“人有多大胆,地有多大产”。大意是说一个人对自己有能力完成某项任务的信念越强,那效能越高。或者简单说就是自信很重要,而促成自信的方式可以是:过去的成功经验、从榜样吸取力量、受到言语激励等。

9. 公平理论

公平理论是说一个人总是会拿自己的产出收入比和另一个人比较,如果比率相似,那么人们会认为环境是公平的。

这落到个人头上,就是我们要重视这种差异么?都是同样的学校、同样的智商、同样的家庭背景,如果一个人收入等比你多很多,你在意么?

10. 期望理论

这种理论把人的动机分解成几个部分:一是如果我努力了,那么这种努力能否在绩效评估中表现出来?二是如果我获得了良好的绩效评估,那么能否得到奖励?三是即使我被奖励了,这东西是不是我想要的。

这些动机理论从公司的角度看是激励员工的方法,从自己的角度看则是努力前行的动力。我还是上面的观点,这些理论知道就可,但如果无法找到对自己内心进行触动的点,理论在这里并没有很大的价值。如果想进一步了解,则需要阅读组织行为学相关的书籍了。上面的内容则主要参照了人民大学出版的《组织行为学》一书。

最后想说的是单纯从境界上来说似乎有一种精神远远超出动机理论所能涵盖的范围,这种澎湃的生命力和永不屈服的精神,虽然年代久远,乃至失去传承,但这种精神却正是上古华夏民族所身体力行的精神。

何新先生为自己国学经典系列写了一个总序,对此进行了很好的描述,他说:

华夏民族的先史中有一个神话时代。这个时代实际就是华夏民族肇始和文明滥觞的英雄时代。

女娲是敢于蹈火补天的英雄。伏羲、神农、黄帝、炎帝、蚩尤、大禹,或创世纪,或创文明,或拓大荒,或开民智,或奋身为天下法。

鲧与大禹父死子继,以身济世,拯黎民于水火;蚩尤共工九死不悔,虽失败而壮志不屈,天地为之崩陷。

夸父逐日,体现了对神灵的藐视。而精卫填海,则表现了对宿命的不驯。

由此观之,中华民族的神话先古时代,实在是一个群星灿烂的时代,慷慨悲壮的时代,奋进刚毅的时代;是献身者的时代,殉道者的时代,创造英雄和产生英雄的时代。

传说中华民族是龙和凤的传人,而龙凤精神,我以为就是健与美的精神。 

我个人总是感觉很难用动机理论去解释这种宏大且壮阔的精神。 

小结

IT这个行业确实是年轻人更容易出头的行业,如果不信,去看看腾讯和银行高层的年龄吧。一个企业兴起的时候往往会带着一批人走上成长的快车道。在这类企业里没有太多的历史包袱所以占据高位的往往是些年轻人,这和有个几十年历史的行业非常不同。

而为了达成这一目的,程序员首先必须有效的持续增值并成为某一方的高手(架构师、Guru或者优秀的管理者)。单纯从技能上讲,你一定不能和金字塔最底层的百万大军竞争,想象一下一个刚学会某门语言的人和一个每天思考虚拟机原理与设计、设计跨平台系统的人有多大的差距。而从公司的角度看,高手则意味着可以为公司在现在或将来创生较大价值。

想成为高手就需要选定一个大致的方向,持续深化,并避开学习路上的诸多陷阱,如:失去焦点、分离学习与实践、过散而不专等等。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值