工程和单个文件的关系

有一件很明显的事情,当软件项目变得很大的时候,仅仅使用一个文件来完成所有的内容是不现实的。以《魔兽世界》这款游戏为例,游戏中需要声音、动画、图片这样的素材,也需要地图编辑、人工智能、光影渲染这些不同的模块,在制作的时候,需要有不同的部门完成不同的工作,工作中所使用的文件和工具都不相同,不可能生成同一个文件。这时,就存在一个协调的问题。因此,对于大型的开发工具来说,它们不是以单个文件为单位进行处理的,而是以项目为单位。一个开发项目包含一个到几个工程,每个工程都包含有大批的文件,有源代码,有程序所使用的图片音乐等资源,还有编译时需要记录的各种参数。每次编译都要完全编译整个工程(当然在优化状态可以只考虑更新变动的部分)。

显然工程对于类似《魔兽世界》这样的大型项目的编写是十分必要的,但在新手练习的小程序上,使用工程就像你只想在家给你的小狗搭个窝,却拉来了整个中国长江三峡工程开发总公司,实在有点小题大做。而且,以后我们要编写很多这样的小程序,如果每一个都新建工程,那会生成多少垃圾文件啊!所以,我们需要一种只编译单独文件的方法。幸运的是,不论哪种开发工具,它们都提供了这样的方法。虽然这种方法通常不会在菜单上直接出现,但它确实是常用和正确的方法。

函数、API、类、控件、开发包与软件复用

还有件事也很明显,随着工程项目的越来越浩大,每一次都从零开始编写一个项目是不经济也是不现实的。我们注意到,不论是程序还是源代码,都有以下两个特性。第一,它们都是人类智慧的成果,每一行源代码都凝聚了程序员的聪明才智,花费了开发者的时间和金钱。第二:几乎每一行源代码本身都可以毫不费力的零成本的被复制到另一处,另一个代码块、另一个程序甚至另一个项目。基于这样的特性我们认识到:如果能够重复利用已经编写过的程序和源代码,尤其是那些在使用中已经被证明健壮而正确高效的程序,就能够节约巨大的人力物力财力和时间。即使只能使用其中的一小部分,也是了不起的成就,这就叫做软件复用。

软件复用最重要的好处就是能够让程序员不再把有限的智慧放到早已解决过的问题,而是投身新的问题,也就是:不要再重复发明轮子。开放源代码的一个重要理由就是为了软件复用。软件复用的一个行之有效的方法是使用函数。所谓函数,就是把一些具有固定功能的代码段组合在一起,并给予一个名字。在需要这些功能的时候,只要在适当的地方填入函数的名字。在编程时使用函数而不是纯粹手工打造,就像在盖楼时使用砖块而不是用粘土堆砌——已经是不小的进步了。盖楼时使用的砖块,既可以自己制造,也可以到市场上去购买。购买来的砖块,虽然有某些差异,但总是遵循某些共同特性。这些砖块虽然是一块块地使用,但总是一车车的大量购买。函数也一样,市场上总是有专业公司提供函数出售,他们出售的函数按照功能聚集在一起,成为函数库。虽然不同公司的函数库可能具有相同的名字和功能,但内部是怎样构成的却不尽相同。

大部分现代编程语言,在规定了语言本身的语法和词汇(当然其中也包括了函数的使用方法)的同时,还会规定一个函数库。这个函数库只规定了每个函数的名称和用途。至于函数的具体实现方案,有的是由语言本身直接定义,有的是由实现该语言的编译器的厂商提供。而使用这种语言的用户,只要在需要的时候使用,而不用去管函数库内部的问题,大大提高了效率。这个库就叫做标准函数库。通常,现成的函数库都是经过了大量的实践检验证明是高效而健壮的,要比自己徒手打造的函数好用的多。所以在可能的情况下,要充分使用已有的函数库,尤其是标准函数库。C语言之所以如此强大,原因之一就是它有一个强大完备的标准函数库。Python同样也是一门功能强大的语言,其拥有一个强大的标准库,同时还有数不清的第三方库!第三方库的功能覆盖科学计算、Web开发、数据库接口、图形系统多个领域。

软件通常是运行在操作系统下的,从软件复用的角度看,操作系统如果能提供某些通用的服务,程序就可以集中注意力做自己的事。这些服务包括文件读写、设备操作、网络通讯、窗口绘制等等。否则,程序就会把大把的精力浪费在这些基础工作上。幸运的是,几乎所有的现代操作系统都提供了这样的服务。这些服务以函数的形式出现,程序使用这些服务,就像使用函数一样。这些函数形式的系统服务,就叫做应用程序接口API(Application Programing Interface)。遗憾的是,不同的操作系统,提供的API通常是不同的。使用某个操作系统的API编写的程序,搬动到另一操作系统时,由于API不能相互对应,也就不能运行了。这就是编程要针对平台的原因之一。

有些大型程序,比如Autodesk公司的AutoCAD,当你对它的某些功能不满或是感到有改进的必要时,它提供了编程改变的可能,相对于第一次开发来说这就叫二次开发。二次开发时,原始程序所提供的那些服务也被称为API。

