灌溉梦想,记录脚步

ASP.NET和PHP、JSP究竟学哪个?

Asp.net

首先来说,Asp.net 和 Asp 没什么关系。 Asp 是脚本编程,用的是JavaScript或VbScript脚本进行编写,而ASP.net 则是使用基于.NET平台的语言如VB.NET、C#等,完全不同的东西。ASP.NET迄今为止共有四个版本:1.0、1.1、2.0、3.5它们使用的开发环境分别对应Visual Studio 2002、2003、2005、2008,当然在Visual Studio 2008支持多版本的.NET Framework,即可以在Visual Studio 2008下开发ASP.NET 2.0及3.5。

ASP.net的服务器,要求安装一个.NET Framework,当然我这里指的是windows系统,顺便点一下,.net只能放在windows环境里来运行。

Asp.net属于编译语言,和ASP的最大不同(ASP属于解释语言)。

ASP.net 的速度 是 ASP不能比拟的。下面我来说下为什么ASP.net 比 ASP 快:

ASP.net 是编译语言,所以,当第一次加载的时候,它会把所有的程序进行编译(其中包括 worker进程,还有对语法进行编译,形成一个程序集),当程序编译后,执行速度几乎为0,而ASP是把代码交给VBScript解释器或Jscript解释器来解释,当然速度没有编译过的程序快了。

Php

php和Asp一样也是,也是属于脚本语言,一般连接的数据库为MySql数据库,当然它也能和Access数据库和MsSq(SqlServer)数据库等其他数据库连接。他们都属于免费软件(在中国境内),也就是说他的资源是free的。

Php从安全性上比Asp要好,当然这里说的是相对而言,一个好的程序员把安全性做好的话,都差不多,不过Php的安全性要比Asp要好,为什么这么说呢。这里主要原因是这样的,PHP的搭建服务器环境相对复杂(需要安装Apache + MySql + PHP),而Asp的搭建环境比较简单(只需要安装IIS就可以了),所以学PHP的门槛比Asp的门槛要高,所以很多人就偏向Asp学习的人就多了,自然研究Asp漏洞的人就多了,而PHP会的人就少,所以研究漏洞的人就更少了,从这点来说PHP的安全性比ASP的安全性要高些。

而且还有一点就是 Apache 的环境最好是Unix,当然Windows下也是可以安装的。(Apache 是PHP的支持环境)

还有再说一点,就是MySql的效率问题,他比Access好很多倍,但是比MsSql(SqlServer)要差点。

JSP

JSP目前我还没有太多研究。总体上来说JSP的工程量巨大,任何工程都可以做到,当然是一个团队开发,3个人以上的一个团队开发,他的工期耗时也是最常的。
.NET的优势

有人问到这个问题,所以我总结了下。

.NET开发工具Visual Studo的易用性使得它在Java很难实现的“用户企业(信息系统部门)也可编程的系统”上超人一头。这可能还存在其他类似的领域。

由于Java本身较为复杂,且不易学习掌握,因此用户企业只负责企划,而将编程工作完全委托给集成商的现象非常普遍。

Java普及的主要因素很多,其中最关键的在于“开放性”。由于可各种OS上运行,而且很多开发商还提供了Web应用服务器和开发工具,因此用户可以随意选择。而开发商则通过在功能和性能方面相互竞争来不断提高产品水平。

说了半天,究竟学哪种语言好呢?.NET和JSP应该是未来发展的趋势。世界上一些大的电子商务解决方案提供商都采用JSP/Servlet和.NET框架模式。不过,偏爱PHP的开发者们也不用苦恼,精通任何一门,都是有前途的。

网络工程师的学习指南

虽然是水平第一,考试第二的,但朋友们毕竟还是以考试为目标的。说明白点,水平再高,过不了网络工程师也没说服力。
网络知识是电脑技术的十分重要的分支,除了网络之外,我们有更多更广的知识当然好,但即使不愿意承认,我也必须认可这样一个问题,就是有些知识对于通过网络工程师考试几乎没有用(说得好听些,就是对于你将来从事网络工作用处不大);甚至,有些网络知识对于通过网络工程师考试也没用,一个例子:哪怕是对ASP精通无比,对于你通过网络工程师上下午试题几乎没有任何帮助。

网络工程师跟高程一样,无法通过短期培训班之类提高水平,主要看个人长期的努力。既然好多朋友都问,该如何下手学习,我们就尝试着讨论一下,哪些资料在我们学习范围之内,这个讨论很“务实”“功利”,仅讨论如何针对网络工程师考试。

开始讨论之前,先说说到哪儿去买书,现在很多城市里面,都有针对考试的小型书店,面向公务员考试、司法考试等等,这里可以买到网络工程师教程之类的书,计算机本科自学考试的书,也是一种很好的选择。还有一些资料,这种书店买不到,需要去计算机类图书丰富的书店买。另外网上获得的资料不错,但是最好打印来看。

1、《网络工程师教程》,必看,当作指导性的大纲来看,它可以使你网络知识的结构更加清晰与合理。由于教程不完全覆盖考试内容,获取其他资料作为知识的深化和补充是绝对必须的,下面的推荐与大纲介绍的基本同步。

2、《数据通信原理》,包括通信原理和交换技术的内容,在上午肯定有一二道大题,只看教程不够。对这本书不一定看得太深,即使没有任何基础通上一两遍也不困难,可以让你提高一大步。这部分相关的内容还包括《信号与系统》,不想做硬件的朋友我觉得就不用看了。

3、网络体系结构和协议,这部分看教程即可。

4、局域网技术,先看教程,然后找一本CCNA英文教材看一遍。这样有三个好处:比教程更深入;同时提高专业英语水准;顺便学习CISCO路由器和交换机的基础知识。

5、广域网技术看教程,这部分ATM是重点,需要找别的资料深化一下(因为它流行,如CISCO流行一个道理)。

6、网络互连,先看教程。路由方面的知识教程上不够,建议有Linux环境,看看UNIX系统中的路由配置。CCNP的教程不必要全看,路由和交换看看就行,中文的也可以。

7、网络操作系统,如上,研究linux就可以。上午题目里面会有。

8、网络管理上,教程中本章前面对局域网的管理部分非常好,是每一个网络管理员都应该耳熟能详的经验。后面的SNMP不太深,但是也差不多够了,想深化的找一本《网络管理》,对snmp会有更认识。

9、网络安全,教程很概念化,如果想深入一点,看看《计算机密码学》,对加密技术能有更多感性认识(如RSA的原理,一次一密乱码本),但不用太深入。如果有条件,还可以感受一下win2000在安全方面对身份认证,鉴别,访问控制等技术的具体实现。我觉得其中有两个重要问题,访问控制和防火墙,但是这两年都没考,最好结合Cisco的学习去深化一下。

10、后面章节的内容看教程就好,还是很不错,将来做论文和实际项目,都会用上。

11、Linux教程必看,包括各种网络服务的配置(WWW,FTP),CGI现在不太时髦,可以不用看。另外如果有时间,把《网络操作系统》看一遍也很不错。

12、网络程序设计,只要有相当C语言能力,越高越好,不需要C++和Visual C(有的话更好),在Linux环境下,学习socket就可以,书方面看UNIX或LINUX网络程序设计都可以,置顶帖子里的UNIX网络程序设计是我看过的最好的。

