转:编程的起点和可能的失足
转自:http://blog.csdn.net/leezy_2000/article/details/33349965
编程的起点和可能的失足
从大环境来看,想不写程序直接去做管理工作是很难的。大多时候都要在开发上做出一定成绩,接下来才有选择技术还是管理的机会。因此即使是希望选择管理方向,技术上的基本功还是需要的。所以下面这节的内容和选择做管理方向还是技术方向关联不大,只要是想做程序员,大致上都有必要一读。
从那里开始编程生涯
大学里经常会开设软件工程专业,在这门课程里面大多时候会讲解需求工程、开发模型、设计方法、项目管理等。但很多同学会感觉这课程让人摸不着头脑,认真学也学不到什么。从这种普遍现象可以发掘出一些本质问题。
这里的本质问题是指软件开发是实践性非常强的科目,因此不适合先从概念开始。这不意味着软件工程、设计思想不重要,而只是说不适合从纯粹的概念开始学习编程。
在软件这个行业里,很多比较资深的人员对如何学习编程是有统一认识的:学一点,实践一点,再学一点,再实践一点。但困难的是每个人对每次迭代的“一点”究竟是多少认知不同,对“一点”是什么的定义也是不同。
我个人的观点是以3000代码行为界算第一个一点,也就是说一个人学会某个语言后小练习不算,先完成一个3000代码行左右的,没有UI的独立程序。为解释什么叫独立的程序,举一个具体的例子。
在《敏捷软件开发:原则、模式和实践》一书中有一个薪水支付的例子程序,正好是这个规模,很适合帮助达成这一目的。这个程序的基本规格说明是:
(下文引自《敏捷软件开发:原则,模式与实践》)
- 有些雇员是钟点工。会按照他们雇员记录中每小时报酬字段的值对他们进行支付。他们每天会提交工作时间卡,其中记录了日期及工作小时数。如果他们每天工作超过8小时,那么超过的部分会按照正常报酬的1.5.倍进行支付。每周五对他们进行支付。
- 有些雇员完全以月薪进行支付。每个月的最后一个工作日对他们进行支付。在他们的雇员记录中有一个月薪字段。
- 同时对于一些带薪(Salaried)雇员,会根据销售情况,支付给他们一定数量的酬金。他们会提交销售凭条其中记录了销售的日期和数量。在他们的雇员记录中有一个酬金字段。每隔一周的周五对他们进行支付。
- 雇员可以选择支付方式。可以选择把支付支票邮寄到他们指定的邮政地址;也可以把支票保存在出纳人员那里随时支取;或者要求将薪水直接存入他们指定的银行账户。
- 一些雇员会加入协会。在他们的雇员记录中有一个每周应付款项字段。这些应付款必须要从他们的薪水中扣除。协会有时也会针对单个协会成员征收服务费用。协会每周会提交这些服务费用。服务费用必须要从相应雇员的下个月的薪水总额中扣除。
- 薪水支付程序每个工作日运行一次,并在当天为相应的雇员进行支付。系统会被告知雇员的支付日期。这样它会计算从雇员上次支付日期到规定的本次支付日期间应付的数额。
在学完编程语言、面向对象、UML之后可以先参照这份规格说明,什么例子程序都不看,自己完整的做一份实现,实现中要包含UML图和代码,接下来可以去把Robert C.Martin的例子程序下载回来,同自己的实现在设计上和实现细节上做详细的比较,找出那点自己好,那点Robert C.Martin的好。这样对编程语言、对面向对象、对设计原则就可以有比较踏实的一些理解。此外,这个程序的一个额外的好处是它可以完全独立于平台,只依赖于语言和标准库即可。
假设说一个新手已经熟练掌握了一门语言,那么完成上述的任务估计需要2~4人周,当然有经验的人1个人周左右已经足够了。
在此之后,可以精读一个上点规模的(1~5万行最佳)独立性比较强的应用程序,由于已经上了规模,做到完全的与平台相隔离就有点难了,没法提供统一的例子作参考。但选择标准主要有两个,一个是尽可能和自己未来期望的方向相吻合,一个是尽可能比较独立和经典。独立的目的是方便调试,经典的目的是确保代码质量。比如:如果是Windows本地应用就可以考虑Notepad++类的开源应用,Web应用就可以考虑WordPress等。这个时间点上需要避免好高骛远,Linux内核与Chrome当然很好,但它们并不适合初学者的。
在精读过程中可能需要几类书籍:一是平台框架相关的(线程机制等),一类是模式相关的,一类是工具型的书(如何调试)。这个时候是要耐下心来读几本比较经典的书的。
精读之后,就要再找到一个项目来实践。这里的关键是真的项目,至少要有真的用户,并且用户数目越多越好。最好是能够向知名开源项目提交代码。
各种基础知识中比较例外的是计算机体系结构、数据结构和算法这类理论性比较强的东西,这种学习曲线比较陡的东西需要结合大学的课程把它学会,接下来再在实践中逐渐应用,而不能一边做事一边学习。原因是学习曲线越陡的东西越需要大块时间,毕业之后再学效率会差。
总的来看,上述几个步骤,应该在大学毕业后2~3年内完成,最好在大学里完成,这样可能会有点优势。这些完成之后,打基础阶段可以算是基本结束。
打牢根基 VS 速成道路
有很多不同的方法可以学会编程,比如说:一个人既可以先打牢基础,接下来再逐步学会如何进行各种开发工作;也可以不管三七二十一,先借助各种IDE把程序做出来再说。上一节主要介绍的是先打根基的方法,而不是速成的方法。
相对于打根基的方法,后一种学习方法更容易在短时间内看到效果,所以很多人都是这么入的行,比如:先从IDE开始,接下来再从表面往本质去学,逐步去了解控件拖放背后所隐含的东西。这不能说完全不好,但我认为这是一种失足,几乎一定会催生程序员只能吃青春饭的结果。
在刚开始编程的时候,如果形成对IDE的过度依赖,那就会导致根基浅薄,能做的事很可能被限制在某个有限的范围内。当下的大多IDE功能已经非常强劲,这对提高产品的生产率无疑是非常有必要的,但在学习阶段,则要尽可能避免过度依赖于IDE,避免用各种控件来快速完成任务。
比如说:微软在Visual Studio 2012里面内置了一种名为LightSwitch的技术,基于这项技术,一个人可以在基本不编码的情况下,完成信息系统的开发,并支持相对比较丰富的功能(增删改查,搜索,排序等)。无疑的基于这样的工具做开发速度会快上很多,但在学习阶段过度使用这类工具,却会毁了一个人的根基。
想象一下,在使用LightSwitch的过程中一个人会学到什么?他所能学到的主要是这种工具的使用方法,既不会学到SQL语句,也不会学到数据库表格的设计方法,也不会学到ASP.net的基本架构(虽然ASP.net已经封装了非常多的东西)。这样一来,这个人虽然能够快速的完成某个工作,但却给自己埋下了很深的隐患---他很容易的被束缚于某个工具,并且无法应对新领域。
善用IDE集成好的功能进行快速开发不是学习阶段应该做的事情,学习阶段最根本的目的是打基础,把一门语言学精,把一种设计思想学精,把一种算法学精等等,这种基础可能不直接表现为生产力,即使把算法学精了,可能还是无法立刻写出来比较炫的程序,但这有助于面对不停变化的世界,这与单纯的达成某个目的,完成某个程序不同。这可以类比为打地基与盖楼,地基部分显然不能单独进行销售,也不能住人,但没有地基也就没有其上几十层可以高价售出的住宅,楼越高,地基也就越深。当然,只盖地基或者让五层楼和五十层楼使用一样的地基也没必要,这不用多说。
那具体来讲,那些东西可以被认为是编程的根基,需要在学习阶段扎实的掌握?下面将通过推荐几本书(或者说几类书)来描述一个共通于所有程序员的最小集合。
- 计算机体系结构
这一类别下最具代表性的书籍是《深入理解计算机系统》,作者是Randal E.Bryant和David O’Hallaron。读这本书的目的是了解计算机到底是怎么个东西,软件到底运行在什么样的基础之上。
- 算法和数据结构
这一类别下最具代表性的书籍是《算法导论》,作者是Thomas H.Cormen,Charles E.Leiserson,Ronald L.Rivest,Clifford Stein。读这本书的目的是了解软件到底可以用什么样的手段干些什么事情。软件是一种工具,可以帮助解决人类面临的许多问题,而主要手段则只有两种,一种是这本书里所介绍的算法和数据结构;另一种则是下一类别中所涉及到的分析和设计方法。它们像小刀子一样,可以把各种领域中的各种问题进行分割,并映射到程序的世界里来。
- 设计原则和模式
这一类别中比较有代表性的书籍是《敏捷软件开发:原则、模式与实践》,作者是Robert C.Martin。读这本书的目的是了解数据结构和算法之外另一种对现实问题进行抽象的方法如面向对象以及进行这种抽象时所要遵守的原则。
这类书籍经典的还有很多比如:GoF的《设计模式》,而之所以选择上述这本是因为这本书里提供一些比较完整的例子,更适合初学者一些。
- 软件工程
这一类别中最具代表性的书籍是《代码大全》,作者是Steve McConnell。读这本书的目的是建立对软件开发的全局视图。知道一个软件从无到有所要经历的一系列过程。
软工的书还有很多,比如很有名的《人月神话》,但《人月神话》类书其实对很多人是不适合的,对初学者就更不适合。
上面四本书是一个最小集合,针对不同场景需要进行不同的增加,比如可能需要进一步了解某种框架的机制,那就需要读《XX技术内幕》这类书。但即使是读这几本书也不适合只读书而不动手,最好是穿插在上一节中提到的实践中来读,否则的话对后两本的理解会有所欠缺。
如果想走厚积薄发这条路的上面几本书是一定要预先读通的。阅读过程中,如果发现有些细节问题彻底无法理解,那就要在实践过程中进一步琢磨,找到自己的答案。读这类书时,有一件事情一定要有心理准备:虽然这些书读通并不容易,很花时间,但想读了这些书后立刻写出来一个能卖点钱的工具是不太可能的,这真和大楼的地基一样,没什么立竿见影的效果。如果想尽快达成后者这样的目的,那很可能就要走速成的道路,去读些介绍IDE怎么用,某个框架怎么用的书,比如:《C#高级编程》这类。
为避免误解,有一点需要额外进行一点说明。前面强调的避免过度IDE依赖主要是指不要用封装良好的模块来取代对基础知识的学习,不是说不需要建立自己的工具箱。查找工具、调试工具(进程线程查看等)、二进制数据查看工具、正则表达式工具、持续集成工具、文档生成工具(JavaDoc)、正则表达式工具等对一个程序员的生产力是非常有帮助的,应该在学习过程中逐个掌握。软件开发工作发展到现在,任何一个类别下面都有相当多的比较成熟好用工具了,关键是选定一个把它用熟。