使用砖块盖楼确实很方便,但如果能使用预制板,那就更方便了!比函数更高一级的可以复用的程序模块叫做类,类的使用比函数复杂,但是它可以更广泛的复用,是更高级的软件复用形式。类,同样可以聚集成类库。能够使用类的语言,就会规定标准类库。C++比C更强大,更难学,原因之一就是因为,C++除了具有C 所有的函数库之外,还有一个完整强大的标准类库。在类库当中,有一种很特殊的类,称为控件(control)。控件在快速的窗口程序开发中特别有用,它可以实现拖放式的编程。举例来说,想要编写一个有一个按钮的窗口程序,那么只要先创建一个窗口程序的工程,这个工程会自带一个窗口控件,而且直接显示在工作区里,然后再用鼠标把按钮控件从控件板上拖到窗口里需要的位置,按钮就摆放好了。至于按钮对应的功能,就需要程序员来编程实现。将来编译运行之后,程序的外观就和设计的外观一模一样。控件极大的提高了编程效率,但因为它需要自动生成某些代码,所以需要编辑环境的支持,支持控件的编辑环境总体来说比较少。控件的总和,就是控件库。

所有这些,函数、API、类乃至控件,开发必备,就像旅行时必需携带的行李一样,于是被统称为开发包(SDK : Software Development Kit)。

有些开发包是编译器自带的,如标准库等等,有些包是第三方厂商提供的。大部分开发包都需要集成开发环境(内带编译器)的支持,有的要编译器提供内部实现,有的要编译器给予连接,有的要编译器生成代码。不同的编译器提供的方式不太相同,这就造成了编译器之间的差异,有时甚至导致某个开发包不能在某款编译器上使用。为了进一步提高程序员的工作效率,很多集成开发环境还发明了另一些方法,相当于直接用一间间的房子叠在一起做成居民楼,你几乎只要刷刷外墙漆,就可以完成了,这被称为应用程序框架。可惜,不同的厂商的方法根本不同,这进一步扩大了集成开发环境之间的差异。不管未来怎样,至少现在,编程的规模变得越来越大,也越来越需要更多人的智慧。每个人的智慧都是有限的,不应该被浪费,充分使用每个人的智慧,才能取得最大的成功。软件复用就是整合所有人智慧的方式之一。从你编程的第一天开始,请牢牢记住:软件复用。要复用&复用&&再复用。

函数、API、库小结

相当于历史典故、谚语俗话、文化背景的东西,就是各个编译器和平台上的接口和库了。假设现在有个程序要读写文件,不要误认为你需要亲自写个程序去控制硬盘的磁头伸缩,或者是光驱的透镜移动或者是U盘的地址定位,除非你是想做个Linux或者Windows那样的操作系统。否则所有包括文件操作、网络通讯、人机界面这些,都是由操作系统提供的现成模块,只等着你来使用。这些模块通常称为应用程序接口(API - Application Programming Interface),不同的操作系统提供的API不一样。在接口的基础上,很多编译器和程序员做了进一步的包装形成了库,你可以比直接使用接口更方便地使用这些库而达到同样的功能。

由于系统的不一致,编译器的不同,所以在学库之前,先要确定你所要工作的平台和环境,还有应用方向。Windows下编游戏和Linux下做数据库用的库是大相径庭的。然后就是同样的一套步骤,找教材,做练习。这个教材通常就是官方文档,Unix/Linux平台有大量的文档,分布于man页和各种手册上,Windows下最好最全的就是MSDN,其他平台自行搜索。可以去找习题,但更好的方案是去找一个实际的小型应用,在使用中学习效果无与伦比。编写一个QQ或者BT,绝对能让你对网络操作部分了如指掌。网络上有很多开源项目,有兴趣可以自己去找找。

学习库和学习算法可以同时进行,在你完成这两个阶段的时候,你已经是一个合格甚至是优秀的程序员了。

优秀的文学作品有个共同的特征,他们虽然立足于不同的民族文化,但关心的却是全人类共通的思想感情,体现着终极的人文关怀,我们都会为 The Old Man and the Sea 中的Santiago所感动不是么。优秀的程序虽然应用方向不同以及平台各异,但它们一定都完全符合计算机原理,并且用最合理的数学模型来展现。如果你想成为合格的程序员,计算机组成原理和相关的数学知识是一定要补习的理论课。

除了看书和做题之外,还有一个内容不可缺少,就是阅读别人的程序。没有哪个作家不大量阅读别人的作品,同样你也可以从别人的代码中吸取营养。代码就是程序的全部,是真实的实现方法,一切都在代码中,甚至有时长篇累牍的说明还不如几行代码清晰明白。今天的程序员是幸运的,开源运动的发展使得他们能够无偿而方便地得到世界上最优秀的并且是实际运作中的代码,几乎遍布任何应用领域。只要你有心,就可以找到任何想要的代码。但读代码也是一件考验你毅力的事,读优秀的代码更是一种享受。但请阅读和你水平相当的代码,差距太大将会是严重的身心打击。你不会告诉我你C都还没学就想精通Linux内核吧?

超凡的主题跌宕的情节——其实就是你的程序的应用方向。如果说前面都是练习的话,那现在就是你自主创新的时候了。很多人都只是在老板的安排下为了工资而被动做些既不喜欢又没有价值的流水线产品,少数人才有机会做自己喜欢的东西。想想看, 3DMAX、WOW、Firefox、Nginx、Linux甚至Mac OS X都是多么知名的程序,也许有朝一日你的程序将会和它们一样知名。不过我还是不得不给你泼冷水,这需要不懈的努力、敏锐的眼光和少量的运气,只有极少数的程序员能做到这一点。不过,有梦想才能不断前进,不是么?:-)