13、网络工程师教程有一本配套的同步辅导,作一遍也好,但感觉没有本质进步,另外有一本航天出版社的《网络设计师重点分析》,那本书更没用(有抄袭之嫌)。真正的网络工程师题目往往需要你的综合能力,能够运用自己各方面的基础知识解决问题,比如2001年上午题目有一个有关路由表的问题。

14、如果感觉专业英语有欠缺,可以找一本清华的《计算机英语》,不过这不是专门面向网络英语的,可以考www.mcseguide.com订阅一份CCNA的邮件,既能学英语,又能做做题目。网上其他计算机英语读物,或是英文网站都不错,自己动手去找找,绝对可以丰衣足食。

15、越多的实践对你帮助越大,能在一个单位作网络管理最好啦。没有机会就尽量创造机会啦。

LINUX下进行C语言编程基础

这篇文章介绍在LINUX下进行C语言编程所需要的基础知识.在这篇文章当中,我们将会学到以下内容:

源程序编译
Makefile的编写
程序库的链接
程序的调试
头文件和系统求助

1.源程序的编译

在Linux下面,如果要编译一个C语言源程序,我们要使用GNU的gcc编译器. 下面我们以一个实例来说明如何使用gcc编译器.

假设我们有下面一个非常简单的源程序(hello.c):

int main(int argc,char **argv)
{
printf( " "Hello Linux " ");
}

要编译这个程序,我们只要在命令行下执行:

gcc -o hello hello.c

gcc 编译器就会为我们生成一个hello的可执行文件.执行./hello就可以看到程序的输出结果了.命令行中 gcc表示我们是用gcc来编译我们的源程序,-o 选项表示我们要求编译器给我们输出的可执行文件名为hello 而hello.c是我们的源程序文件.

gcc编译器有许多选项,一般来说我们只要知道其中的几个就够了. -o选项我们已经知道了,表示我们要求输出的可执行文件名. -c选项表示我们只要求编译器输出目标代码,而不必要输出可执行文件. -g选项表示我们要求编译器在编译的时候提供我们以后对程序进行调试的信息.

知道了这三个选项,我们就可以编译我们自己所写的简单的源程序了,如果你想要知道更多的选项,可以查看gcc的帮助文档,那里有着许多对其它选项的详细说明.

2.Makefile的编写

假设我们有下面这样的一个程序,源代码如下:

/* main.c */
#include " "mytool1.h " "
#include " "mytool2.h " "
int main(int argc,char **argv)
{
mytool1_print( " "hello " ");
mytool2_print( " "hello " ");
}
/* mytool1.h */
#ifndef _MYTOOL_1_H
#define _MYTOOL_1_H
void mytool1_print(char *print_str);
#endif
/* mytool1.c */
#include " "mytool1.h " "
void mytool1_print(char *print_str)
{
printf( " "This is mytool1 print %s " ",print_str);
}
/* mytool2.h */
#ifndef _MYTOOL_2_H
#define _MYTOOL_2_H
void mytool2_print(char *print_str);
#endif
/* mytool2.c */
#include " "mytool2.h " "
void mytool2_print(char *print_str)
{
printf( " "This is mytool2 print %s " ",print_str);
}

当然由于这个程序是很短的我们可以这样来编译

gcc -c main.c

gcc -c mytool1.c

gcc -c mytool2.c

gcc -o main main.o mytool1.o mytool2.o

这样的话我们也可以产生main程序,而且也不时很麻烦.但是如果我们考虑一下如果有一天我们修改了其中的一个文件(比如说mytool1.c)那么我们难道还要重新输入上面的命令?也许你会说,这个很容易解决啊,我写一个SHELL脚本,让她帮我去完成不就可以了.是的对于这个程序来说,是可以起到作用的.但是当我们把事情想的更复杂一点,如果我们的程序有几百个源程序的时候,难道也要编译器重新一个一个的去编译?

为此,聪明的程序员们想出了一个很好的工具来做这件事情,这就是make.我们只要执行以下make,就可以把上面的问题解决掉.在我们执行make之前,我们要先编写一个非常重要的文件.Makefile.对于上面的那个程序来说,可能的一个Makefile的文件是:

# 这是上面那个程序的Makefile文件

main:main.o mytool1.o mytool2.o

gcc -o main main.o mytool1.o mytool2.o

main.o:main.c mytool1.h mytool2.h

gcc -c main.c

mytool1.o:mytool1.c mytool1.h

gcc -c mytool1.c

mytool2.o:mytool2.c mytool2.h

gcc -c mytool2.c

有了这个Makefile文件,不过我们什么时候修改了源程序当中的什么文件,我们只要执行make命令,我们的编译器都只会去编译和我们修改的文件有关的文件,其它的文件她连理都不想去理的.

下面我们学习Makefile是如何编写的.

在Makefile中也#开始的行都是注释行.Makefile中最重要的是描述文件的依赖关系的说明.一般的格式是:

target: components

TAB rule

第一行表示的是依赖关系.第二行是规则.

比如说我们上面的那个Makefile文件的第二行

main:main.o mytool1.o mytool2.o

表示我们的目标(target)main的依赖对象(components)是main.o mytool1.o mytool2.o 当倚赖的对象在目标修改后修改的话,就要去执行规则一行所指定的命令.就象我们的上面那个Makefile第三行所说的一样要执行 gcc -o main main.o mytool1.o mytool2.o 注意规则一行中的TAB表示那里是一个TAB键

Makefile有三个非常有用的变量.分别是$@,$^,$ ~/sin 命令,然后看~/sin文件,到那里面去找了. 在sin文件当中,我会找到这样的一行libm-2.1.2.so:00009fa0 W sin 这样我就知道了sin在 libm-2.1.2.so库里面,我用 -lm选项就可以了(去掉前面的lib和后面的版本标志,就剩下m了所以是 -lm). 如果你知道怎么找,请赶快告诉我,我回非常感激的.谢谢!

4.程序的调试

我们编写的程序不太可能一次性就会成功的,在我们的程序当中,会出现许许多多我们想不到的错误,这个时候我们就要对我们的程序进行调试了.

最常用的调试软件是gdb.如果你想在图形界面下调试程序,那么你现在可以选择xxgdb.记得要在编译的时候加入 -g选项.关于gdb的使用可以看gdb的帮助文件.由于我没有用过这个软件,所以我也不能够说出如何使用. 不过我不喜欢用gdb.跟踪一个程序是很烦的事情,我一般用在程序当中输出中间变量的值来调试程序的.当然你可以选择自己的办法,没有必要去学别人的.现在有了许多IDE环境,里面已经自己带了调试器了.你可以选择几个试一试找出自己喜欢的一个用.

5.头文件和系统求助

有时候我们只知道一个函数的大概形式,不记得确切的表达式,或者是不记得着函数在那个头文件进行了说明.这个时候我们可以求助系统.

比如说我们想知道fread这个函数的确切形式,我们只要执行 man fread 系统就会输出着函数的详细解释的.和这个函数所在的头文件说明了. 如果我们要write这个函数的说明,当我们执行man write时,输出的结果却不是我们所需要的. 因为我们要的是write这个函数的说明,可是出来的却是write这个命令的说明.为了得到write的函数说明我们要用 man 2 write. 2表示我们用的write这个函数是系统调用函数,还有一个我们常用的是3表示函数是C的库函数。

记住不管什么时候,man都是我们的最好助手。

好了,这一章就讲这么多了,有了这些知识我们就可以进入激动人心的Linux下的C程序探险活动

九行代码让windows崩溃

目前很多地方都转载着利用9行代码使windows崩溃的文章,不过我发现没有关于为什么会使windows崩溃的分析。我先把原文给大家看看。然后把具体的细节说一下。
微软一直声称Windows XP多么多么稳定可靠,但日前一位名为Masaru Tsuchiyama的外国编程爱好者刊出了一小段C语言代码。这一只有9行的小程序如果在Windows XP/2000下运行,则可导致系统完全崩溃,并重新启动。但此程序对其他版本的Windows没有任何影响。这一产生无限循环输出的小程序的代码如下:
#include
int main( void )
{
for(;{
printf( "hung up\t\t\b\b\b\b\b\b" );
print("hung up\t\t\b\b\b\b\b\b";
}
return 0;
}
如果去掉Print语句,此程序还会导致NT 4.0系统出现蓝屏错误。
但愿微软赶快修补这一漏洞。同时提醒大家,此代码只可用于研究,不得用于任何非法勾当。
如果去掉Print语句,此程序还会导致NT 4.0系统出现蓝屏错误。以上遍上网上纷纷转载的原文。

关于为什么会导致错误,就在看下面的分析吧。
\b是退格
代码是用退格符把console里的光标退成null,
然后显示任一字符(除\t),即崩溃.
但是一般情况\b是不能退出规定的区域的,
而如\b的前一个字符是\t则可以退出规定的区域(bug?).
双击运行时,系统将新建一个console,所以我们的显示在console
的左上角,我们只需两个\b就可退出屏幕(第一个吃掉\t).
原因是win32子系统意外中止导致系统崩溃.smss是windows系统建立的第一个用户进程,他的工作之一是建立csrss和winlogon进程,然后一直等待这两个进程的句柄,如果这两个进程意外中止,
smss将导致系统崩溃.csrss进程就是专门负责所有win32进程和系统进行通信的进程.所有win32进程的系统调用都会由csrss帮你完成,但是这样做因为需要进程切换所以效率太低.所以在windowsNT从3.51升级到4.0时将许多部分从用户态移入内核态,win32进程的系统调用将直接进行以减少进程切换时间.但是仍有少量系统调用需要csrss进程完成,据我所知createprocess
是这样的函数,所有console上的显示是这样的函数(还有其他的).
当我们调用printf("\t\b\ba")最终将调用WriteFile API.
WriteFile((HANDLE)7,"\t\b\ba",NULL,NULL)等同于
printf("\t\b\ba"),7是console标准输入的句柄.
WriteFile判断句柄类型,如是文件句柄将调用ntdll.dll中的
NtWriteFile函数.如是console句柄将调用WriteConsoleA函数.
WriteConsoleA函数将调用ntdll.dll中的csrClientCallServer
函数通知csrss进程,然后调用NtRequestWaitReplyPort等待结果.
估计是csrss进程在处理这个请求过程中出错了.
几年前侯杰老师分析后我整理出来的。因为没有地方说过,甚至简单的分析都没有,所以我才把他翻出来 :) 细心的人发现csrss出错的细节没有描述,谁有时间就补充一下吧..

怎样成为优秀的程序员

Tip 1 要方法而不是记忆
我的一个程序员朋友常跟我说记住超过200个C++函数是多么的有帮助。“我从来不必去查找函数的定义,因此我可以比其他程序员编程快上50%。”他自豪的说。可结果是什么?难道他不知道编译器的代码自动完成功能可以节约大量查找函数及输入函数的时间吗,另外当C#发布出来后,他在记忆函数上面的努力就白费了。当然,编程中对函数的熟记是一件必需的事情,但是你应当花费更多的时间在学习做事的方法上,比如说创建一个数据库连接,如何产生RSS源等,然后是关注于代码是如何实现的。学习做事的正确方法远比死记硬背重要。
Tip 2 建立属于你自己的资源库
我们都会有因为这样或者那样原因而不得不建立的代码集。我从来不记得连接数据库的准确代码语句,所以我每次都不得不在代码集中花10分钟去查询它。为了解决这个问题,我创建了一个用于记录代码片段的Word文档,以帮助我记忆和查找。我的一个同事建了个记录链接的书签,另外一个同事在他的邮件中存储了这些内容。无论你的方法是什么,都是一种可以使你方便查找到文件或内容的好习惯。当你建立你的知识库后,你会发现它将极大的帮助你去把代码写得更好和更快。
Tip 3 知道做什么而不是怎样做
很多初级程序员问我“我怎样做这个,或者我怎样做那个?”我总是会跟他们说“你想做什么呢?”听闻此言后,他们会死盯着我,就好像我跟他们的妈妈约会了一样。这就是我的下一个观点,绝不要在知道你想做什么之前去学习怎样做,比如一个程序员想要搜索一个文本文件中是否存在的某个特定的词汇。下面是用C#来实现该目的:
view plaincopy to clipboardprint?
string fileContent; System.IO.FileStream myStream = new FileStream("c:\\aa.txt", FileMode.Open); System.IO.StreamReader myStreamReader = new StreamReader(myStream); fileContent = myStreamReader.ReadToEnd(); myStreamReader.Close(); int idx = fileContent. IndexOf("string"); if (idx) { return true } string fileContent;System.IO.FileStream myStream = new FileStream("c:\\aa.txt", FileMode.Open);System.IO.StreamReader myStreamReader = new StreamReader(myStream); fileContent = myStreamReader.ReadToEnd();myStreamReader.Close();int idx = fileContent.IndexOf("string"); if (idx){return true}
现在我给他这些代码去做这件事,但是更重要的是理解自己正在试着做的是什么。在这个例子中我们想做的是:
1. 打开一个文件
2. 读其中的内容
3. 关闭文件
4. 搜索字串
5. 如果找到了则输出结果
用这个方法来解决事情产生了以下结果:
1. 它使语言无关
2. 使你的精力集中在需要做什么上
3. 使你的代码更易读和有效
知道要做什么将使你的代码更有目的性。现在在C++、PHP、VB.NET、Ruby on Rails中编写上述代码是很容易的事情了,因为你理解了要做什么而不是怎样去做。
Tip 4 创建适合你的注释风格
每一个程序员都讨厌注释,但是为了写出更有质量和易读的代码,我们需要注释。问题是大多数程序员常被告知如何注释,一些公司希望每一行代码都有注释,另外一些则想要在每个函数前面有一段注释,还有的规定在不同的代码块前注释。我并不同意这种强制性的规定,只要代码是可用的、易读的和有效的,那么程序员应当可以用其个人喜好的格式来注释。对我来说在每一行都注释将破坏代码的节奏,我更喜欢在函数的前面注释,罗列我接下来一步步将要做什么,然后在函数中参考注释中所写的步骤进行编程。这是适合我的模式,这样可以在我编程前帮助我组织设计,也保持了我的节奏,使我不会因为需要注释而在编程时中断,也有助于其他人阅读我的代码。下面是我怎样注释的例子:

view plaincopy to clipboardprint?
/* 1. Open File* 2. Read file into string* 3. Close file* 4. Search for key word* 5. If fond return true; */ string fileContent; //1. System.IO.FileStream myStream = new FileStream("c:\\aa.txt", FileMode.Open); System.IO.StreamReader myStreamReader = new StreamReader(myStream); //2. fileContent = myStreamReader.ReadToEnd(); //3. myStreamReader.Close(); //4. int idx = fileContent.IndexOf("string"); if (idx) { //5. return true; } /* 1. Open File* 2. Read file into string* 3. Close file* 4. Search for key word* 5. If fond return true;*/string fileContent;//1.System.IO.FileStream myStream = new FileStream("c:\\aa.txt", FileMode.Open);System.IO.StreamReader myStreamReader = new StreamReader(myStream);//2.fileContent = myStreamReader.ReadToEnd();//3.myStreamReader.Close(); //4.int idx = fileContent.IndexOf("string");if (idx){//5.return true;}

这种注释风格使我和大多数程序员可以容易的阅读它。那么,找一个适合你的注释风格吧。
Tip 5 精通one,学习another,关注next
有时有程序员发email问我他应该学习什么语言,什么是最好的编程语言等等。你至少应该精通一门编程语言,可以相当好的去编写代码,然后再去学习掌握另外一门,逐渐的成长。以我自己为例,我精通C#,擅长PHP,并且已经开始使用Ruby on Rails大概有一两个月了。为什么呢?精通一门语言可以使你进步,在进步中写更好的代码,找到完成任务更好的方法等。进步也是我作为一个程序员年复一年的工作,却仍没有觉得枯燥的原因。

主流编程语言优劣考

主流编程语言优劣考

前言

本文的目的并非是想挑起语言之争,而是希望通过客观地分析每一种主流语言的能力,辨明其长短,让程序员能够扬长避短,有效地使用各种语言。让各种语言能够各安其位,为你更好的服务。
程序员应当成为语言的主人,而不是语言的奴隶。

正文

这里,我将比较一下几种主流编程语言:C,C++,Java,.NET,Ruby,JavaScript。
其他主流编程语言,如Pascal,Delphi,我不太熟悉。希望熟悉的朋友能够补全对这些语言的评价。
至于Basic,它的版本差异很大,而且能力不太全面,这里也不做评价。

语言特性对比表

C C++ Java .NET Ruby JavaScript
类型 无类型 强类型 强类型 强类型 强类型 强类型
静态/动态 静态 静态 静态检验类型动态 解释执行 动态 动态
支持面向过程 是 是 否 否 否 是
支持基于对象 否 是 否 是 是 是
支持范型 否 否 是 是 否 否
支持模板 否 是 否 否 否 否
支持面向对象 否 是 是 是 否 否

可能你对于我这样的语言评价有些疑问,请首先看我的另一篇文章基于对象和面向对象编程范式辨析和主流编程语言中的应用 理清相关的概念。我对与面向对象和基于对象的定义和流行的定义不太一样。

C语言优劣考

C语言由来

让我们先回顾一下历史。
电脑使用CPU指令,通过寄存器,内存等物件执行计算。最早的编程,是直接使用代表CPU指令的机器码编写的。直接使用二进制的数据编程,当然很容易出错。于是,人们后来发明了一种方法,就是使用英语单词作为助记符,代表各条CPU指令。这就是汇编语言。现在,程序员可以使用英语单词进行编程,然后使用一个解释程序,把汇编指令翻译成机器语言,再交给计算机执行。1970年,UNIX操作系统的研制者丹尼斯·里奇(Dennis Ritchie)和肯·汤普逊(Ken Thompson)为了更好地编写操作系统,发明了C语言。
C语言比汇编语言更先进。它使用了面向过程的编程范式。同时它仍是一门十分接近汇编语言,面向机器的编程语言。适合编写操作系统和其他直接操纵硬件硬件的编程。

面向过程编程范式

下面是我查到的过程式设计的定义:
过程式设计:
1、自上而下(top-down)的设计方式:是一个自顶向下,逐步求精的过程;
2、以main函数概括出整个应用程序需要做的事情,而main函数由对一系列的子函数的调用组成;
main中的每一个子函数都可以被精炼成更小的函数。重复这个过程,即可完成一个过程式的设计;
3、特征是以函数为中心,以函数作为划分程序的基本单位,数据往往处于从属地位。

过程式设计的优点:易于掌握与理解,符合人们的思维习惯;
过程式设计的缺点:
1、不能适应问题比较复杂,或者需求经常变化的情况;
2、数据与操作分离开,对数据与操作的修改变得很困难;
3、程序架构的依赖关系不合理:main函数依赖于子函数,子函数又依赖于更小的子函数;
而子函数往往是细节的实现,这些实现是经常变化的,造成的结构就是:
程序的核心逻辑依赖于外延的细节,一个细节上的小改动,会引起一系列的变动。

我对于面向过程编程范式是这样理解的:
面向过程编程,就是使用函数代表处理的过程。这些函数使用的数据,要么是参数,要么是外部的数据。
使用函数编程,这看上去很像函数式编程。但面向过程的编程范式不同于函数式编程。函数式编程的函数,一般不使用外部的数据。不维持外部的状态。这有很多优点,但也同样有了很大的局限性,不似面向过程编程这样方便。
C语言就是典型的面向过程编程语言。它通过函数抽象了过程处理。函数,就是C语言的接口。
C语言中,数据常常作为全局的变量保存起来。这样,使用C语言编程就很难保证其他代码不破坏函数依赖的数据的状态。这是C++基于对象编程范式出现的原因。这个我们稍后再说。

我们再看看C语言对机器指令的抽象。
C语言是一门十分接近汇编语言的语言。所以有人说C语言既是一门高级语言(面向过程,函数),也是一门低级语言(面向机器,直接反映计算机的实际计算过程)。
C语言使用原生类型,数组,Struct等来表示数据。C语言中,数据在内存中的表示是十分确定的。程序员可以充分控制。如,C语言中可以使用memcpy()直接复制内存中的数据。
现在,大多数的操作系统原生函数库,都使用C语言作为其接口。绝大多数的语言都具备与C语言函数库进行互操作的能力。
C语言可以说是程序世界的世界语。

C语言的优点

1, 面向过程开发,以函数为中心。简单有效。实现了简单的接口。
2, 面向机器,让用户可以完全的操纵机器,效率较高。
C语言运行高效,广泛应用于各种计算领域。对于简单的任务,非常有效。

C语言的缺点

1, 函数无法有效控制需要的数据。不能保证外部状态不变。容易出现Bug。
2, 对于机器的控制太强,也就是依赖太强。由于过于强调效率,使用C语言编程时,更多的需要考虑机器,而不是问题本身。
由于过于关注机器,而不是问题域本身,因此抽象能力不足。容易出现各种Bug。对于编写大型的程序,常常力不从心。

C语言的使用方法

C语言作为一种简单高效的编程语言,适用于编写简单的程序。在编程中,应该注意扬长避短,使用面向过程的编程范式,少用对机器的依赖。
1, 使用函数编程时,应该尽量使用函数参数传递状态,少用全局数据。因为,你无法保证全局数据不被其他代码改变。
这样使用函数,叫作“纯函数”。类似于函数式编程的用法。而且,使用这种方式编程,由于不存在全局数据,在进行多线程开发时,还不需要考虑多线程问题。
2, 使用结构化的编程方式。不要卖弄技巧。
3, 函数是接口。尽量使用函数调用,而不是直接的代码。通过层层分层,分配职责,编写出短小精悍,易于维护的代码。
4, 尽管C语言是一种面向机器的语言。但是,我们还是应该尽量少地依赖机器。多从问题域来考虑和抽象问题。如,少用内存假设等等。因为,我们会使用很多种语言,C,C++,Java,C#等语言的很多语法类似。但是实际的表现,各个语言都是不同的。如果过分考虑C的机器特性,那么很可能会因为记错而编写出错误的代码。
5, 代码,首先是给人看的。顺便给机器执行!
不要处处优化代码。只应该优化性能瓶颈。因为优化的代码,常常表示很难看懂!
6, 应该大量使用Struct组织相关的数据。在用C语言编程时,也应该树立类型和对象状态的概念。把Struct作为函数的参数传递数据。

C++语言优劣考

在C语言优劣考中曾经说过:C语言中,数据常常作为全局的变量保存起来。这样,使用C语言编程就很难保证其他代码不破坏函数依赖的数据的状态。这是C++基于对象编程范式出现的原因。
C++最初是作为C语言的扩展出现的,最初的名字就叫“带类的C”。后来,C++逐渐演化成一门独立的语言。但还是和C语言兼容。

基于对象的编程范式

基于对象的编程范式,又称“抽象数据类型”(ADT)。
面向过程的编程范式中,函数无法控制函数外的共享数据。这使面向过程的编程语言不能很好地编写大型系统。为了解决这个问题,人们发明了基于对象的编程范式。
就是把数据和处理数据的函数都封装在一个类中。这样,共享的数据就不会再被外部的代码改变了!

下面是我查到的定义:
抽象数据类型(Abstract Type简称ADT)
ADT是指抽象数据的组织和与之相关的操作。可以看作是数据的逻辑结构及其在逻辑结构上定义的操作。

ADT的描述规范
一个ADT可描述为:
ADT ADT-Name{
Data://数据说明
数据元素之间逻辑关系的描述
Operations://操作说明
Operation1://操作1,它通常可用C或C﹢﹢的函数原型来描述
Input:对输入数据的说明
Preconditions:执行本操作前系统应满足的状态//可看作初始条件
Process:对数据执行的操作
Output:对返回数据的说明
Postconditions:执行本操作后系统的状态//"系统"可看作某个数据结构

Operation2://操作2
……
}//ADT

抽象数据类型可以看作是描述问题的模型,它独立于具体实现。它的优点是将数据和操作封装在一起,使得用户程序只能通过在ADT里定义的某些操作来访问其中的数据,从而实现了信息隐藏。在C﹢﹢中,我们可以用类(包括模板类)的说明来表示ADT,用类的实现来实现ADT。因此,C﹢﹢中实现的类相当于是数据的存储结构及其在存储结构上实现的对数据的操作。
ADT和类的概念实际上反映了程序或软件设计的两层抽象:ADT相当于是在概念层(或称为抽象层)上描述问题,而类相当于是在实现层上描述问题。此外,C﹢﹢中的类只是一个由用户定义的普通类型,可用它来定义变量(称为对象或类的实例)。因此,在C﹢﹢中,最终是通过操作对象来解决实际问题的,所以我们可将该层次看作是应用层。例如,main程序就可看作是用户的应用程序。

C++支持多范型的开发方式:面向过程,基于对象,面向对象,模版。
C++和C语言是兼容的。因此,你完全可以使用C++编译系统编写C语言的程序,因此,支持面向过程编程是很自然的。但是,使用面向过程编程,还能说是在使用C++编程吗?

另外,需要注意,C++语言,实际上是一种不同于C语言的新语言。在内存上,除了一些C语言的元素之外,新的语言元素并不像C那样面向机器。
对于C++,你不能使用memcpy等内存操作的函数,很可能会出现错误。因为C++语言建立在一些高级概念的规范上,这些规范并没有规定内存如何分配等机器方面的细节。

我在基于对象和面向对象编程范式辨析和主流编程语言中的应用 一文中已经指出基于对象和模板是必须组合在一起使用的技术。
C++中首选的编程范式是“模板支持的基于对象”的编程范式。实现静态多态。
然后才是面向对象的编程范式。实现动态多态。
最后是C语言风格的面向过程编程。

C++的使用方法

使用C/C++开发环境,我们可以同时使用C和C++开发。既然C++和C是兼容的,我认为完全没有理由使用C语言,而不使用C++进行开发。
即使是很小的问题,使用C++的“模板支持的基于对象”的编程范式也是首选的开发方式。

另一方面,在整个类库的外部,如果我们希望向其他语言提供接口,那么我们还应当提供C语言的API函数作为接口。

C语言是程序世界的世界语。

使用C++的基本类型,struct,STL库的Vector,STL的string::c_str()等都可以得到C语言兼容的接口。还不能使用异常。因为C语言不支持异常,而且C++本身的异常,在不同的编译器中也可能不兼容。

总之

1,使用C++开发,只在外部接口中使用C语言开发。使用“模板支持的基于对象”的编程范式,或者面向对象的编程范式。不要使用面向过程的编程范式。
2,尽量把代码放到类中,而不是使用全局或者命名空间的变量。
3,尽量不要使用操作符重载。
4,必须注意到C++不像C语言那样面向机器,不能对C++对象的内存布局进行假设。不能根据内存内的数据直接构建对象。不要进行内存操作。
5,C++还是很面向机器的。很多语言规则都规定了内存的布局,必须按照规则定义、初始化等等。这和Java,.NET,Ruby等语言不同。用惯高级语言的程序员特别需要注意C++和C对程序员的繁琐要求。
C/C++的设计哲学中,始终把自己作为一门系统编程语言,针对机器进行了很多优化。因此,对于人,就很不照顾了。很多规则很不人性化。但没办法,你必须适应它们!
它们就是为了高效而生的。它们就是汇编的替代者。

Java语言优劣考

Java是一门静态强类型面向对象的编程语言。它是C++和Smalltalk取长补短的产物。
Java是静态编译的强类型语言。你必须声明变量的类型,以便编译器能够检查代码的类型是否正确。这和 C++是相同的。Java是一门类型非常安全的编程语言。
Java只支持一种编程范式:面向对象编程范式。对于过时的面向过程编程范式并不支持。也不支持基于对象的编程范式,也没有模板。
原因可能是,当java在90年代中期刚刚诞生时,面向过程的编程已被唾弃。而C++的基于对象的编程方式,由于没有和模板相互结合,而名声扫地。C++对于面向对象的编程范式的支持又比较差。
于是,汲取经验教训之后, Java作为一门纯正的面向对象编程语言诞生了。
Java使用面向对象的编程范式实现了动态多态,实现了抽象化的编程方式。取得了巨大的成功。

Java语言中,除了基本类型是值类型之外,没有任何值类型,你也不能创建任何值类型。这样,基于对象编程这条路就被卡死了。
虽然丧失了值类型的效率,但是也避免了基于对象编程的大量错误。

Java语言中所有方法也都是虚函数。这也是为了保证纯正的面向对象编程。

Java语言是静态面向对象编程范式的顶峰。使用面向接口的抽象编程,是有效使用java开发的唯一途径!

另一方面,Java实际上是一门动态语言。它是动态解释执行的。和Ruby,JavaScript等一样。
这使java具备了运行时的灵活性。可以实现自省,反射等C++等传统静态语言无法实现的功能。

.NET语言优劣考

.NET是java的兄弟。是微软因为被Sun排除在java之外而开发的一套语言。主要包括C#,VB.net,C++/CLI等语言。
它的设计理念基本和java相同,也是一个支持静态面向对象编程范式的平台。
对于.NET语言平台,我选择C#和C++/CLI这两种语言进行论述。VB.NET和C#类似,这里就不再多说了。

C#

C#.net还支持值类型,也就是基于对象的编程范式。(当然,.NET框架也是支持值类型的)
C#.net的泛型类型替换是在运行时执行的。对于引用类型(在堆内存中创建实例的类型),它使用类型强制转换,而不是C++模板的源代码生成来实现参数化类型。
对于值类型,则使用类似于C++模板的MSIL中间代码生成机制实现。
顺便提一下,java的泛型实现和C#的机制类似。也是使用强制类型转换实现。而且,Java中没有值类型,也不能对基本类型进行泛型操作,因此没有C#和C++中的源代码扩张问题。
但是,老实说,java的泛型机制确实太弱了!

C#语言首选的是面向对象编程范式。C#也可以使用泛型支持的基于对象的编程范式。
使用值类型,对于用惯面向对象编程范式的C#和java程序员来说有一定的难度。而且,提升的效率也并不很高。
同时,在语法层面上,C# 泛型是实现参数化类型的更简单方法,不具有 C++ 模板的复杂性。此外,C# 并不尝试提供 C++ 模板所提供的所有功能。
因此,C#泛型支持的基于对象编程要比模板支持的基于对象的编程要弱很多。
理念上,泛型编程有些不伦不类,有着太强的面向对象编程的气味。
C#中,使用泛型支持的基于对象的编程范式不如面向对象编程范式。
我认为,C#语言还是应该首先使用面向对象编程范式。

C++/CLI

C++/CLI是为了让C++使用.NET平台而提供的扩展机制。
.NET平台是类似于java的静态强类型动态执行的执行平台。是面向对象编程范式理念的框架。
C++/CLI使用了新的语法,使用C++/CLI进行.NET开发时,类似于C#编程。
同时,也可以使用模板进行C++/CLI编程。这是C++/CLI2005新增的功能。
使用C++/CLI进行.NET编程时,既可以使用C#样式的面向对象编程。也可以使用模板支持的基于对象的编程范式进行开发。
可以把模板支持的基于对象的编程范式和.NET的面向对象的编程范式结合起来使用。

C++/CLI可以同时使用原生C++和.NET编程。如果使用.NET框架执行,那么C++原生代码就会存放在生成的MSIL中间代码中,在运行时再使用C++编译器编译成机器码。

.NET的互操作机制

.NET运行时本身就是使用COM编写的,是一个COM服务器。因此,.NET和COM互操作是非常简单的。也可以使用COM技术,用C/C++直接调用.NET内的方法。
在互操作上。.NET比java实现得更好。不能从C语言调用Java方法,只能从java代码中使用JNI调用C方法。

总体评价

.NET是java的表兄弟。又做出了一下改变。
1,定义了.NET的汇编语言。基于.NET的汇编语言可以支持任何语言在.NET平台上执行。Java自然也可以作为一个平台。但是java平台的设计目标就是java这一种语言,因此没有定义汇编语言,只有java的机器码。

2,支持值类型。虽然用处不大,但是可以提高性能,也方便与C语言的函数库交互。

3,泛型的实现比java强大。

4,特别是C++/CLI,具有模板*.NET运行库的强大能力。

Ruby语言优劣考

Ruby是一种强类型的动态解释型语言。在Ruby中一切都是对象。
使用Duck Typing“像鸭子一样编程”的编程理念。Ruby有类型,但是变量不确定类型。这也实现了动态的多态能力。
不象Java,.NET等静态面向对象编程语言,不需要使用什么都不作,仅仅表示类型的规范的接口。Ruby中使用变量时不需要声明使用什么接口或者类型。
任何类型都可以,只要确实有这样的方法或者数据成员存在即可!
类似于C++的模板编程,只是C++的模板需要指定参数的类型。Ruby不需要指定变量的类型,因此不需要模板那样的机制。

Ruby这样不指定变量类型的语言使用起来非常灵活。

按照动态语言的观点,既然编译时不能完全找出运行时的错误,不如不要编译时检查,也不要编译。使用单元测试来寻找错误。

但是,C++,Java,.NET这样的编译时检查类型的语言也有自己的优点:
1,更加安全,编译时就会发现错误。
2,可以实现IDE的智能提示。而Ruby这样的语言就不可以。因为C++,Java的变量使用时都指定了类型,因此可以在IDE中智能提示可能的成员。
而Ruby这样的动态语言的变量都没有指定类型,所以无法为你提供智能提示。

使用Ruby,应该使用“动态类型语言”的基于对象的编程范式,使用隐式的接口。使用的类不需要有一个共同的基类。让各个实现类互相独立存在就行了。记住,这是和C++的模板支持下的基于对象的编程范式类似的基于对象(ADT抽象数据类型)的编程!

不要试图用java,C#这样的语言的面向对象的编程思维方式来编写Ruby程序!

JavaScript语言优劣考

JavaScript是一门长期以来被忽视的语言。它的重要性和能力都被大大的低估了!
这是因为Java和.NET崛起以来,“静态类型语言”的面向对象的编程范式受到广泛的推崇。作为动态语言,函数式语言的JavaScript长期以来被广大Java,.NET程序员视为畸形怪胎!老实说,长久以来,我也一直是以厌恶的眼光看待它。多少次,它让我很抓狂。
直到现在,我还是没有学好JavaScript。尽管JavaScript已经诞生了这么多年,但是把JavaScript作为一门很有前途的动态强类型语言,函数式语言来看待还是新鲜事物。还没有见到很多关于这方面和设计模式的研究。
周爱民的《JAVASCRIPT语言精髓与编程实践》一书应该不错,但是我还没有看过。

JavaScript支持面向过程的编程范式

这是JavaScript使用最广泛的一种编程范式。简单、快速、有效。JavaScript代码需要通过网络传输到用户浏览器中,因此JavaScript的使用一般都是简单的几个数据提交和验证功能。如果使用Ruby那样的动态基于对象的编程范式编码显得有些小题大做,又浪费带宽。

JavaScript支持“动态类型语言”的基于对象的编程范式

如果JavaScript仅仅支持过时的面向过程的编程范式,那么JavaScript就真的是大家心目中的鸡肋了。
这些年来,广大程序员都忽视了JavaScript也是一门动态类型语言,还是一门函数语言!
我们完全可以向Ruby那样进行基于对象的开发。
现在,伴随着广大用户对户客户端的效果和AJAX技术的期待。JavaScript正在完成越来越大的任务。正在开发和传统语言类库类似的庞大类库。
如,EXT实现的用户界面库。和Java的Swing库很接近。这样巨大的系统,必须要使用基于对象的编程范式,再使用面向过程的编程范式不可想象!

把JavaScript当成Ruby来使用,这是我对你的忠告。

题外话:
不过也许我的JavaScript技术永远不会很高。因为虽然我越来越欣赏JavaScript语言的机制。但是,我对用户界面的开发并不是很有兴趣。我认为用户界面是小道。底层的逻辑开发才更有价值,我也更加有兴趣。

总结

现在再来看看篇首的“语言特性对比表”,也许你能够认同我对这些语言的观点了。

如果我需要进行原生系统开发,我会选择使用C++,使用模板支持的基于对象的编程范式进行编码。
如果需要给其它语言提供接口,我会用纯C语言实现一些接口函数,供其它语言调用。

如果需要Java语言进行开发,肯定要使用面向对象编程。需要大量使用接口,依赖于抽象。

如果需要使用.NET开发。那么我也会使用面向对象编程范式编码。很少使用值类型。
如果使用C++/CLI开发,我会使用模板开发原生C++程序,也会首选模板开发.NET程序。也可以像C#那样使用面向对象编程范式开发.NET程序。
我真的爱死模板了!这么多年来我还一直认为模板是个废柴呢!

如果要编写脚本,我会使用Ruby,“动态类型语言”的基于对象的编程范式。
Java和.NET平台上都在引入Ruby,Python等动态语言,也许很快就可以用它们开发Java和.NET程序了!

在浏览器上开发,当然得用JavaScript[很久以前,我使用VBScript这门语言—上了微软的当了。那时以为凡是微软的就是好的!。
简单的需求,当然用面向过程范式开发。
大的项目,比如AJAX,地图,GUI等,使用“动态类型语言”的基于对象的编程范式开发。

公司技术管理角度看C++游戏程序员发展

这是我多年来招聘培训游戏程序员的一点想法。一直想汇总一下。主要目的是为了更好的对公司新进C++程序员进行培训,并且建立起游戏程序员培训,发展,成才,成为核心骨干,管理层,期权收益人等一整套体系。因为对于MMO游戏制作来讲,解决好C++技术队伍,是保证合格软件的基础之一。

我在的H3D Studio核心技术人员和游戏制作管理人员全部是SMTH BBS游戏制作版成员。从99年开始截止BEGINER的历任版主都在H3D STUDIO里工作过。在这里我把具体的培训以及技术队伍组建的内容去掉,只和大家聊聊关于游戏程序员切身利益相关的事。

另外这不是居高临下来评判什么事情。我本人也不是多么高级的技术人员或者管理人员。只是坚持做一件事情年头很长教训很多而已。所以有些体验。文中所有评判其他结构或人水平低,并不是说我本人水平有多高。不要误会。

1 ,C++游戏程序员现状

中国C++程序员100%都是自学的。因为中国几乎没有象样的C++培训机构。大家都知道社会培训是赚钱为主要目的。能在那里成才是个大运气。也不象JAVA有SUN公司一手推行。中国大学教育里也根本没有C++教学。关于C/C++基础课的知识,只是让学生入门。但对于实际的C++软件工程应用,大学课本知识实践意义不大。最重要的是,大学里没有合格的C++老师。编程是门技术,叫手艺也行。而大学是搞科研的,多的是科学家,靠出PAPER教科凭职称为生。并不是技术员。没有10万行以上代码经验和成功软件项目经验的人,很难教出中高级C++程序员。

游戏制作业对C++程序员的要求是比较高的。比一般行业软件高很多。因为任何一个MMO都是个中大型软件项目。日使用人次达到几十万上百万,同时使用人数几十万在线的大型网络多人交互软件,集成了超过十几项专业领域编程技术的软件,想不大都不行。

另外,中高级C++程序员能力一般都很强。因为都是自学成才,这需要较高智商,很强的自学能力,解决问题能力,和克服困难的毅力。但是这种人才在游戏行业里人数并不多。抛开凤毛麟角具备整体大型软件架构能力的高级人才不谈。能够承担独立模块开发,具备独立解决问题的能力,写出在空间,性能,可维护性等几个方面达到要求的C++程序员,也是很难找到的。而具备这些能力,同时又具备一些专业领域技术的人(图形引擎,网络引擎,等),更加稀少。

所以,即便是大游戏公司,对于C++游戏程序员的需求,也是永远不能够得到满足。而已经在公司工作的C++程序员,不经过短则3个月,长达1年的锻炼,也无法真正胜任独当一面的C++游戏程序开发工作。

2 ,MMO游戏开发对C++游戏程序员要求

前面提到,所有MMO游戏都是中大型软件。软件占用空间,稳定性,性能,可维护性等各项衡量软件质量的指标,对MMO游戏软件的要求都非常严格。远大于普通行业软件。这种规模和银行系统类似。而客户端和软件逻辑比一般的商业软件又要复杂很多倍。这就要求软件编写人员具备较高的程序编写素质。

游戏软件中,解决好软件工程部分,只是项目的1/3。另外两部分是策划和美术/音频。从经验来看,需求变更对于MMO游戏软件,不是偶然事件,而是一种MMO游戏软件开发的基本属性。游戏软件投入大,周期长,风险高。MMO市场变化也大,交互电子游戏发展迅速。游戏软件必须面对外界变动。又因为开发周期长,所以软件需求变动成为了软件开发的一种基本属性。犹如复杂性是软件工程的一项基本属性一样。

这导致游戏软件的开发充满了不确定性。交互娱乐不同于商业应用。娱乐是属于理性和感性之间的领域。而C++开发面对就是0和1的二元世界逻辑。这两个领域存在着不可调和的矛盾。这种情况,对C++游戏程序员提出了更高的要求。

首先,基本C++知识,C/C++运用技能,必须极其扎实。并不是游戏软件开发用到什么平时书本上很难得到的知识点或者技能点。游戏C++开发的知识体系和技能体系,利用现有C++书籍就可以满足。比如《C++ PAORGRAMMING LANGUAGE》《C++ PRIMER》《EFFECT C++》《MORE EFFECT C++》等。但是在开始游戏编程之前,把这些书本吃透并且实践熟练的人,非常难遇到。当然能够真做到这点的人,已经是个中高级C++程序员了。我曾经遇到过一个,毕业工作不久就去了GOOGLE

其次,对于面向对象的深入理解。是非常重要的。熟练掌握C/C++语法,编程技巧,只是满足了C++游戏程序员一部分要求。而面向对象观念的深刻理解,会为大型C++项目开发带来翻天覆地的变化。 有时候,在一个10人以上并行开发的C++游戏项目中,面向对象方法会成为救命稻草。《设计模式》以及《设计模式解析》相关的书籍,也是必修课。

最后,好技术人员的本质是自大的。这属于正常。但是如果这种习性影响了自身继续提高和团队合作。以及影响了其成为技术管理者和项目技术核心时,那么这种技术人员的自身价值会大打折扣。 如果早日越过自命不凡这一关,扩大眼界,继续在综合素质上提高。在技术管理能力,架构能力上提高,其自身价值才会继续增长。落到实处,就是待遇和身家增长。

由于游戏开发的本质是团队开发。任何时候,只有对一个团队有价值的技术人员,其本身的价值才有可能得以体现。

3 ,成长和技术发展路线

一般技术人员发展有几个阶段

1 ,具备独立开发局部功能的能力

比如为某个UI编写逻辑接口函数。为某个LOGIN对话框编写自绘制控件等。

2 ,具备独立开发和攻关某个功能模块的能力

比如为游戏增加一个小型逻辑功能模块。

3 ,具备独立设计并开发某个系统的能力

比如设计和开发AUTOPATCH 系统

4 ,具备解决技术难题,设计架构的能力

比如开发网络同步仿真系统,开发一个中大型游戏制作工具

5 ,具备整体架构,管理,协调其他人共同开发一个大系统的能力

客户端主程,服务器主程,引擎主程等

6 ,技术director

制定技术发展方向,技术团队建立,技术管理等

在迈向每个阶段的过程中,伴随的都是巨大的工作量和工程压力。有时候是跨越1年的失败等等。在公司项目不成功时转换单位,重新开始,或者继续做为核心团队留在公司继续从新的机会做起,都是好的办法。但关键是吸取经验教训,尽量多学多练。并且结合自身长处发展。当然,游戏制作人员,最好还是依靠一个核心团队。成为核心团队的一员。

能够达到第三档的程序,已经是公司不可缺少的人才了。但往往程序员自身对自己的认识,和公司对其的认识,有时候会有差异。我碰到过一些人,脑子好用,写东西很快。各种技术都有涉猎。但总是不放心让他独立开发设计某个系统。哪怕是相对独立的工具。也会被搞得一塌糊涂。要后面人不停擦屁股。可自己还觉着自己水平很高。这种人浮躁,眼高手低,不愿意细致周全的做好一件完整的事。所以就可以看到他不停的跳来跳去,可在新公司的职位也没有见多么提高。公司非常重视交给一个程序员一件事,他是否能完整,考虑周全的把事情做完。哪怕时间长一点,也不能不做完。这会给工程带来致命的后果。

4 ,发展待遇

从自身经验出发谈一下公司是怎么考虑技术员工待遇的。

前面提到的6档,粗略了划分了待遇水平。其实到了第三档,你的待遇已经是这个行业所决定的了。而不是某个公司决定的。因为游戏业大量缺乏这样的C++程序员。如果具备这个水平,在几个大城市游戏公司找到工作并不难。大公司提升慢,还有我这种不到百人规模的公司要。所以行业价格才是公司要考虑的。如果给少了,软件项目的C++程序员流失会带来较大影响。但给的多,其实是C++程序员自己的价值增长瓶颈。如果几年下来一直以为自己水平就该拿这么高,结果到了一家整体技术水平比较高的企业,就会彻底傻眼。这个时候再放低心态去重新开始,对技术员来讲就是件很艰难的事了。

在目前游戏行业技术水平普遍较低的情况下,哄抬程序员工资水平对程序员自身好处也不会很大。就算一个新手本来拿几千的水平,给他1万。他根本就不会知道自己到底有多少水。一年下来也就多拿了3-4万人民币。可耽误的是学习,影响了心态。而那些心态好,知道努力方向的技术人员,干个3-5年后如果有拿期权和股权的机会,比那些一开始虚高的人,身家就不知道高多少倍了。

下面再谈谈我个人在招聘C++程序的体会。

1 做为C++程序员,成长周期比较长。如果是新手(代码量少于2万,没有做过大型项目的),会考察3点。是否踏实肯钻研,有无责任心,以及是否够聪明。如今,满足这三点的人其实不多。

责任心是人品,决定了是否对公司有贡献。这是最重要的。有些人其实很自私。这种人对公司贡献是负数。而且到头来,自身价值也很难起来。因为技术是要靠游戏的商业成功体现价值的。要取得商业成功,就需要一个团队为一件事付出。是否踏实决定了能学会多少技术知识。关于智商,我是最近2年才意识到人的智商确实有很大差别。干程序这行,智商必须越高越好。否则前途不大。

2 如果是有过2-3年C++程序经验的人,应考察的是人品,是否自大,是否有合作意识,是否跳槽频繁。

首先还是责任心。太自私,太为自己着想,时刻把自己利益看成最重要的人,到哪里都不会受欢迎。无论他技术有多好。

然后考察的是是否自大。人最容易自大的时候,往往是对一门技术已经入门,取得一定的小成就。但是眼界还没有开阔,没有领略到这个领域真正深入的技术知识。周围缺少好技术的人。这个时候,技术人员都容易自大。适度的自信和自大是允许的。但是目空一切就完蛋了,说明这个技术人员的提升空间很小。

合作意识是游戏开发的关键。包括交流能力,思考和解决问题的思维方式。一个喜欢独来独往的技术人员,在游戏团队里是个很可怕的事情。因为游戏软件不是一个人能够完成的事情。由于逻辑复杂,需要各种专业技术领域知识,需求变动频繁。每一步都需要团队通力配合。缺乏这种意识,或者对团队开发不适应有抵触的技术人员,在游戏开发领域存活的希望不大。

做为一个C++程序员,跳槽频繁的履历是很致命的。做C++时间长的人都知道。进入一个庞大的C++软件工程本身就需要不少时间。经过培训,项目熟悉,在为项目做贡献,这个时间短不了。如果一个人经常跳槽,说明他一直没有踏实在一个项目里深入做过核心的东西。或者做失败一个马上跑掉。这种人公司不敢要。

3 对于有专项技能的程序员,比如图形程序员。C++只要入门有培训空间即可。但对专业要求比较高。应该是已经在某个技术领域钻研比较深。 当然最后在公司还是得成为使用C++熟练的高级程序员。因为任何专业领域的技术如果要应用到工程中,还必须用C++做工具。

4 好的C++游戏程序员,其实不容易找。如果他干得好,早就成为项目核心成员。如果项目不错,自身待遇也会很好很稳定。不需要通过一般应聘渠道应聘。不是被拉到公司做核心技术拿期权,就是自己创业。

这里我打个比方。网易有个云风。大家都知道他是大话西游2的客户端主程。他是中国第一个做开源C++游戏引擎的人。开放了一整套C++游戏引擎代码。这是他大学时做的。毕业后去网易。有了平台,做成了中国历史上最成功的MMO之一。做为游戏技术人员,他的价值可以说已经是很高的了。到底有多高,我们都不好瞎说什么具体数字。但可以这么刨析一下。

一个经验丰富的C/C++程序员。有过中国自主研发在线过百万游戏的成功项目经验。目前有网易出钱让其独立领导队伍搞引擎和游戏产品已经快3年。这样的一个履历,经验,本身就价值很高。他在任何公司都可以找到年薪几十万的工作。如果他具备管理才能。哪怕就是项目管理,或者技术管理能力。对于一个上市公司,他能做出的贡献,应该用百万/年量级来衡量。如果他能找到一个商业人士,负责舵手,并且自己具备一定商业能力,独立创业。吸引的天使风险投资也得几千万(否则做不了事,当然)。如果产品能做成,身家到达几千万是很自然的事。

我相信中国游戏程序员水平,运气,发展空间比他高的人不多。那么我们可以拿他做个标杆。

我知道很多人不服他。不过这里说的问题并不是关于他本人的。也不需要对他本人做什么服不服的评判。做为一个社会的人,不是靠能写多少行代码,代码多么优雅水平多么高来衡量身家的。从这点说,技术没有转化为成功商业产品之前,它的价值为0。做为技术人员,社会衡量他价值的标准,并不是要去阅读代码是否质量优越速度飞快。而是看他能为一个成功商业产品或者公司发展做出多少贡献。这个道理,几年前我还不太明白。而且我做为一个技术人员,相信多数技术员同胞们都不太可能从根儿上理解和认同这个看法。这里不是评判水平,而是评判价值。你的价值代表了你能够拿到的待遇。这个不是某个老总说了算,某个公司说了算,而是取决于人均GDP和当前行业发展水平,行业销售额的。我想这个道理也适用于所有游戏制作相关人员。搞制作的都是技术人员。