2019年3月8日星期五

领导力,是我接下来需要去努力的方向

背景

2018年11月,大概是我一个非常重要的转折节点,在原单位当了8年多的项目经理,因公司业务调整,成立了子公司,我被抽调进入了产品岗,成为了一名产品总监,这并不是什么手握大权的大官儿,你大概可以理解成小组长,甚至目前可以管理的人员数量和项目经理相比,都微不足道。
子公司从事的是线下电商数字化的业务,主要的商业服务对象也是我们集团的主营业务实体,它本身并不是从零起步的,已经经历过大概四代核心领导层的换帅,最终由我过去的老板,也是我现在的老板来接手。所以当它出现在我面前的时候,已经是一个200个人规模的大公司了。
感谢我直接上级(后称“我的领导”)的赏识,我才有机会在职业生涯中,跳过产品经理的岗位,直接变成一名产品总监,这种独特的职业履历,也正是我今天来写下这篇随笔的原动力。

我的履历

虽然我没有实际当过一天的产品经理,也没有以产品的身份实实在在地实操过互联网业务,但是通过观察和学习,我发现互联网从业人员应有的能力和我这种半路出家的人,思维模式上并无二致。
我先做一个自我评价吧,主观地讲(可能存有自我偏见),我是一个:

  • 标新立异的人,习惯于回到问题的原点进行思考
  • 勤奋愿意解决问题的人
  • 执行力很强的人
  • 共情能力还不错的人
  • 有点完美主义倾向的人
除此之外,我的专业是计算机,也从事了十几年软件研发工作,期间是啥缺干啥,从写代码、PS、文档、PPT、摄影等都得会一点。大概也是我的这种习惯的行为模式,导致我总是能在解决眼前的问题的时候,以简单直接的方式直截了当。
举个例子:前年公司搞年会,要想做个人脸识别的签到,我的同事会人脸识别,他主要负责搞定核心科技,而我就得去弄个摄像头啥的。既然是年会吧,你干巴巴地放一个摄像头肯定是low爆了,所以当时我大概花了10块钱就把这事儿办的妥妥的:
  1. 找到一张小黄人的图片,在它的两手之间PS了一个横幅,然后把它交给打印店
  2. 将打印好的小黄人剪下来,然后将小黄人的眼珠子拿刻刀划掉
  3. 然后把摄像头放在小黄人背后,整个摄像头就隐藏起来了
这大概就是我。

我的内心

上面这样的例子,虽然一点都不难,但是要做出来,我认为至少有几个要素:
  • 愿意去把事情做得尽可能更好
  • 对这个集体和目标有更多的热爱
  • 把事情的结果和自己的个人品牌建立关联
  • 动手能力要过关
我的过去如此,大概我的现在也如此。
作为一名下属,我觉得是我这种遇事迎头解决、全力以赴的方式,让领导一次又一次更加信任地将事情交给我。但是我不是万能的,我一定有解决不了的事情,这时候我的另一个经验就发挥了作用,我会尽力将我的困难及时地向上反馈。从协作网络的角度讲,我应该算是一个合格的网络节点。而这些认知,也大概变成了我对别人的期待:
  • 在成为一名专家之前或者同时,你需要成为一个优秀的网络节点,这样才能在一个组织网络中,让组织的效用最大化
  • 既然是网络节点,就需要快速、准确地传递信息,不论是你能做到的,还是不能做到的,都需要及时反馈
这就是我内心的一些价值主张。

新公司

回到我的新公司,一个既新又充满历史的组织,新是因为对于我是新的,顶层boss是新的,管理思路是新的,旧是因为人是旧的,思维模式是旧的,具体执行的组织结构是旧的,遗留的系统是旧的。
这里的新旧,不是我作为好坏评判的标准,所以暂且忘记哪些是旧的,哪些是新的。
单纯讨论公司的架构,可能需要我铺垫太多跟公司相关的背景知识,你才能做更进一步判断,那么我就从我们做出“产品”的团队,来向你描述我们的组织形式。
我们的产品,大多并不大,从形态上,你可以理解为像微信这样功能相对不是特别臃肿的形态,从用户规模上,你倒是也不用太在意,如果数量庞大,大概公司也就不会经历四轮换帅了。还有一些产品的形态,像是一个短期的活动,你类比一下美团搞个朋友圈裂变?又或者是一个在线抽签的小程序?虽然外在形态上不复杂,预期用户规模也不大,但是因为历史原因,我们有面向几亿用户的架构设计,我们的服务之间也是尽可能松耦合。如果公司是一步一步发展成现在这样的,我们大概会称它为过度设计,但既然是已成事实,那现在倒是也是一套不错的规范。
在描述组织形式之前,我花了这么一大段来写产品的目标,是因为我认为组织之所以有各种不同的形态,是因为没有一劳永逸的组织,它是人和目标之间妥协后的一个结果。
现在的组织形式分两个维度,按职能分:
  • 产品团队:定义产品、设计产品
  • 研发团队:前端研发、后端研发、大数据研发、算法研发、测试、外包
  • ------ 没有运营?对,目前并没有,所以谁操心谁来……
按产品分:
  • 产品1:产品总监、产品经理、研发、测试
  • 产品2:产品总监、产品经理、研发、测试
  • ……
  • 在最顶上还有一个领导,负责这个事业部的战略、资源、决策、对外撕逼等
但是完成最终的产品除了上面这些同学是不够的,前面介绍过,我们是一家大公司,有面向几亿用户的架构,所以在我们事业部外,还有UED、大数据团队、服务器管理团队等,这些也都可以理解为基础资源。
够了吗?还不够的,因为我们的产品也不是孤立存在的,我们一个事业部下面的产品1、产品2,可能是互斥的,可能是互补的,目标通常也都是服从事业部总体战略的,但整个公司,其实有一个更宏观的战略。就我们公司而言,我们对外统一有一个小程序,而我们的产品1、产品2,当然也不是所有产品,大部分也都是在这个小程序下面的,你可以理解成不同的功能或者模块。而这里说的小程序,是另一个事业部。
至此,我所描述的关于组织形式,甚至包括我们的“地形”也和你描述清楚了。

现状

我觉得任何主观地评论都不如客观地陈述更适合我这种管理学菜鸟,但我可以把我看到的写下来,咱们一起讨论。

案例A:

现在产品经理会负责定义产品,并获得产品总监的认可,然后和研发、测试的同学宣讲,研发的Leader会同意研发的同学接手这个项目,并自行确认研发细节和产品的同学沟通,同时测试的同学会形成测试用例,并和产品的同学进行确认。前面提过,我们没有运营,而且我们的产品同学表示,我们不会。
虽然他们嘴上说不会,但是他们可能更多想要表达的是不愿意,他们所指的运营,可能更多的是产品上线后的推广和使用。至于产品形态在实际生产中的应用,他们脑子里有个简单的雏形,也基本都通过实际行动体现在产品中了。为了便于读者理解,我这么类比你可能更容易理解。以一个公司撒钱发红包的例子来说,用户需要扫一个二维码,然后微信发个红包给用户,这里需要有线下二维码,他们会在大街小巷出现,它应该是呈现在一个易拉宝上面的,然后放在路口而不是放在垃圾桶后面。到这里,我们的产品同学大概都能想明白,但是,具体这个产品,是否要有个活动主题,是应该结合春晚还是结合元宵晚会,奖品是每次扫码都给吗,还是扫几次给一次,还是多试试做个ABTest?这些是我们的产品觉得不应该去思考的。
这大概是关于如何造出产品的一个案例。

案例B:

产品总监(我):我觉得有个问题咱们讨论一下哈,咱们这个项目虽然形态上是要发红包出去,但是我们其实对收上来的数据是有要求的,我们要求同一个用户,要领多次红包,这样的数据才对我们的数据建模有帮助。我们之前有个假设前提,是用户都是贪婪的,用户会到处去找不同的二维码扫,但是用户第一次在我们的产品里面领取到红包后,我们并没有任何提示让用户去扫第二个,那么按照大部分产品,比如支付宝的用户习惯,用户可能扫完就走了。因为线下活动的条件限制,我们只能在收银台摆放我们的二维码,这就导致这些二维码的曝光率会大大降低。既然是收银台,那么正常的用户行为,可能是一次游逛,仅去了一次收银台,那么用户去下一个收银台就缺乏动机,我们就得把这样的动机,在我们的产品里面表现出来,我们不指望那些不喜欢钱的用户去领,但是我不能让那些其实想要领钱,却因为我们没有告知他,导致他压根不知道居然还能再领钱的事情发生,举个简单的例子,我们在领到钱之后可以给一个用户提示,让用户知道。从这点讲,我们现在还有需要改进的地方,否则真的数据收上来,质量不行,咱们这笔钱就白花了。
产品经理:我们现在的产品就两个页面,没有地方可以加什么提示了,真的加了,也没有人看的。
产品总监(我):我只是希望你想一想这个问题的解决方法,不一定是我说的在扫码后加个提示。
产品经理:我觉得你想要让数据有效,你就得砸钱啊,你说数据不好看,你就砸时间长一点,你现在只有两万块钱,我当然没有办法保证质量,我觉得有人扫这个红包,这个产品就是个好产品了。
产品总监(我):你知道我们现在客观情况是不可能无止尽砸钱进去,而且好像并不是钱多钱少的问题,而且我的权限也改变不了这个钱的多少。但是我觉得目前这个产品有很多可以做的事情:
  • 在你的扫码二维码上,把咱们缺失的信息传达出去,也是一个简单实际的方案
  • 在你的页面末尾加个提示,也是可以的
  • 在你的页面前置一个今日扫码资格次数,也是电商常用的伎俩
  • 或者你做个应急预案,咱们就算现在不改产品,也可以在上线后实时监控数据,如果数据不行,我们可以把这批用户的手机号拉出来,给他们群发短信告诉他们还可以再去别的门店领钱,这也是个方案,不过如果要这么做的话,我们现在就得提前让研发的同学准备查询语句、找短信网关的同学去协调资源,到时候怎么看,什么时候需要启动这个策略也都需要提前明确。
我们估计也只有这么一次撒钱的机会,我们都不希望这个东西因为数据不行再做第二遍,如果真的到了那一天,人家只会认为我们的产品有问题对吧?
产品经理:继续辩解……短信也没人看、不会领的人就是不会领、第一次数据我觉得不好很正常、一开始让我做这个的时候,我就提出来了,这个东西不可能数据会好,你又没有钱,你要做这种砸钱的产品,你有钱了再说,你想要数据好,你就多申请点钱啊。
产品总监(我):就这样吧,我觉得咱们上不上线感觉意义不大了……
产品经理:最好别上
产品总监(我):(冷静了一会)你这么理解啊,如果用户扫一次,我们算是解决了拉新的问题,但是第二次、第三次再扫,其实是解决我们产品活跃度的问题,如果我们大部分数据没有这样的活跃度,我们的这个方案,就还需要去优化。
就这样一次又一次地循环讨论,然后大概在我的领导路过之后,这个话题变得缓和了一点,后面会怎么样我还不清楚,我非常期待有一个比我想出来的方案更好的方案,或者哪怕是上面的方案,也尽可能落地一点。
这大概就是一次真实的交流,当然,有时候我会被说服,因为人家说的很对,我也虚心接受,或者在讨论时,我意识到自己追求的那一点完美,似乎无伤大雅,我就自动终止了。

案例C:

产品总监(我):嘿,我也不太清楚你们实现后的细节,你给我说说憋。
前端研发:好啊,我给你说一下,%*&(**(……)*——
产品总监(我):对哦,我确认一下,这个LBS信息你记录了没有啊?我要手机的LBS,你们不要弄错了哟。
前端研发:哦,这个我不知道啊,不是我记录的,是后端的同学。
产品总监(我):那你回头帮我和他说一下吧。回头如果我们被薅羊毛了,这个数据可能会很有用。
前端研发:记录这个干嘛,咱们产品是为了发红包,这些无关的就不要了。
产品总监(我):呃%%%%%,再见

这里我做个检讨,我们产品团队,并没有在一开始,刻意去强调应该记录的内容、字段,以及这些数据的用途,可能我们讲清楚了项目的目标、暴露给用户的功能,却漏掉了最后在后台要做分析所需要的这些素材,但这些数据一旦没有存,在未来想要复盘的时候,将出现重大的缺失,虽然凭借我们的聪明才智,总能把后续的“总结”工作做得很完美,但我还是希望未来将这部分需求定义,也作为前期沟通需求的一部分,提前加进去。
当然,上面这位前端的同学这么说,除了因为和我太熟了之外,也客观暴露出一个问题,那就是前端潜意识认为,我没有做错什么,因为我做的都是产品的同学让我做的,所以我不接受修改。

故事先讲到这里,这大概就是我所要破的局。
你有什么高见?

2016年3月6日星期日

Markdown

Markdown作为流行的标记语言,已经火的一塌糊涂了,你只顾写你的,反正标记就那些,然后剩下的交给转化软件和CSS去格式化吧……
GitHub上的READMD.md足以证明它火的程度。

The key design goal is readability 
Markdown理念:

  1. 简单写、容易读
  2. 字符化
  3. 极简主义

Markdown原理:

  1. 标记语言——by Author(人)
  2. 转换程序——by Markdown Program(各种Markdown程序)
  3. 最终呈现——by Viewer Program for Humers(HTML/pdf/txt/RTF)

Markdown展示:(by Ulysses)



不同的Markdown系统Markdown标记也有所区别,不过都大同小异,找一个适合自己的即可。

Markdown收益:

其实HTML也是标记语言有木有,不过因为它被掺杂了太多的样式、脚本,显得不太纯粹了,而且是基于xml的语言,天生冗余就会比较多,如果你打算在写文章的时候自行html,那你不仅要学习html还要花时间在每一次敲击标记这件事上。
Markdown则简单地多,它尽量只表达最简洁的那些样式,剩下的事情,交给程序去做吧。
所以当你开始写它的时候,请不要回忆那些生成的效果,标题就是一个#,段落就是两个##,请不要像我一样,把两个星号表达为**粗体**,而应该叫它为强调,至于你用粗体来表达还是用斜体来表达强调这件事,都是后面的事情了。

Markdown与可视化编辑:

有了上一节的铺垫这一节就容易多了,Markdown强调的是事情本身,作者认为重要的内容,就打上**标记,中国的读者,喜欢用粗体表达重要,美国的读者可能喜欢用斜体表达重要,没关系,作者不用为不同的用户写两遍。
而可视化编辑器,不论是在线编辑器还是Microsoft Word在你看到它的杰作之时它就已经定型了。

但是,就单纯从方便的角度,则是仁者见仁的,毕竟我们还是喜欢直观的东西,但这丝毫不影响Markdown成为一种选择。

Markdown延伸玩法:



在此引入两篇文章:

  1. 一篇导引文章,简要讲述了一些简单的标记:http://markdowntutorial.com
  2. 一篇非常好的文章,不仅讲了Markdown的来龙去脉,还说清楚了它的工作原理:http://lifehacker.com/5943320/what-is-markdown-and-why-is-it-better-for-my-to-do-lists-and-notes
引用文章里面的一个Web Markdown系统,供大家练习:http://hashify.me/




2016年3月4日星期五

如何编译MongoDB?

本文将在Linux环境下编译Mongodb。
您可以选择已经编译好的版本直接使用,也可以尝试自己编译。https://www.mongodb.org/downloads#production


动手开始:

1、Linux,本文选择Ubuntu 14.04 LTS 64bit,下载地址:

2、包依赖:编译器 gcc g++ clang 安装方式:

# sudo apt-get install gcc (4.8.2以上版本)
# sudo apt-get install g++ (4.8.2以上版本)
# sudo apt-get install clang(3.4以上版本)

3、包依赖:python (2.7以上版本) 安装方式:

# sudo apt-get install python

4、包依赖:scons (2.3以上版本) 安装方式:

# sudo apt-get install scons
5、包依赖

# sudo apt-get install aptitude
# aptitude install scons build-essential
# aptitude install libboost-filesystem-dev libboost-program-options-dev libboost-system-dev libboost-thread-dev

6、源代码:从GitHub上面下载:https://github.com/mongodb/mongo 直接选择一个分支,右侧Download Zip,解压缩到目录:

# mkdir mongodb-master-src
# unzip mongodb-master.zip mongodb-master-src/
# cd mongodb-master-src/

7、新建一个 version.json 文件在 mongodb-master-src/ 目录下:在大部分能搜索到的文档中,大家都是直接下载好后就编译,但是会报一个scons错误,原因就是因为缺少这个文件。

# gedit version.json
然后输入以下内容后保存: 
{
    "version": "0.0.1-fake-"
}

8、编译源代码:
# sudo scons all -j 4
这里-j 4 是指你所使用的CPU核数。也可以直接:
# sudo scons all  
或者仅
# sudo scons mongod
# sudo scons mongo
# sudo scons mongos

9、编译后验证,执行下面语句,你将看到版本提示信息。

# ./mongod --version

10、编译后配置,新建相关目录及配置文件
# mkdir mongodb_sample
# cd  mongodb_sample/
# mkdir bin
# mkdir data
# mkdir log
# mkdir conf
# cd conf
# gedit mongod.conf
在打开的端口内输入:
port = 12345
dbpath = data
logpath = log/mongod.log
fork = true  
其中:port代表访问该数据库的端口号,fork表示是一个后台进程。

11、复制编译好的文件到bin目录
# cp ../mongod mongodb_sample/bin/

12、启动mongod:
# cd mongodb_sample/bin/
# ./mongod -f conf/mongod.conf
13、检查log和data目录将看到文件夹内有新的文件。
14、停止mongod,这里因为没有连接到mongod服务器,所以直接使用kill的方式进行关闭,关闭的时候,不使用kill -9,可以使用kill -15:

先查找进程ID:
# ps -A | grep mongod
然后
# kill 32759
关于kill命令后面的参数,详见:https://en.wikipedia.org/wiki/Unix_signal#SIGTERM

2016年2月29日星期一

Hadoop技术内幕——深入解析MapReduce架构设计与实现原理 读书笔记(1)


Hadoop 1.0.0 源代码阅读,需要先安装以下软件。
很可惜,即便一切照做了,导入的文件也各种报错。

1、Java 1.6.0下载
http://www.oracle.com/technetwork/java/javase/archive-139210.html

2、Apache Ant 1.6.0下载
http://archive.apache.org/dist/ant/binaries/
http://archive.apache.org/dist/ant/binaries/apache-ant-1.6.0-bin.zip

3、Eclipse下载
http://www.eclipse.org/downloads/packages/release/Galileo/SR2
http://archive.eclipse.org/technology/epp/downloads/release/galileo/SR2/eclipse-jee-galileo-SR2-linux-gtk-x86_64.tar.gz

4、Hadoop 1.0源代码
http://svn.apache.org/repos/asf/hadoop/common/branches/
http://svn.apache.org/repos/asf/hadoop/common/branches/branch-1/
https://archive.apache.org/dist/hadoop/common/hadoop-1.0.0/
https://github.com/apache/hadoop/tree/branch-1

2016年2月15日星期一

Google的Bigtable学习笔记(不保证正确性)

Google的Bigtable学习笔记(不保证正确性)
1、首先是一个列式存储的简单数据模型的数据库,它比键值对模型/文档模型NoSQL数据库复杂点(也就更强一点)。
2、它的分布式存储性能依靠于GFS也就对单机房网络有硬性指标。
3、它同时提供了相对均衡的顺序读写操作,也就更适用于这样的应用。
4、保证SSTable不变的结构简化了读写冲突所产生的问题复杂性。同时允许不同的tablet共享一个SSTable。
5、memtable的设计减少了大量的读写冲突,双线程+序列允许归并写入,鉴于较小概率的读恢复操作,major compaction在排序时候借助写时候留存的序号进行去重,简化了写操作。
6、高级别的缓存针对访问相同数据进行的缓存服务比较容易被想到,但是块级别的缓存解决了顺序读的读写效率,是值得学习的。
7、因为row key是依照字典序进行排序的,所以在应用级别对row key的选择就是设计的一个重心。
8、字典序的设计对跨行更新以及分布式事务都提出了挑战,但是这个系统并不适用于解决类似的问题。
9、提供了无限的列结构以及column families,是它强于键值对模型/文档模型NoSQL数据库的地方,等价于自建了各种索引。也就是所谓的半结构化数据。
10、Tablets服务器对于主服务器的依赖较低,因为主服务器仅与有限的Tablets服务器进行通信,只负责解决它们的生存问题,而不用解决直接的来自于用户的请求。
11、利用Chubby进行分布式锁机制,使用了文件句柄的冲突检测来实现对于分布式服务器的管理,并配合了主服务器对Tablets的心跳检测,实现了完整的检测,在加上自杀和他杀技术的使用,使得整套系统得到了较高的可靠性。
12、两段式压缩对于类似于不同的时间点对相类似的数据进行存储后的压缩能够做到较好的压缩比,因为内容重复度比较高。

http://research.google.com/archive/bigtable-osdi06.pdf

2016年1月27日星期三

软件开发到底是怎么一回事呢?

人生得一良友不易,友人是做数据库DBA(运维方向)出生,对软件开发算是没有什么经验,但是最近手头却有点儿事让它对软件这件事开始有了兴趣。于是就问我这个问题。我呢,水平很差,这么大的标题丢过来,怎么回答呢?好在友人给明确了方向:
代码管理,版本控制,补丁管理,架构设计,模块划分,接口设计,报错编码制定,日志设计,测试方法,安全管控,性能规划
然后我就根据这些,作答如下,既然写了这么多,就拿出来和大家分享。

1、代码管理,版本控制,补丁管理
对于单一产品的公司,其实问题就是各种迭代和这些迭代的管理。
首先是坐下来讨论一下影响我们代码变化的因素是什么?需求、bug,计划内、计划外?
传统的软件管理,通常会把需求分成很多期,然后针对每一期制定版本计划,然后按着计划做。
但是现代软件偏向于敏捷的管理方式,用用户故事将需求分解成不同的场景,进行故事管理,然后通过迭代的方式向前,然后及时修正项目的整体目标。
回到代码管理,我有个原则,就是你不管是需求还是用户故事,在你打开你的电脑开始写的时候,就要明确你在为什么功能而coding,然后你每一次提交版本必须和你的代码库,task(一种集成在项目管理工具里面的任务,你也可以理解为excel里面的一行需求)一一对应。比如你今天就是做了一个接口,接口只完成一个功能,比如修改密码。那就写清楚你在做什么,然后和你的需求哪些相关。简单地说,就是每一次提交是一个原子提交。然后提交的时候,至少需要保证你的代码是可以编译通过的。
版本控制呢,通常需要考虑到分支的管理和标签的管理。其实我有一个保证它安全的好办法,那就是不用版本控制工具。它们不如复制粘贴/压缩包来的可靠。如果你确定一个分支要发布,首先你需要用版本工具进行分支发布,然后针对分支的补丁就在上面继续,然后适时往主分支合并。但是于此同时,请做一件事,将它们下载下来,把它压缩起来,然后放到一个文件服务器上。然后一旦出现问题,找个文本比较工具,你通常就豁然开朗了。
补丁管理这件事,刚刚也提到过了,你真对哪个版本出的问题,就在哪个分支上面去改,然后适时合并,适时当然是你在差异没那么大的时候做是最好的。
这里插一句题外话,敏捷的核心我个人认为不是在怎么说清楚用户故事,而是你要有单元测试,没有这个都是扯淡……当然其它也很重要,但是UnitTest是必要级别的。这也就是外包软件行业通常做不到敏捷的一个重要原因,因为不是那么容易做到。

2、架构设计
架构设计这可不是那么牛逼的一两句能说明白的事情,不过有几个个人认为还是比较重要的原则。
a、适度设计,其实拿捏这个度,何其难,在一个人开始看待一个问题的时候,自然就有自己的观点在里面,你的视角一定不是世界的中心,那么合理拆分就可以了,本着实用主义的精神做架构设计,通常能在成本、智力等方面都能取得一个还不错的平衡。
b、合理,其实面向对象编程最牛逼的地方就是让一段代码试图去模拟一件事的本身,这就像数据库设计里面的关系表一样,它一定要表达的是正确的关系,那么哪怕它性能上有缺陷。这些其实和什么代码可读性等都是相通的。这就是为什么大部分人都认为多线程程序会比较难,因为它通常不是人类思维。这样的合理设计通常从数据库的设计上面就开始影响你整个复杂度了。这一条通常随着架构师见识和对问题的理解程度不同,在项目进展的不同时期会有不同的体会,一开始合理的东西,在项目后期可能就不是那么回事了。
上面说的都是废话,因为不具备操作性,就是在你要做决定的时候去回想一下才有帮助。那么有什么规律可循呢?
其实通常我们都是习惯带着问题去解决它们的,比如你的性能要求很高,你要求达到一个特定的SLA,那么你在开始选择技术和框架的时候就要在这些方面都比较小心,然后用你熟悉而不是你似懂非懂的技术来解决,这样就算出问题,你至少能知道怎么去思考这个问题,而不会去怀疑那个东西不靠谱。然后就是包括所有影响这些的点,既然说的是性能问题,那么数据库、索引等都是需要考虑的,还有一些可以从业务上分开的,也可以从业务上解决,比如明明一个页面用户只想看到一个数值,但是你总是在页面上带一个大列表,而大列表刚好又查询了一个大表,那么这个页面必定有问题。

3、模块划分
模块划分其实就是你把你的功能合理分拆的过程,你能把你们家的主卧、次卧、厨房卫生间拆分开,你能搞清楚为什么电商分类里面不会把电风扇放到数码产品里面,就说明你掌握了模块划分的基本规则。这些都是纵向划分,按照领域进行细分。
我觉得你这里是不是想要知道的还包括分层管理,软件是个上下叠加的层次结构,其实从你下面跑的硬件到操作系统这一层级通常被做好了,然后就是做好你的软件的部分,所以接触你的操作系统的通常是软件公司给的各种框架,比如.net framework和java虚拟机等,然后就是那些架构框架,什么asp.net、servlet等,这些都不涉及到你的业务,通常是解决了技术层面的问题,然后你现在看到的成熟的解决方案通常都从界面开始(也许是个接口,总归和外界有个交互),然后从这一层中向下,到刚刚那层底层框架之间就需要你自己来分了。看看你是不是需要访问数据了,比如数据库,不管是sql还是nosql,总归需要去联一下了,这里多是考核你层间接口的设计能力,然后你想象你设计的接口就像插座上面的标准插口一样,上层不再关心下层的实现细节,如果下层有问题,让下层去改好了。然后一层一层往上剥离,就到了你刚刚想要做的对外的那个界面了(也许是接口)。什么三层架构什么的,也只是对这些的一个大致归类。
不过按你的思路,也许你的脑子里是个VisualStudio里面的Solution的Panel,你想知道的是一个大的解决方案中各种程序集(dll/lib)的分类方式,那么你回到你最熟悉的Windows/linux下面好了,负责网络的就是网络驱动,管它怎么实现的,我反正负责网络的,你找我就可以了。然后负责IO的,就负责IO就好了。程序集的划分差不多也就是这样的,以SSO举例,加解密我们会有单独的模块,然后做具体业务逻辑的也会有,然后一些辅助的小代码(比如查一下ip地址啊什么的),大概也就是这样一点点分出去。

4、接口设计
上面的很多思路其实在接口设计中都是相通的,其实就是职责分明,一个接口尽量完成一个原子操作,不要完成很多件事,除非你把它当作一件事来做。这个粒度的把握也需要思考清楚。比如修改密码的接口,你就不要再加入重置密码的逻辑,哪怕你背后的代码恨不得调用同一套,也需要暴露两个接口。接口之所以被设计出来,就说明它是相对稳定的,任何对接口的修改,都是一次玩命,原则,约定的功能是不可以减少的,哪怕是不合理的,这个才是接口最难的地方。就像你发布了电灯底座接口,然后全世界都在为你生产电灯,然后你说不行,圆的你不喜欢你喜欢方的,我改了哈,然后,你懂得,上街不要被人打。那么接口的设计就非常需要合理,哪怕你留下一个没有用的参数,内部你压根不用,你写死都可以,但是一定要合理,只有这样,未来使用这套接口的标准程序才不会受到影响。然后单元测试的思想就很重要了,接口永远要保证之前测试的场景在每次升级后还能正常被跑过,否则你的接口随时有可能产生涟漪反应。
5、报错编码制定,日志设计
万物归本,这件事就是你确定一个列表,然后把它吐出来的过程,Windows那么多弹错,无非也是一堆编码,出了问题到kb里面一搜就出来各种编码了。至于这个规则是按类似手机号或邮编的编码方式还是按照条形码的方案来,这个仁者见仁场景也不一样,哪怕你毫无规律地来编,它们都只是起到了一个Id的作用。
这里可能需要提到的一点,这个编码和日志设计通常都在一起,其实在你程序需要记录的时候,哪怕你觉得它八百年才会发生一次,你也要需要给人一个合法的编码和完美的解释,那么你就不至于当系统弹出“有错”的时候,你一看有十几处一样的错误。我倾向于错误始终唯一的方式。
在现代软件编程中,可以借助AOP的思路来将它们收集起来,这个思路和程序横向切片差不多,它在代码上的体现通常是,你的代码明明只是做了业务逻辑,但是它自动会帮忙记录日志,而且能告诉你到底是哪个程序第几行在什么地方干了什么。当然这个也是有代价的,就像你在水龙头上安装了过滤器,那么水流自然要小一点。
现在有nosql了,海量存储变的更方便了,然后分析这件事借助离线计算的方式,总归是能算出来的,但是记得,一定要把信息尽可能多地记录下来。

6、测试方法
传统的测试当然非常重要,什么冒烟测试、用户验收测试、回归测试、集成测试等都非常重要。
这里要提到的更多的是自动化测试,虽然我在项目中很难用到这一点,但是它的思想我非常认同,因为它是用代码来测试代码,代码是什么,是你经验的积累,你找个妹子上去点一遍,点的过程就是经验,你让妹子点20遍也许妹子能朝你踹一脚,但是代码一旦完成,只会越来越趋近精确。现在软件工程上面对类似界面点击这些都已经有了成形的工具,但是说实话国内软件业掌握的还不怎么样。当然也因为有很多不完善。
通过持续的反复测试,说白了不管是人还是机器,更多的经验和体力投入都能获得更好的效果。

7、安全管控
安全管控,现在安全组做的那些事情,包括用安全工具来扫描、找红帽组织来,其实都是基于行业经验来做到监理的角色。当然软件开发,本质还是一个智慧的事情,比如你家盖房子,你知道安装了窗户,需要有锁,而且锁必须在房子里面,不能在外面,低楼层需要安装防盗窗,防盗窗必须比一个正常的人要窄,这些都是经验。有很多现成的经验,需要在程序员开始干活之前就要掌握,其实不应该假设程序员什么都懂,其实他们很萌的。我刚开始写web的时候,那个时候没有往安全方面去想,因为之前一直做的是windows界面,不同窗口之间无所谓安全的事情,但是做web的时候,真的做了那种除了登录页面之外的页面也可以不要登录,敲个地址就能进去的low事儿,后来自己发现了,才从web的原理着手去了解了这样的问题,但是这个事情,终归是个意识和见识问题。大部分不干坏事的人不知道怎么干坏事,所以大家还是需要多学习。
然后就是一个好的基础框架,开发规范,很多公司程序员并不太了解这些,但是它们也不出轨,比如单点登录就帮他们解决了这个问题,因为架构上要求一个用户至少是登录的。
这里特别要提到接口,通常很多人做完接口就不管安全了,因为它不好测,也看不见嘛,但是这一块通常需要被重视。不过像什么WebService的标准里面都有一整套安全规范,当然除了大公司用之外,大家可能掌握的也不多。

8、性能规划
性能,是个数学问题吗?你先知道一共有多少的性能压力,你把小轱辘的轮子放在卡车下面自然是承受不了的。现在比以前好多了分布式计算让性能从单一计算机性能瓶颈上分解出来,但是分布式。。。。通常适用于可以分布式的事情。。。
其实在我们常见的场景中,无非是web性能和数据库性能,web性能现在大家都是用负载均衡来分开的,其实,很多时候傻逼的程序员干的蠢事需要服务器cpu来买单的事情也不少见。性能出问题,大多出现的问题,比如耗时的程序在工作,比如网络慢了,进行IO操作了,访问数据库了,跨边界的操作通常容易导致性能问题。比如访问内存的速度通常和访问数据库都不是一个量级的。那么在一个for循环里面访问数据库就是一个比较不合适的做法。那么一次性读取后再for也许能帮到你,当然也不是所有的场景都如此。还有就是良好的算法功底,比如一个循环的算法复杂度是O(n),而一个哈希表的算法复杂度是O(1),通常大家都不需要自己去写这些,但是选择合适的数据结构来处理问题,变得很重要。
至于你说你的服务器应该买多牛逼的,那我就不知道了,压力测出来之后,看着买能买得起的最贵的,然后调程序去吧。














2011年12月5日星期一

过程与结果之于文档

平生见过的文档不多。个人认为一个过程中的文档应该是一个做事的书面化。格式、范围也都是用来完成「做事」这个目标的。明确了目标就容易了。
有人说,有个文档,描述结果就可以了。这里的结果不是最终的结果,而是中间结果。举个例子,今天内幕提高准备金,你让人正飙涨的股票火速抛售。于是你就跟人说:全抛!大概就是这样。
就这事,有几个风险?
1、他信不信?
2、消息准不准?
3、他有没有其他干扰?
第一点,明明疯涨,为何要抛?你被怀疑羡慕嫉妒恨!
第二点,消息准吗?会不会是假消息?中途有没有变数?万一继续涨,怎么跟人解释?
第三点,你确定他一无所知吗?他是否比你知道的还多?万一你们的消息有冲突?
看到这个中间结果,问题就涌上来了。文档也类似,你拿到文档去做事却不知道为何这么做,结果会怎样?
文档里一定有很多你都没想到的细节在具体操作层面才会暴露出来。这时候去追诉为什么就显得尤为重要。不仅如此,过程还代表了一种思维方式,阅读文档的人也会因此而获益。当然,文档里的字就多了,但不代表你多想了,因为那些本来就要想。反而那些只有结果的文档不知道是不是灵感乍现的杰作?







2011年8月19日星期五

坏设计下的烂代码无法应对变化

关于成本的系统,之前的结构,我是指数据部分还是有点儿复杂的,为bug埋下了伏笔,但最初期待的功能很多并没有实际作用,后面补充的需求却给这个模型带来了麻烦。是时侯砍掉那些多余的需求了,其实事情本没有那么复杂。之前我们用了类似视图的功能来做,对于查询我们可以无缝集成,不论sql还是代码,但对于插入和修改就必须跟踪数据来源,这仅是麻烦之一。当我们试图去操作excel这个平面结构的时候,操作excel本身就不同于sql,我们根据sql的数据来控制excel,这就存在对数据库的操作以及对数据指令的操作,严格上说我还应该保持二者的事务性,即便这一点已然被忽略了剩下的工作量也并不小。同样是因为excel,自动化测试并不容易做。因为excel是平面的,数据库也是,留下的部分其实都只是一些操作,所以也是我始终不接受所谓的面向对象的方式来做,务实点,这个底层并不适合,起码意义不大。2.0如果要做就一定涉及到领域对象和领域计算(规则),首先业务不简单,要学习,其次,一定要有一套能够支撑计算的计算框架,或者称为计算模型,这完全不同于增删改查,和流程也不是一回事,是个数学模型。如何做我并没有想好。我现在其实比较期望的是简化版的1.1而不是2.0。

2011年8月5日星期五

如何用单元测试避免版本升级隐患

当我们的网站,在运行的时候,你是否考虑过做系统升级?OK,那些安全相关的漏洞,通常不会给你带来太大的影响,但是一些类似.net framework之类的,还有一些第三方的dll,则可能带来严重的问题。你的程序可能有意想不到的后果。虽然Microsoft在版本向下兼容方面做过了大量的测试,但也不见得就能保证你的正确性。你的所有问题,都变得连你自己都不知道了,你只有期盼上帝不要引爆那个炸弹。
单元测试,原本是用来保证代码正确,推动项目前进,描述用户需求的有效工具。但你想,如果你的项目对绝大多数的分支都做到完美的单元测试,你还害怕更换dll吗?版本升级,对你的影响是可控的,你可以重新运行所有的单元测试,并决定是否更新版本。
------------
本文因为篇幅较短,内容较散,所以列入该博客,大家笑笑就是。

2010年11月25日星期四

对于IIS7无法显示htm页面、图片、js脚本文件和样式文件的问题,解决方法

对于IIS7无法显示htm页面、图片、js脚本文件和样式文件的问题,解决方法如下:

Windows 7
开始->控件面板->程序->打开或关闭windows功能->Internet信息服务->万维网服务->常见http功能->静态内容(选中)

Windows Server 2008 R2
服务器管理器->角色->Web服务器(IIS)->Internet信息服务(IIS)->角色服务->添加角色->常见http功能->静态内容(安装)

2010年9月7日星期二

如何取消关闭windows 2003中ie增强的安全配置

添加删除Windows组件,去除“Internet Explorer增强的安全配置”组件即可。

源于http://www.docin.com/p-7372067.html

2010年5月22日星期六

将Windows Server 2008 R2当作Windows 7来运行

System:Lenovo/IBM Thinkpad T400
OS:Windows Server 2008 R2 (6.1.7600)
Requirement:internet connection
Purpose:[Important!]将Windows Server 2008 R2当作Windows 7来运行。
Description:在安装完Windows Server 2008 R2之后需要完成的步骤。


1.安装ThinkPad System Update.
2.因为System Update不支持Windows Server 2008,所以需要修改相关文件后才可以使用.
http://blog.sina.com.cn/s/blog_562fa4b70100gds0.html / (备份)http://blog.sina.com.cn/s/blog_401c7b890100jjkb.html (出现错误提示为:收集用户信息出错)

Windows Server 2008 R2的OS名为:WINSRV2K8-R2

3.至ThinkPad T400页面,用Windows7的驱动替代,至
http://think.lenovo.com.cn/support/driver/driversdownlist.aspx?categoryid=29324&osid=233&description=&count=2&mcid=29324&categoryidThreeNum=
页面打包下载。
4.通过服务管理器->配置->安装“无线LAN服务”,才可使用无线网络。
5.关闭IE每次都会弹出的拦截器,http://blog.sina.com.cn/s/blog_643754960100iwar.html/(备份)http://blog.sina.com.cn/s/blog_401c7b890100jjke.html,方法是打开“服务管理器”,点击根节点“服务器管理器”,然后在右侧找到“管理IE Sec”。
6.然后可以安装Adobe Flash Player。
7.指纹识别
7.1 打开服务管理器,在功能添加中,添加“windows biometric framework”功能。然后在控制面板中就会显示“生物特征设备”项目。
7.2 打开服务管理器,在功能添加中,添加“.net framework 3.5.1”功能。
7.3 常规做法
7.4 结果,设置失败。
8.开启aero效果
系统设置--高级--性能--设置--调整为最佳外观

2009年2月27日星期五

关于自动属性,一丁点,好看不中用,没技术含量

using System;
public abstract class ClassBase
{
public abstract int IProperty {get;set;}
}
public class ClassA : ClassBase
{
public override int IProperty {get;set;}
}
public class Program
{
public static void Main()
{
ClassBase b = new ClassA();
b.IProperty = 5;
Console.WriteLine("i = {0}", b.IProperty);
}
}
因为针对自动属性的{get;set;}简要写法,显然除了abstract和override的差别之外,别无其他。因为没有什么发现,就记录在这里了,不到别的地方去丢人现眼了。呵呵。
1.Save all code as a file named "abstract.gc" or other.
2.Run the "Windows Command prompt" or "Visual Studio 2008 Command Prompt" tools.
3.Setup the compile environment. (Visual Studio 2008 Command Prompt not do this step.)
4.Use the csc command to compile.
>> {path}>csc abstract.gc
5.Run the program.
>> {path}>abstract

【转】程序员的十层楼

程序员的十层楼
转载自:http://softwareblogs-zho.intel.com/author/zhouweiming/

自西方文艺复兴以来,中国在自然科学方面落后西方很多,软件领域也不例外。当然现在中国的许多程序员们对此可能有许多不同的意见,有些人认为中国的程序员水平远落后于西方,有些则认为中国的程序员个人能力并不比西方的程序员差,只是整个软件产业落后而已。

那么,到底中国的程序员水平比西方程序员水平差,还是中国有许多优秀的程序员达到或超过了西方程序员同等水平呢?要解决这个问题,必须先知道程序员有多少种技术层级,每个层级需要什么样的技术水平,然后再比较中国和西方在各个技术层级的人数,就可以知道到底有没有差距,差距有多大。

当然,对于如何划分程序员的技术层级,不同公司或不同人会有不同的划分标准,下面的划分仅代表个人的观点,如有不当之处,还请砸板砖予以纠正。

第1层 菜鸟
第1层楼属于地板层,迈进这层楼的门槛是很低的。基本上懂计算机的基本操作,了解计算机专业的一些基础知识,掌握一门基本的编程语言如C/C++,或者Java,或者JavaScript,...,均可入门迈进这层。

在这层上,中国有着绝对的优势,除了从计算机专业毕业的众多人数外,还有大量的通信、自动化、数学等相关专业的人士进入这一行,此外还有众多的其他专业转行的人士,人数绝对比西方多出甚多。并且还有一个优势就是我们这层人员的平均智商比西方肯定高。

没有多少人愿意一辈子做菜鸟,因为做"菜鸟"的滋味实在是不咋的,整天被老大们吆喝着去装装机器,搭建一下测试环境,或者对照着别人写好的测试用例做一些黑盒测试,好一点的可以被安排去写一点测试代码。当然如果运气"好"的话,碰到了国内的一些作坊式的公司,也有机会去写一些正式的代码。

所以,菜鸟们总是在努力学习,希望爬更高的一层楼去。

第2层 大虾
从第1层爬到第2层相对容易一些,以C/C++程序员为例,只要熟练掌握C/C++编程语言,掌握C标准库和常用的各种数据结构算法,掌握STL的基本实现和使用方法,掌握多线程编程基础知识,掌握一种开发环境,再对各种操作系统的API都去使用一下,搞网络编程的当然对socket编程要好好掌握一下,然后再学习一些面向对象的设计知识和设计模式等,学习一些测试、软件工程和质量控制的基本知识,大部分人经过2~3年的努力,都可以爬到第2层,晋升为"大虾"。

中国的"大虾"数量和"菜鸟"数量估计不会少多少,所以这层上仍然远领先于西方。

大虾们通常还是有些自知之明,知道自己只能实现一些简单的功能,做不了大的东西,有时候还会遇到一些疑难问题给卡住,所以他们对那些大牛级的人物通常是非常崇拜的,国外的如Robert C. Martin、Linus Torvalds,国内的如求伯君、王志东等通常是他们崇拜的对象。其中的有些人希望有一天也能达到这些大牛级人物的水平,所以他们继续往楼上爬去。

第3层 牛人
由于"大虾"们经常被一些疑难问题给卡住,所以有了"大虾"们只好继续学习,他们需要将原来所学的知识进一步熟练掌握,比如以熟练掌握C++编程语言为例,除了学一些基础性的C++书籍如《C++ Primer》,《Effective C++》,《Think in C++》,《Exception C++》等之外,更重要的是需要了解C++编译器的原理和实现机制,了解操作系统中的内部机制如内存管理、进程和线程的管理机制,了解处理器的基础知识和代码优化的方法,此外还需要更深入地学习更多的数据结构与算法,掌握更深入的测试和调试知识以及质量管理和控制方法,对各种设计方法有更好的理解等。

学习上面说的这些知识不是一挥而就的,不看个三五十本书并掌握它是做不到的。以数据结构算法来说,至少要看个5~10本这方面的著作;以软件设计来说,光懂结构化设计、面向对象设计和一些设计模式是不够的,还要了解软件架构设计、交互设计、面向方面的设计、面向使用的设计、面向数据结构算法的设计、情感化设计等,否则是很难进到这个楼层的。

当然除了上面说的知识外,大虾们还需要去学习各种经验和技巧。当然这点难不倒他们,现在出版的书籍众多,网络上的技术文章更是不胜数,然后再去各种专业论坛里泡一泡,把这些书籍和文章中的各种经验、技能、技巧掌握下来,再去学习一些知名的开源项目如Apache或Linux操作系统的源代码实现等。此时对付一般的疑难问题通常都不在话下,菜鸟和大虾们会觉得你很"牛",你也就爬到了第3层,晋升为"牛人"了。

看了上面所讲的要求,可能有些大虾要晕过去了,成为牛人要学这么多东西啊!要求是不是太高了?其实要求一点也不高,这么点东西都掌握不了的话,怎么能让别人觉得你"牛"呢?

需要提一下的是,进入多核时代后,从第2层爬到第3层增加了一道多核编程的门槛。当然要迈过这道门槛并不难,已经有很多前辈高人迈进了这道门槛,只要循着他们的足迹前进就可以了。想迈进这道门槛者不妨去学习一下TBB开源项目的源代码(链接:http://www.threadingbuildingblocks.org/),然后上Intel的博客(http://softwareblogs-zho.intel.com/category/multicore/)和多核论坛(http://forum.csdn.net/Intel/IntelMulti-core/)去看看相关文章,再买上几本相关的书籍学习一下。

在国内, 一旦成为"牛人",通常可以到许多知名的公司里去,运气好者可以挂上一个架构师的头衔,甚至挂上一个"首席架构师"或者"首席xx学家"的头衔也不足为奇。有不少爬到这层的人就以为到了楼顶了,可以眼睛往天上看了,开始目空一切起来,以为自己什么都可以做了,什么都懂了,经常在网络上乱砸板砖是这个群体的最好写照。由此也看出,国内的牛人数量仍然众多,远多于西方的牛人数量,在这层上仍然是领先的。

也有不少谦虚的"牛人",知道自己现在还不到半桶水阶段。他们深知爬楼的游戏就像猴子上树一样,往下看是笑脸,往上看是屁股。为了多看笑脸,少看屁股,他们并没有在此停步不前,而是继续寻找到更上一层的楼梯,以便继续往上爬。

第4层 大牛
从第3层爬到第4层可不像上面说过的那几层一样容易,要成为大牛的话,你必须要能做牛人们做不了的事情,解决牛人们解决不了问题。比如牛人们通常都不懂写操作系统,不会写编译器,不懂得TCP/IP协议的底层实现,如果你有能力将其中的任何一个实现得象模象样的话,那么你就从牛人升级为"大牛"了。

当然,由于各个专业领域的差别,这里举操作系统、编译器、TCP/IP协议只是作为例子,并不代表成为"大牛"一定需要掌握这些知识,以时下热门的多核编程来说,如果你能比牛人们更深入地掌握其中的各种思想原理,能更加自如的运用,并有能力去实现一个象开源项目TBB库一样的东西,也可以成为"大牛",又或者你能写出一个类似Apache一样的服务器,或者写出一个数据库,都可以成为"大牛"。

要成为"大牛"并不是一件简单的事情,需要付出比牛人们多得多的努力,一般来说,至少要看过200~400本左右的专业书籍并好好掌握它,除此之外,还得经常关注网络和期刊杂志上的各种最新信息。

当"牛人"晋升为"大牛",让"牛人们"发现有比他们更牛的人时,对"牛人"们的心灵的震撼是可想而知的。由于牛人们的数量庞大,并且牛人对大虾和菜鸟阶层有言传身教的影响,所以大牛们通常能获得非常高的社会知名度,几乎可以用"引无数菜鸟、大虾、牛人竞折腰"来形容,看看前面提过的Linus Torvalds等大牛,应该知道此言不虚。

虽然成为"大牛"的条件看起来似乎很高似的,但是这层楼并不是很难爬的一层,只要通过一定的努力,素质不是很差,还是有许多"牛人"可以爬到这一层的。由此可知,"大牛"这个楼层的人数其实并不像想像的那么少,例如比尔·盖茨之类的人好像也是属于这一层的。

由于"大牛"这层的人数不少,所以也很难统计除到底是中国的"大牛"数量多还是西方的大牛数量多?我估计应该是个旗鼓相当的数量,或者中国的"大牛"们会更多一些。

看到这里,可能会有很多人会以为我在这里说瞎话,Linus Torvalds写出了著名的Linux操作系统,我国并没有人写出过类似的东西啊,我国的"大牛"怎么能和西方的比呢? 不知大家注意到没有,Linus Torvalds只是写出了一个"象模象样"的操作系统雏形,Linux后来真正发展成闻名全球的开源操作系统期间,完全是因为许多支持开源的商业公司如IBM等,派出了许多比Linus Torvalds更高楼层的幕后英雄在里面把它开发出来的。

可能有些菜鸟认为Linus Torvalds是程序员中的上帝,不妨说个小故事:

Linus,Richard Stallman和Don Knuth(高德纳)一同参加一个会议。

Linus 说:"上帝说我创造了世界上最优秀的操作系统。"

Richard Stallman自然不甘示弱地说:"上帝说我创造了世界上最好用的编译器。"

Don Knuth一脸疑惑的说:"等等,等等,我什么时候说过这些话?"

由此可以看出,Linus Torvalds的技术水平并不像想像中那么高,只是"牛人"和"大虾"觉得"大牛"比他们更牛吧了。在我国,有一些当时还处于"大虾"层的人物,也能写出介绍如何写操作系统的书,并且书写得非常出色,而且写出了一个有那么一点点象模象样的操作系统来。我想中国的"大牛"们是不会比西方差的,之所以没有人写出类似的商业产品来,完全是社会环境的原因,并不是技术能力达不到的原因。

"大牛"们之所以成为大牛,主要的原因是因为把"牛人"给盖了下去,并不是他们自己觉得如何牛。也许有很多菜鸟、大虾甚至牛人觉得"大牛"这层已经到顶了,但大多数"大牛"估计应该是有自知之明的,他们知道自己现在还没有爬到半山腰,也就勉强能算个半桶水的水平,其中有些爬到这层没有累趴下,仍然能量充沛,并且又有志者,还是会继续往更上一层楼爬的。

看到这里,也许有些菜鸟、大虾、牛人想不明白了,还有比"大牛"们更高的楼层,那会是什么样的楼层?下面就来看看第5层楼的奥妙。

第5层 专家
当大牛们真正动手做一个操作系统或者类似的其他软件时,他们就会发现自己的基本功仍然有很多的不足。以内存管理为例,如果直接抄袭Linux或者其他开源操作系统的内存管理算法,会被人看不起的,如果自动动手实现一个内存管理算法,他会发现现在有关内存管理方法的算法数量众多,自己并没有全部学过和实践过,不知道到底该用那种内存管理算法。

看到这里,可能有些人已经明白第5层楼的奥妙了,那就是需要做基础研究,当然在计算机里,最重要的就是"计算"二字,程序员要做基础研究,主要的内容就是研究非数值"计算"。

非数值计算可是一个非常庞大的领域,不仅时下热门的"多核计算"与"云计算"属于非数值计算范畴,就是软件需求、设计、测试、调试、评估、质量控制、软件工程等本质上也属于非数值计算的范畴,甚至芯片硬件设计也同样牵涉到非数值计算。如果你还没有真正领悟"计算"二字的含义,那么你就没有机会进到这层楼来。

可能有人仍然没有明白为什么比尔·盖茨被划在了大牛层,没有进到这层来。虽然比尔·盖茨大学未毕业,学历不够,但是家有藏书2万余册,进入软件这个行业比绝大部分人都早,撇开他的商业才能不谈,即使只看他的技术水平,也可以算得上是学富五车,顶上几个普通的计算机软件博士之和是没有问题的,比起Linus Torvalds之类的"大牛"们应该技高一筹才对,怎么还进不了这层楼呢?

非常遗憾的是,从Windows操作系统的实现来看,其对计算的理解是很肤浅的,如果把Google对计算方面的理解比做大学生,比尔·盖茨只能算做一个初中生,所以比尔·盖茨永远只能做个大牛人,成不了"专家"。

看到这里,也许国内的大牛们要高兴起来了,原来比尔·盖茨也只和我等在同一个层次,只要再升一层就可以超越比尔·盖茨了。不过爬到这层可没有从"牛人"升为"大牛"那么简单,人家比尔·盖茨都家有2万多册书,让你看个500~1000本以上的专业书籍并掌握好它应该要求不高吧。当然,这并不是主要的条件,更重要的是,需要到专业的学术站点去学习了,到ACM,IEEE,Elsevier,SpringerLink,SIAM等地方去下载论文应该成为你的定期功课,使用Google搜索引擎中的学术搜索更是应该成为你的日常必修课。此外,你还得经常关注是否有与你研究相关的开源项目冒出来,例如当听到有TBB这样针对多核的开源项目时,你应该第一时间到Google里输入"TBB"搜索一下,将其源代码下载下来好好研究一番,这样也许你的一只脚已经快迈进了这层楼的门槛。

当你象我上面说的那样去做了以后,随着时间的推移,总会有某天,你发现,在很多小的领域里,你已经学不到什么新东西了,所有最新出来的研究成果你几乎都知道。此时你会发现你比在做"牛人"和"大牛"时的水平不知高出了多少,但是你一点也"牛"不起来,因为你学的知识和思想都是别人提出来的,你自己并没有多少自己的知识和思想分享给别人,所以你还得继续往楼上爬才行。

我不知道国内的"专家"到底有多少,不过有一点可以肯定的是,如果把那些专门蒙大家的"砖家"也算上的话,我们的砖家比西方的要多得多。

第6层 学者

当"专家"们想继续往上一层楼爬时,他们几乎一眼就可以看到楼梯的入口,不过令他们吃惊的是,楼梯入口处竖了一道高高的门槛,上面写着"创新"二字。不幸的是,大多数人在爬到第5层楼时已经体能消耗过度,无力翻过这道门槛。

有少数体能充足者,可以轻易翻越这道门槛,但是并不意味着体力消耗过度者就无法翻越,因为你只是暂时还没有掌握恢复体能的方法而已,当掌握了恢复体能的方法,将体能恢复后,你就可以轻易地翻越这道门槛了。

怎么才能将体能恢复呢?我们的老祖宗"孔子"早就教导过我们"温故而知新",在英文里,研究的单词是"research",其前缀"re"和"search"分别是什么意思不用我解释吧。或许有些人觉得"温故而知新"和"research"有些抽象,不好理解,我再给打个简单的比方,比如你在爬一座高山,爬了半天,中途体力不支,怎么恢复体力呢?自然是休息一下,重新进食一些食物,体力很快就可以得到恢复。

由此可知,对体能消耗过度者,休息+重新进食通常是恢复体能的最佳选择。可惜的是,国内的老板们并不懂得这点,他们的公司里不仅连正常国家规定的休息时间都不给足,有些公司甚至有员工"过劳死"出现。所以国内能翻越"创新"这道门槛的人是"少之又少",和西方比起来估计是数量级的差别。

再说说重新进食的问题,这个重新进食是有讲究的,需要进食一些基础性易消化的简单食物,不能进食山珍海味级的复杂食物,否则很难快速吸收。以查找为例,并不是去天天盯着那些复杂的查找结构和算法进行研究,你需要做的是将二分查找、哈希查找、普通二叉树查找等基础性的知识好好地复习几遍。

以哈希查找为例,首先你需要去将各种冲突解决方法如链式结构、二次哈希等编写一遍,再试试不同种类的哈希函数,然后还需要试试在硬盘中如何实现哈希查找,并考虑数据从硬盘读到内存后,如何组织硬盘中的数据才能快速地在内存中构建出哈希表来,...,这样你可能需要将一个哈希表写上十几个不同的版本,并比较各个版本的性能、功能方面的区别和适用范围。

总之,对任何一种简单的东西,你需要考虑各种各样的需求,以需求来驱动研究。最后你将各种最基础性的查找结构和算法都了然于胸后,或许某天你再看其他更复杂的查找算法,或者你在散步时,脑袋里灵光一现,突然间就发现了更好的方法,也就从专家晋升为"学者"了。

学者所做的事情,通常都是在前人的基础上,进行一些小的优化和改进,例如别人发明了链式基数排序的方法,你第1个发现使用一定的方法,可以用数组替代链表进行基数排序,性能还能得到进一步提高。

由于学者需要的只是一些小的优化改进,因此中国还是有一定数量的学者。不过和国外的数量比起来,估计少了一个数量级而已。

也许有人会觉得现在中国许多公司申请专利的数量达到甚至超过西方发达国家了,我们的学者数量应该不会比他们少多少。因此,有必要把专利和这里说的创新的区别解释一下。

所谓专利者,只要是以前没有的,新的东西,都可以申请专利;甚至是以前有的东西,你把他用到了一个新的领域的产品里去,也可以申请专利。比如你在房子里造一个水泥柱子,只要以前没有人就这件事申请专利,那么你就可以申请专利,并且下次你把水泥柱子挪一个位置,又可以申请一个新的专利;或者你在一个柜子上打上几个孔,下次又把孔的位置改一改,...,均可申请专利。

这层楼里所说的创新,是指学术层面的创新,是基础研究方面的创新,和专利的概念是完全不同的,难度也是完全不同的。你即使申请了一万个象那种打孔一类的专利,加起来也够不到这层楼里的一个创新。

当你爬到第6层楼时,你也许会有一种突破极限的快感,因为你终于把那道高高的写着"创新"二字的门槛给翻过去了,实现了"0"的突破。这时,你也许有一种"独上高楼,欲望尽天涯路"的感觉,但是很快你会发现看到的都是比较近的路,远处的路根本看不清楚。如果你还有足够的体力的话,你会想爬到更高一层的楼层去。

第7层 大师

从第6层楼爬到第7层楼,并没有多少捷径可走,主要看你有没有足够的能量。你如果能象Hoare一样设计出一个快速排序的算法;或者象Eugene W. Myers一样设计出了一个用编辑图的最短路径模型来解决diff问题的算法;或者象M.J.D. Powell一样提出了一个能够处理非线性规划问题的SQP方法;或者你发现基于比较的排序算法,它的复杂度下界为O(NLogN);或者你发现用栈可以将递归的算法变成非递归的;或者你设计出一个红黑树或者AVL树之类的查找结构;或者你设计出一个象C++或Java一样的语言;或者你发明了UML;...,你就爬到了第7层,晋升为"大师"了。

上面举的这些例子中,其中有些人站的楼层比这层高,这里只是为了形象说明而举例他们的某个成就。从上面列出的一些大师的贡献可以看出,成为大师必须要有较大的贡献。首先解决问题必须是比较重要的,其次你要比前辈们在某方面有一个较大的提高,或者你解决的是一个全新的以前没有解决过的问题;最重要的是,主要的思路和方法必须是你自己提供的,不再是在别人的思路基础上进行的优化和改进。

看了上面这些要求,如果能量不够的话,你也许会觉得有些困难,所以不是每个人都能成为"大师"的。中国软件业里能称得上是"大师"的人,用屈指可数来形容,估计是绰绰有余。值得一提得是,国外的"大师"就象我们的"大牛"一样满天飞的多。

我把我猜测本国有可能进到这层楼的大师列一下,以起个抛砖引玉的作用。汉王的"手写识别"技术由于是完全保密的,不知道它里面用了什么思想,原创思想占的比重有多少,因此不知道该把它划到这层楼还是更高一层楼去。原山东大学王小云教授破解DES和MD5算法时,用到的方法不知道是不是完全原创的,如果是的话也可进到这层楼来。

陈景润虽然没有彻底解决哥德巴赫猜想,但他在解决问题时所用的方法是创新的,因此也可以进到这层楼来。当然,如果能彻底解决哥德巴赫猜想,那么可以算到更高的楼层去。

求伯君和王志东等大牛们,他们在做WPS和表格处理之类的软件时,不知是否有较大的原创算法在里面,如果有的话就算我错把他们划到了大牛层。由于所学有限,不知道国内还有那些人能够得上"大师"的级别,或许有少量做研究的教授、院士们,可以达到这个级别,有知道的不妨回个帖子晾一晾。

鉴于"大师"这个称号的光环效应,相信有不少人梦想着成为"大师"。或许你看了前面举的一些大师的例子,你会觉得要成为大师非常困难。不妨说一下,现在有一条通往"大师"之路的捷径打开了,那就是多核计算领域,有大量的处女地等待大家去挖掘。

以前在单核时代开发的各种算法,现在都需要改写成并行的。数据结构与算法、图像处理、数值计算、操作系统、编译器、测试调试等各个领域,都存在大量的机会,可以让你进到这层楼来,甚至有可能让你进到更高一层楼去。

第8层 科学家

科学家向来都是一个神圣的称号,因此我把他放在了“大师”之上。要成为科学家,你的贡献必须超越大师,不妨随便举一些例子。

如果你象Dijkstra一样设计了ALGOL语言,提出了程序设计的三种基本结构:顺序、选择、循环,那么你可以爬到第8层楼来。顺便说一下,即使抛开这个成果,Dijkstra凭他的PV操作和信号量概念的提出,同样可以进到这层楼。

如果你象Don Knuth一样,是数据结构与算法这门学科的重要奠基者,你也可以进到这层楼来。当然,数据结构和算法这门学科不是某个人开创的,是许多大师和科学家集体开创的。

如果你象巴科斯一样发明了Fortran语言,并提出了巴科斯范式,对高级程序语言的发展起了重要作用,你也可以进到这层楼来。

或者你象Ken Thompson、Dennis Ritchie一样发明了Unix操作系统和功能强大、高效、灵活、表达力强的C语言,对操作系统理论和高级编程语言均作出重大贡献,那么你也可以进到这层楼来。

或者你有Frederick P. Brooks一样机会,可以去领导开发IBM的大型计算机System/360和OS/360操作系统,并在失败后反思总结,写出《人月神话》,对软件工程作出里程碑式的贡献,你也可以进到这层来。

或者你提出了面向对象设计的基本思想,或者你设计了互联网的TCP/IP协议,或者你象Steven A.Cook一样奠定NP完全性的理论基础,或者你象Frances Allen一样专注于并行计算来实现编译技术,在编译优化理论和技术取得基础性的成就,…,均可进入这层。

当然,如果你发明了C++语言或者Java语言,你进不到这层来,因为你用到的主要思想都是这层楼中的科学家提出的,你自己并没有没有多少原创思想在里面。

看了上面列出的科学家的成就,你会发现,要成为“科学家”,通常要开创一门分支学科,或者是这个分支学科的奠基者,或者在某个分支学科里作出里程碑式的重大贡献。如果做不到这些的话,那么你能象Andrew C. Yao(姚期智)一样在对计算理论的多个方向如伪随机数生成,密码学与通信复杂度等各个方向上作出重要贡献,成为集大成者,也可以进入这层楼。

成为“科学家”后,如果你有幸象Dijkstra一样,出现在一个非常重视科学的国度。当你去世时,你家乡满城的人都会自动地去为你送葬。不过如果不幸生错地方的话,能不挨“板砖”估计就算万幸了。

从上面随便举的一些例子中,你可能能猜到,西方科学家的数量是非常多的,于是你会想中国应该也有少量的科学家吧?我可以很负责任地告诉你一个不幸的结果,中国本土产生的科学家的数量为0。目前在国内,软件领域的唯一的科学家就是上面提过的姚期智,还是国外请回来的,并不是本土产生的。

可能你不同意我说的本土科学家数量为0的结论,因为你经常看到有许多公司里都有所谓“首席XX科学家”的头衔。我想说的是,这些所谓的“首席XX科学家”都是远远够不到这层楼的级别的,有些人的水平估计也就是一个“牛人”或“大牛”的级别,好一点的最多也就一个“学者”的级别。尤其是那些被称作“首席经X学家”的,基本上可以把称号改为“首席坑大家”。

虽然我国没有人能爬到这层楼上来,但是西方国家仍然有许多人爬到了比这层更高的楼上。如果要问我们比西方落后多少?那么可以简单地回答为:“落后了三层楼”。下面就来看看我们做梦都没有到过的更高一层楼的秘密。

第9层 大科学家

进入这层楼的门槛通常需要一些运气,比如某天有个苹果砸到你头上时,你碰巧发现了万有引力,那么你可以进到这层楼来。当然,万有引力几百年前就被人发现了,如果你现在到处嚷嚷着说你发现了万有引力,恐怕马上会有人打110,然后警察会把你送到不正常人类的聚集地去。因此,这里举万有引力的例子,只是说你要有类似的成就才能进到这层楼来。

牛顿发现万有引力定律开创了经典物理运动力学这门学科,如果你也能开创一门大的学科,那么你就从科学家晋升为“大科学家”。比如爱因斯坦创建了相对论,从一个小职员变成了大科学家。当然大科学家可远不止这两人,数学界里比物理学界更是多得多,如欧几里得创建了平面几何,笛卡尔开创解析几何,还有欧拉、高斯、莱布尼茨等数不清的人物,跟计算相关的大科学家则有图灵等人。

从上面列出的一些大科学家可以发现,他们的成就不仅是开创了一个大的学科,更重要的是他们的成就上升到了“公理”的层面。发现公理通常是需要一点运气的,如果你的运气不够好的话,另外还有一个笨办法也可以进到这层楼来,那就是成为集大成者。例如冯·诺伊曼,对数学的所有分支都非常了解,许多领域都有较大的贡献,即使撇开他对计算机的开创贡献,成为大科学家照样绰绰有余。

当然,程序员们最关心的是自己有没有机会变成大科学家。既然计算机这门大学科的开创性成果早就被冯·诺伊曼、图灵等人摘走了,那么程序员们是不是没有机会变成大科学家了呢?我们的古人说得好:“江山代有才人出,各领风骚数百年”,现在在计算机这门学科下面诞生了许多非常重要的大的分支,所以你还是有足够的机会进到这层楼的。

如果你能够彻底解决自然语言理解(机器翻译)这门学科中的核心问题, 或者你在人工智能或者机器视觉(图像识别)方面有突破性的发现,那么你同样可以轻易地晋升为“大科学家”。这样当某天你老了去世时,或许那天国人已经觉醒,你也能享受到如Dijkstra一样的待遇,有满城甚至全国的人去为你送葬。

现在还剩下另外一个大家感兴趣的问题没有讨论,那就是这层中已经出现了牛顿、爱因斯坦、高斯等我们平常人都认为是顶级的科学家,是不是这层已经是楼顶了呢?相信还记得本文标题的人应该知道现在仅仅是第9层,还有第10层没有到达呢。可能不少人现在要感到困惑了,难道还有人站在比牛顿、爱因斯坦、高斯等人更高的楼层上?

这个世界上确实存在可以用一只手的手指数得清的那么几个人,他们爬到了第10层楼上。因此,第10层楼不是虚构的,而是确实存在的。如果对此有疑惑或者认为我在胡诌一番的话,那么不妨继续往下看下去,窥一下第10层楼的秘密。

第10层 大哲
看了这层楼的名字“大哲”,可能不少人已经猜到了这层楼的秘密,那就是你的成果必须要上升到哲学的高度,你才有机会能进到这层来。

当然,上升到哲学高度只是一个必要条件,牛顿的万有引力似乎也上升到了哲学的高度,因为不知道引力到底是怎么来的,但是牛顿没有被划到这一层,因为进到这层还有另外的条件,那就是你的成果必须引起了哲学上的深度思考,并能让人们的世界观向前跨进一大步。窃以为牛顿、爱因斯坦等人的成就还达不到让人们世界观向前跨进一大步的程度。

所以,这层楼中的人的成就对我们普通人认识世界非常重要,你可以不学相对论,但是你不可以不对这层楼的人所作出的成就不了解,否则你的世界观就是极其不完整的,会犯许多认识上的错误。不幸的是,中国的科普知识普及还不够到位,知道这层楼成就的人好像并不多,程序员中恐怕更少。下面就来看看这些用一只手的手指数得清的大哲们,到底有什么成就,能比万有引力定律和相对论还重要。

1、希尔伯特 (1862~1943)

第1位进到此楼层是一位名叫“希尔伯特”的大数学家,如果你学过《泛函分析》,那么你在学习希尔伯特空间时可能已经对这位大数学家有所了解;如果你不是学数学出身的,又对数学史不感兴趣的话,恐怕你从来没有听说过这个名字。不过如果我问一下,知不知道二次世界大战前世界数学中心在那里,你肯定会有兴趣想知道。

不妨说一下,二战前整个世界的数学中心就在德国的哥廷根,而我们这位大数学家希尔伯特便是它的统帅和灵魂人物。即使在二战期间,希特勒和丘吉尔也有协定,德国不轰炸牛津和剑桥,作为回报,英国不轰炸海德堡和哥廷根。

整个二十世纪上半期的超一流数学家,几乎都出自其门下。这里不妨举几个我们熟悉的人物,例如冯·诺伊曼就曾受到他和他的学生施密特和外尔的思想影响,还到哥廷根大学任过希尔伯特的助手,钱学森的老师冯·卡门是在哥廷根取得博士学位的。顺便提一下,这位大数学家发现当时物理学上出了很多大的成果如相对论和量子力学,但是这些物理学家的数学功力明显不足,因此有一段时间带领他的学生们研究过物理学,并独立发现了广义相对论,只是不好意思和物理学家争功劳,将广义相对论的功劳全部让给了爱因斯坦。

广义相对论相对于这位大数学家在数学上的贡献,其实是算不了什么的,只是由此可看出这位大数学家品格的高尚之处。如果再去看看牛顿之流的人物的品行,整天和莱布尼茨、虎克等人争功劳,利用自己的优势地位打压他人,甚至闹得上法庭,和这位希尔伯特先生比起来,简直就是个小丑。

说到这里,你可能对这位大数学家“希尔伯特”有了一些初步映象,感觉到了他的重要性,不过他在数学上的主要成就可不是几句话说得清楚的。首先,他是一位集大成者,精通当时数学所有分支领域,在数学的各个领域都有较大的贡献,当然这些成就只能让他成为一个大科学家,不能带他进入这层楼。事实上这位“希尔伯特”解决的任何一个数学问题都够不到这层楼的高度,那么他怎么混到这层楼来了呢?

话得从1900年说起,当时还很年轻的希尔伯特在当时的世界数学大会上做了一个报告,高屋建瓯地提出了著名的23个未解决的数学问题,然后整个二十世纪上半期,全世界的数学家们都在这23个问题的指导下展开研究,直到现在仍然有许多数学家受这23个问题的指导在进行研究。例如我们熟知的哥德巴赫猜想,就属于其中第8个问题素数分布的一个子问题。

如果用“高瞻远瞩”来形容这位大数学家的话,那么这个世界上恐怕没有第二个人再配得上“高瞻远瞩”这四个字,不论是欧拉、高斯、牛顿、爱因斯坦还是被誉为最有才华的数学家伽罗华,概不例外。

虽然那23个问题是归纳总结出来的,并不全是原创,但是其中有不少问题是可以上升到哲学的高度,引起深度思考的。可能大多数人都会觉得希尔伯特是进不到这层楼的,我们知道提出问题的人和解决问题的人是一样伟大的,何况他提出的问题是如此之多,基于这点,个人觉得应该让希尔伯特跨进这层楼的门槛里。

看完这位希尔伯特的成就,你可能会觉得对你的世界观并没有产生任何影响。确实如此,他提出的问题不是用来影响你的,而是用来影响其他大科学家和大哲的,下面再来说说另一位对他提出的23个问题中的第2个问题有杰出贡献的大哲,你就会感觉到大哲们的成果的威力了。

2、哥德尔 (1906~1978)

这位大哲的名字叫“哥德尔 (Gödel) ”,你可能从来也没有听说过这个名字,即使你读了一个数学系的博士学位,如果你的研究方向不和这位大哲对口的话,你也不一定了解这位大哲的成就,更不知道他的成果对我们这个世界有何意义。

简单地说,这位大哲20多岁时就证明了两个定理,一个叫做“哥德尔完全性定理”,另一个更重要的叫做“哥德尔不完全性定理”。你也许会觉得奇怪,第9层楼的成就就已经上升到了公理的高度,这种证明定理的事情不是学者和大师们做的事情吗?怎么能比第9层楼的成就还高呢?下面就来简单说一下这两个定理的含义,你就会明白这属于系统级的定理,绝不是普通的定理和公理所能比拟的。

“哥德尔完全性定理”证明了逻辑学的几条公理是完备的,即任何一个由这些公理所产生出的问题,在这个公理系统内可以判定它是真的还是假的,这个结论表明了我们人类所拥有的逻辑思维能力是完备的。这条定理并不能将其带入这层楼来,带其进入这层楼的是另一条定理。

“哥德尔不完全性定理”是在1930年证明的,它证明了现有数学的几条公理(ZF公理系统)是不完备的,即由这些公理产生出的问题,无法由这几条公理判断它是真的还是假的。例如希尔伯特23个问题中的第1个问题,也就是著名的康托尔连续统假设,哥德尔在1938年证明了现有公理系统中不能证明它是“假”的,科恩(Cohen,或许也可以称得上是“半”个大哲)在1963年证明了现有公理系统不能证明它是“真”的。最有趣的是,即使你将某个不可判定的问题,作为一条新的公理加入进去,所组成的新的公理系统仍然是不完备的,即你无法构造一个有限条公理的系统,让这个公理系统是完备的。

也许你仍然无法理解上面这段话的含义,不妨先说一下它对我们现实世界的影响。你可能知道1936年出现的图灵机是现代计算机的理论模型,如果没有哥德尔不完全性定理的思想,图灵机什么时候能出来是很难说的,所以这位哥德尔可以算作计算机理论的奠基者的奠基者。计算机对我们这个世界产生的影响比原子弹大了多少,我想不用我说大家也都清楚。当然,对现实世界的影响只能把哥德尔同图灵等人一样划到大科学家那一层去,能进入这层乃是另有原因。

可能你看过《未来战士》、《黑客帝国》、《I,Robot》之类的科幻电影,于是你产生制造一个和人一样或者比人更高一级的智能机器人的想法,这就引入了一个达到哲学高度的问题,“人到底能不能制造出具有和人一样的思维能力的机器来?”。

我只能告诉你,“你的愿望是良好的,但现实是残酷的”。如果你仔细思考一下不完全性定理的含义,并结合现代计算机所具有的能力分析一下,你会发现这个问题的答案暂时是否定的。如果你想造出和人一样思维能力的机器,那么你需要去好好学习这位大哲及其后续研究者的成果,并在他们的基础上有新的突破才行。

为了说明这位大哲所研究领域的重要性,这里顺便再讨论一个我们日常争议不休的问题,那就是孔夫子的“人之初、性本善”以及西方认为“人之初、性本恶”的观点孰优孰劣的问题。可能有许多人发现西方社会现在领先我们,于是就认为“性本恶”是对的,“性本善”是错的,中国应该抛弃以前的旧思想,改用西方的思想。当然也有一些老学究们,认为中国的人文思想是领先于西方的,自然而然地认为“性本善”是对的,“性本恶”是错的。

如果你学过大哲用过的公理化的分析方法,你就知道一套系统的多条公理间只要不会推导出矛盾的地方,即可以自圆其说,那么它可以看作是对的。这样你可以很轻易地给这个问题下一个结论,即“性本善”和“性本恶”是对等的,不存在孰优孰劣的问题,更不存在谁对谁错的问题。只要你不同时将“性本善”和“性本恶”放入一个系统内,那么是不会有问题的,甚至你也可以认为“人之初、既无善、亦无恶”,或者认为“人之初、部分善、部分恶”,都是可以自圆其说的,所以我们的老祖宗提出的思想并没有问题,之所以落后乃是其他原因造成的。这个问题其实在高斯所处的时代就有了结论,那时有人提出了非欧几何,即平行线公理问题,有人认为过一点可以作多条平行线,还有人认为平行线在无穷远点是相交的,和欧氏几何关于过一点只能作一条平行线的公理都是矛盾的,但是他们各自的系统内推导出的结论都是正确的。

上面说的只是对哥德尔不完全性定理的一些粗浅解析,实际上如果深入思考一下它的含义的话,你会发现它对物理学等许多学科有重大影响,包含的道理实在是深刻,远非一般的思想所能比拟,有兴趣者不妨“google”或“百度”一下“哥德尔”。或许只有我们的老祖宗“老子”提出的哲学思想,深度可以有得一比。

哥德尔不完全性定理也给那些认为科学是严谨的人当头一棒,原来连数学这样的纯理论学科都是不严谨的,其他学科就更不用说了。

至此,已经说完数学上的大哲,下面不妨再看看物理学上的大哲,物理学上好像只出过一位叫“海森堡”的大哲(注:由于本人对物理学不甚了解,不知道“霍金”够不够得上大哲的称号)。

3、海森堡 (1901~1976)

海森堡这个名字相信没有几个人不知道的,大部分人在学习物理时都学过他的“测不准关系”,也就是因为这个“测不准关系”,海森堡爬到了第十层楼。

如果你看过《时间简史》和《霍金讲演录-黑洞、婴儿宇宙及其他》,你也许已经了解测不准关系的威力,所以这里不想做过多的讨论,只谈一些和本土产生的哲学思想相关的东西。

首先看看争论了几千年,并且现在仍然有人在争论不休的“宿命论”问题。霍金认为,只要这个宇宙有一个初始状态,粒子的运动是按照一定物理定律进行的(比如相对论、量子力学属于这些物理定律的一部分),那么所有的粒子运动轨迹将是确定的,然后只要你承认唯物论,即精神是由物质决定的,那么宿命论就是“对”的。当然由于测不准关系的存在,对人而言,又是无法准确预测的,因此也可以将其看作是“不对”的。简单的说,可以认为宿命论是“对”的是绝对的,宿命论是“不对”的是相对的。

可能上面这段话你现在仍然难以理解,或许你又觉得你的命运并不是上天注定的,而是可以通过自己的努力可以改变的。我要告诉你的是,你在想什么也是事先已注定的,包括你在预测本身也是事先注定的,因为大脑思考问题最终是基本粒子运动的结果,而这些粒子的运动必然要遵循物理定律进行,所以你会不会努力,想不想努力,包括你在想你该不该努力这件事本身也是事先注定的。顺便说一下,你现在正在看这篇文章,可能正在想这个宿命论问题值得怀疑,或者觉得写得不够好,准备砸个板砖上来;或者你在想这篇问题写得有点意思,准备看完后转给朋友看一看;又或者你看到这里,觉得很累了,准备休息一下;…;这些都是上天事先就注定的。从你自身的相对角度看,因为你事先不知道后来会发生什么,也可以认为不是事先注定的,可能这句话有些不好理解,不妨好好理解前面说过的公理化思想。

如果你没看过《霍金讲演录-黑洞、婴儿宇宙及其他》,你可能会觉得很惊讶,宿命论历来不都被认为是唯心论吗,怎么由唯物论推导出了宿命论呢?现实就是这样和你开了一个大的玩笑,不过这个玩笑也是事先注定的。如果你再仔细用公理化的方法思考一下唯物论和唯心论的矛盾性,就像前面分析性善论和性恶论一样,你会发现唯物论、唯心论不一定就是冲突的,矛盾的双方是可以统一的,只要你不要同时将唯物和唯心放进同一个系统中就行。

当然也有聪明者仍然会怀疑宿命论问题的正确性,因为这里有一个前提条件,即宇宙要有一个初始状态。宇宙有没有初始状态,我们并不知道啊,虽然有大爆炸学说,但那也只是假说而已,并没有得到确证,有些人就认为宇宙是一直都存在的。这样看来似乎你又有合理的理由在怀疑宿命论了,不过我仍然要告诉你,你现在在怀疑宿命论仍然是事先注定的,不相信的话就来看看下面的分析。

虽然宇宙的初始状态值得怀疑,但是这个宇宙至少已经存在了一段时间,这点我想是毋庸置疑的。我们可以在我们已知的宇宙存在的这段时间内,任意取一个时间点t0,那么在这个时间点t0上,所有的粒子都有一个运动状态。在时间点t0之后的时间里,由于粒子运动是按照物理定律进行的,因此粒子运动轨迹由时间点t0的状态决定。说白一点,如果取100年前的一个时间点作为t0,那么现在的所有粒子运动状态100年前就已经确定了,如果取10000年前一个时间点作为t0,那么最近10000年内所有粒子运动的轨迹在10000年前就确定了,当然,你可以取更早的时间,比如100亿年前的时间点。

总之,现在你会发现宇宙有没有初始状态并不会影响宿命论的正确性,所以这个世界的一切都是注定的。只不过由于粒子间相互影响过于复杂,我们无法知道这些粒子的运动轨迹而已。当然,如果将测不准关系用上的话,那么就是这个运动轨迹对人来说是无法准确预测的,所以不妨开个玩笑:“算命先生经常算得不准大概是测不准关系的缘故吧”。

如果你再深入思考一下测不准关系,你会发现这是一个测量系统的问题。由于宿命论的存在,这个世界本身实际上是确定的,是“准“的,之所以测不准乃是我们人类所具有的测量能力依赖于基本粒子造成的。所以我在前面说宿命论是“不对”的是相对的,它是相对于我们人类的测量能力而言的。根岑(Gentzen,曾任希尔伯特的助手)在一个更强的系统内证明了ZF系统内的问题都是可判定的,从一个侧面说明这个世界本身是确定的。(注:它和哥德尔不完全性定理并不矛盾,由于数学上的复杂性,这里就不详细解释了)

不妨再想想我们老祖宗提出的“是庄周梦见了蝴蝶?还是蝴蝶梦见了庄周?”,“风动?幡动?还是心动?”之类的问题,当然以前你都认为这是纯粹的唯心主义,甚至认为是封建糟粕,但是如果结合测不准关系的内涵,再结合前面所说的公理化分析方法进行分析,估计你现在不敢轻易地下结论。

也许到现在你仍然无法理解为什么把大哲们划在了大科学家的上一层,你可能仍然觉得万有引力、相对论等成果是最伟大的。下面就来谈谈为什么大哲比大科学家高一层。

如果把人类在现有能力情况下,将来所能够拥有的知识总集看成是一个集合A,人类现在已有的知识总集看成是集合B,显然,集合B只是集合A的一个子集,并且是很小的一个子集。牛顿力学、相对论这些理论只能算作集合B里的一个子集,相对于集合A,只能算作是沧海一粟。 换句话说,在人类现有能力可做的事情集合中,牛顿力学和相对论等理论给出了详细的办法让你可以做其中的一些事情,当然剩下的更多的事情是牛顿力学和相对论所无法解决的。

哥德尔不完全性定理和测不准关系的意义在于,它指出集合A的范围,即将人类现有能力发挥到极限的情况下,那些事情是你能做到的,那些是你不能做到的。当然,它并没有给出具体的方法让你去做你能做到的事情,它只是告诉我们我们人类现在发现的能力所能达到的极限。或许将来发现人类有其他新的未发现的能力,那么这个极限就被打破了。比如将来能发现不依赖于基本粒子的其他测量方法,并且测量过程中不会改变其他粒子的状态,那么测不准关系就被打破了。

看到这里,估计你已经发现了一些秘密,科学兜了一大圈,最终还是回到了哲学,也就是我们所认为的玄学上。同时你也会发现,我们老祖宗提出的所谓玄学,原来和现代科学是相通的,并非象某些人想像的那样全是糟粕。如果有人认为西方现代暂时领先我们,进而就认为西方古代就已经超越我们,我们老祖宗就已经落后西方,他们的思想都是糟粕的话,那么我认为他可能犯了崇洋媚外的毛病。我不得不化用一句周杰伦在春晚上的歌词送给他:“你不妨抓一副我们祖传的中医良方,治一治你那崇洋媚外的内伤”。顺便告诉他一下,中医用的阴阳五行理论,它的前提假设就是宿命论。

上面说的这几位大哲的成果,可能对你的世界观会有很大的影响,于是你可能会羡慕起这些大哲们的成果来。如果你有大志的话,你会希望有朝一日你也能变成大哲,但是你发现上面的大哲是研究数学和物理学的,而你是学计算机的程序员,那么是不是没有机会变成大哲呢?

如果你能将NP难题给彻底解决掉,意味着计算机内的计算的奥秘基本被揭开,或许你可以进到这层楼来;或者你能发现另外一套计算机可以理解的数学公理系统,并且这个公理系统是完备的,那么计算机取代人类进行思维的一个必要条件就满足了,计算机将具有真正意义上的“逻辑思维和推理能力”,你可以轻松地进到这层楼来。如果你发现了新的方法可以打破测不准关系,同样你也可以轻松地进到这层楼来。

如果你能彻底揭开人类抽象思维的奥妙,并让计算机懂得了如何创建抽象,具备抽象思维能力,那么也就具备了“设计能力”,可以取代人类进行各种设计了,你也可以轻松地进到这层楼来。顺便说一下,如果你对软件设计有真正深刻理解的话,就会明白这不是在写科幻小说。对此感兴趣者,不妨好好地研究一下程序切片方面的技术,会让你对软件设计和测试等方面的理解有质的提高,或许有一天你能打开这扇大门。

当然,计算机要完全取代人还有其他必要条件,后面还会提及。

值得一提的是,虽然第10层楼是本文中所写的最高层,但是大哲们并没有觉得他们到了顶层,他们通常都还会努力寻找通往更高一层的楼梯。如果你也有成为天下第一的想法,那么你或许会想要做什么事情才能超越大哲们的成就,当然,这都得依赖于找到更高一层楼的楼梯。

个人认为,再往上一层楼的楼梯是通往天堂的道路,也就是说第11层楼的名字叫“天堂”,是“上帝”住的地方,而不是人住的地方。如果将来某天有人能爬到天堂的话,那么他已经不是人了,而是由人变成了“上帝”。

你也许会怀疑这个世界到底有没有“天堂”,“上帝”是否根本就不存在,我也很有同感。因此有必要再写上一段文字,讨论一下“上帝”的问题。如果你想了解天堂的奥妙,有没有办法让你变成“上帝”,不妨看看继续往下看看第11层楼的玄妙。注意我这里用的是“玄妙”二字,因为上帝在大部分人眼里估计都是“玄之又玄”的东西。

第11层 上帝
看了上面的小标题,你可能会觉得奇怪,这篇文章不是讲“程序员的十层楼”吗?怎么冒出了第11层来了?

其实这并不矛盾,程序员确实只有十层楼,因为爬到第11层时,已经变成上帝,不再是程序员了;所以超出10层楼本身并不重要,关键的问题是看你有没有能力变成上帝。

1、谁是上帝?

菜鸟们认为Linus Torvalds是程序员中的上帝,看完了前面各层楼的介绍,此时再看到这句话,相信你要忍不住在心里笑起来。当然,你会不会笑起来是事先注定的。Don Knuth也不是上帝,他离上帝还有三层楼的距离。即使是大哲们,他们离天堂也还差一层楼,因此这个世界上有史以来还没有任何一个人变成过上帝。

我们感兴趣的是,将来会不会有人爬到比大哲们更高的楼层上,变成了上帝。

要变成上帝,你得有上帝一样的能力,上帝会造人,你会吗?

你也许会怯生生地问:“我可以和爱人生小孩,算不算造人?”,你可能还会理直气壮地说:“现在生物学上都可以克隆人了,早就有人掌握了造人的方法”。

事实上克隆人需要有人的体细胞,必须要先有人才会有体细胞。上帝造人时,这个世界上并没有人,是从无生命的物质“尘土”中创造出的人。因此,用最原始的方法生人和克隆人都是从有生命信息的物质中生人,不能算作造人。

这样看来,你根本不会造人,不过我可以告诉你一个“玄方”,让你有机会学会如何造人。

如果你揭开了人类情感的奥秘,让计算机也可以拥有和人类一样的情感,那么计算机将可以理解人类的需求,具有了“情商”,将具有完整的和人一样的能力。此时,人类进化到了机器人,科幻小说将变成现实,也就是说你已经掌握了真正的造人能力,晋升为“上帝”了。

未来到底有没有人能变成“上帝”,人能不能进化到机器人,这是宿命论中事先注定了的。说到这里,不妨再告诉你一个打破宿命论的方法,这个方法就是你要爬到比上帝还要高的楼层。

“还有比上帝还高的楼层?”,你可能会第1时间内冒出这个问题,其实我也有同样的怀疑。因此在写第12层楼前,有必要弄清楚它到底存不存在,即你可不可以骑到上帝的头上的问题。

2. 骑到上帝的头上?

为了解决是否可以骑到上帝的头上这个问题,不妨先假设存在比上帝高的楼层,也就是存在打破宿命论的方法。

宿命论的本质原因是因为时间是单向运行,不可逆转造成的。如果你找到一种可以使时间逆转的方法,那么你就打破了宿命论,爬到了比上帝还高的楼层。

看到这里,你也许会摆脱刚才陷于宿命论的困惑情绪,变得充满希望般高兴起来。不过,如果你的逻辑思维能力足够好,仔细思考一下,会发现存在一个逻辑上的悖论。

在你找到时间逆转的方法之前,显然这个世界仍然是需要服从宿命论的,也就是说你能不能找到打破宿命论的方法是事先注定的。假设你在某个时间点t0处找到了打破宿命论的方法,你在打破宿命论后,想利用时间逆转的方法回到某个时间点t2。下面来看看你到底能不能回到时间点t2。

取位于t0和t2之间的任意一个时间点t1,你在回到时间点t2之前,必须先经过时间点t1,考虑你到达t1的那一时刻,由于t1比t0要早,这个时间点上你还没有找到时间逆转的方法,所以到了时间t1点后,你无法再使用时间逆转的能力回到时间点t2去,所以你永远也回不到时间点t2,由于时间点t2是任意取的,因此,你永远也无法使时间逆转,或者说你根本就没打破过宿命论,这与你在时间点t0打破了宿命论产生了矛盾。

上面这段话看起来似乎有点像“人永远迈不出一步”的诡辩一样,你可能会想返回到时间点t1时,仍然可以拥有时间逆转能力啊。不过你又会发现一个新的问题,时间点t1本来是没有时间逆转能力的,现在又认为时间点t1又有时间逆转能力,那时间点t1到底是有还是没有时间逆转能力呢?或者说在时间点t0前,宿命论注定了时间点t1是没有时间逆转能力的,现在你又认为时间点t1具有时间逆转能力,那么这两个时间点t1究竟是不是同一个时间点?如果不是同一个时间点,说明你没有回到过去;如果是同一个时间点的话,岂不是自相矛盾吗?

为了说得更形象一些,不妨假设你坐一艘超光速飞船,准备从时间点t0回到时间点t2去,假设你回到t2后,随着时间的流逝,又达到了时间点t0,如果这时你又再次坐超光速飞船返回时间点t2,那么一个值得思考的问题就出现了,“你在时间点t2能不能看到上次返回时间点t2的飞船?”

如果回答不能看到飞船,那么上次返回的飞船那里去了呢?显然很难解释通。如果回答能看到飞船,那么你可以到达时间点t2后,下次时间到达t0时,你又坐飞船返回t2,这次你将可以看到上两次的两艘飞船。如果这样一直循环下去,最后你会发现你可以在时间点t2看到无穷多的飞船。用程序员的术语说,叫做“程序陷入了死循环”,最后系统必然会出现“Out of Memory”现象而崩溃。

当然,你也可以认为有其他的方法,不需要飞船,可以一次性从时间点t0直接跳跃到时间点t2,并不需要经过时间点t1。下面不妨来分析一下这个方法是否可行。

既然是直接跳跃到时间点t2,那么你必然是在一个无穷小的时间里出现在时间点t2的某个空间里,例如你要在时间点t2回到某个广场上。首先说明一下为什么是无穷小的时间里出现的,因为如果不是无穷小的时间里出现的话,那么必然可以取到一个时间点t1,会导致前面所说的时间点t1上出现悖论。

你在广场上出现的时,广场上的空气必然要为你让开空间,而这是在无穷小的时间里完成的,那么很容易推导出你周围的空气获得的加速度和速度都是无穷大,因而它具有的动能也是无穷大,无穷大的能量和无穷大的速度意味着什么?一只鸟都可以将飞机撞下来,如果宇宙是有限大的话,它可以让这个宇宙炸毁无穷次;即使宇宙是无限大,它也足以让宇宙炸毁一次。宇宙都毁灭了,又何来的时间?还能说你回到了时间点t2吗?

也许上面说的这些你仍然难以相信,不妨再说得更现实一些,假设你要回到100年前的一个时间点,这100年中,天上有多少流星湮灭了?有多少新星生成了?宇宙膨胀了多少?你有能力让湮灭的流星复原、生成的新星重新返回未生成前的状态,膨胀的宇宙收缩回去吗?如果这些东西的状态没有回复到100年前,又怎么能说明你回到的是100年前的时间点呢?

根据上面的推导和分析,个人认为使时间逆转的方法是不存在的,所以第12层楼是不存在的,自然没有人可以骑到“上帝”的头上。

宿命论将在有时间的时间里永远统治这个世界。

Best Computer Programming Videos

转自:http://www.devtopics.com/best-computer-programming-videos/

We interrupt your regular programming to bring you these entertaining computer programming videos…

If Programmers Built Planes

 

First Fully-Automated Plane Flown by a Computer

We know what happens when we let computers control our lives!

 

Why Programmers Don’t Have Girlfriends

 

Frustrated Programmer

 

Java Programmer Time Lapse

This is what Java (the programming language) and java (the coffee) do to computer programmers:

 

Software Crash on Game Show

This is a clip from the German version of “Who Wants To Be A Millionaire?” The software malfunctions and starts blinking the correct answer to the question.

 

How to Deal with a Programmer

When you need to get a programmer’s attention:

 

Programmer Gone Insane

Warning: Cartoon violence.

 

Dev Life Hip-Hop Music Video

 

Coder Blues

 

Hug a Developer Today

 

Code Monkey

This is a music video about the life of the common lowlands code monkey.


Best Computer Programming Videos

Posted using ShareThis

The Prime Number Shitting Bear



http://alpha61.com/primenumbershittingbear/

2009年2月8日星期日

$150 has been comsumed!

本以为拖上一段时间MSECompany里的东西就会有所更新,结果让人失望,索性我还是有中意的产品,于是还是买了先。
在购买前也斟酌了很久,在Google里搜索到的资料也仅限于《Victorinox Swiss Army Base Camp — Only MVP (http://goxia.maytide.net/read.php/1027.htm)》 。

我个人认为这是一款限量版,因为是定制的,所以不可能量多,而且购买的人仅限于MS的员工以及合作伙伴等,也就是当赠品,MS是大公司是真的,但价值并不在MS身上,或者显得有点掉价,Swiss Army的东西是出了名的精品,手表虽然不比劳力士、浪琴等享有盛誉,但也是顶尖的牌子吧。起码他们的刀具经久不衰。

上次在Open day上特意看了马宁手上的那款手表,据说就是这款,可怎么当时觉得无比单薄,就像是地摊货,但今天拿在手上,还是挺有分量的,看来可能有所出入,下次见面的时候一定要好好比较一下。

说了这么多废话,大家一定等不及了吧,gOxiA的图片怕是手机拍的,不是很清晰,也让我晕了很久,既然已经到手了,就给大家上几张清晰靓丽的照片。












另外这款是鼠标,Wireless Laser Mouse 6000 EN/FN/E,是Made in China的,真是绕了一个地球的产品,去了一趟美国又飞回来了。这款手表的内部报价是$20美金,而大陆市场上盒装是在499左右,官方推荐价格是¥599,还是比较超值的。原本打算为自己购置一个摄像头,后来考虑到$20美金的摄像头那里只有一两款,而且它们在大陆的售价却只有三百多,觉得有亏了的感觉,而且平时也没人跟我视频,还是以后找个MM再买个高清的,$20的MS摄像头,也是最低档次的了。对了,这款鼠标在淘宝的工包价格却是低的可以,一百多两百就能够搞到手了,不知道货品正不正。其实鼠标对我也是多余,因为我手头也是一个Wireless Notebook Laser Mouse 6000,不过是淘宝的工包货,不过当时买的时候刚上市,好像是¥299买的。




2009年1月23日星期五

利用Windows Mobile系统和Microsoft Outlook群发手机短信

又到了一年的春节,每年的这时候总要给亲朋好友发送祝福短信。现在朋友一圈又一圈的,从小朋友到大朋友,几乎都是手机用户。打开手机,号码少说也有一百来个,这可给群发带来了不少难题:
1、以前用过的手机有群发人数限制,人一多,就难免出错,而且有的手机不好操作,或者你压根就不怎么发短信,边看春节晚会边发短信经常让你冒汗,而且时不时还收到别人的短信,有的手机干脆在这时候回到初始画面,让你功亏一篑。
2、有的手机,不具备群发功能,或者群发功能需要反复选取联系人列表,对于性能略差的低端手机以及那些操作步骤较为繁琐的手机,这种操作无疑要人吐血,而且除夕的网络忙现象始终没能很好解决,有的手机干脆不保留任何痕迹,让你从头来过,最后很多人只好放弃。
3、手机质量让人堪忧,不少手机已经年迈失修,经常死机跳闸,对这种性能消耗较高的情况来说,失败率直耸云天。
现在使用智能手机的朋友越来越多了,就市占率来说,Windows Mobile当然是首屈一指的。不过很遗憾的是,其实Windows Mobile 6(哪怕只是部分版本)的群发功能十分薄弱,具体表现为需要反复点选收件人,并从联系人中选择,更吐血的是,再次选择的时候需要从头开始选,假设有一百人,那么这个拉动滚动条的感觉就绝对像是100!(100的阶乘)。
虽然群发功能很薄弱,但是始终支持群发功能。使用Windows Mobile的用户大部分都安装了Microsoft Outlook用来同步数据,也就是你的联系人信息在PC端会有一个一样的拷贝。相比对着几寸的小尺寸屏幕操作慢悠悠的手机,操作电脑可谓是方便快捷了。下面就教你几步来让你疯狂群发短信。(如果你下一年的交际圈没有拓宽的话,今年的列表仍然可以继续使用!非常方便)

原理
这里用“原理”二字,显得有点过了,这里只是一个基本思路的概括。首先Windows Mobile系统群发短信的时候,只需要在收件人中包含下面格式的手机号码即可:
13912345678;13812345678;……
也就是多个手机号码用分号分隔。所以我们只需要将所有的联系人的手机号码转换成以上形式,即可顺利发送短信了。

具体步骤
1、将手机的最新联系人信息和Microsoft Outlook同步(请确认同步构建已经勾选了同步联系人列表),现在你就可以在Microsoft Outlook中查看到最新的联系人列表了。
2、打开Microsoft Outlook,选择“文件”->“导入和导出”->“导出到文件”->下一步,选择“Microsoft Excel 97-2003”,选择导出文件夹的位置,从目录树中找到“联系人”,将文件导出为(选择一个路径,即可保存相应的联系人)


















3、打开导出的xls文件,如果没有安装Microsoft Excel的朋友,可以将其上传到Google Docs上(http://doc.google.com/该步骤可能要求你拥有Google账户,Google是全球领先的计算机搜索服务供应商)
4、找到“手机号码”一列,在右侧添加一列(在Microsoft Excel中的步骤大致为:将鼠标放置在要插入列的标题上,右键,选择“插入”,即可)。在新插入的列中,添加“;”(分号)(在Microsoft Excel中的步骤大致为:在第一行中添加一个“;”,注意是半角的!然后将鼠标移至第一格的分号处,按住键盘上的alt键,将鼠标移至第一格的右下角处,鼠标指针会变成较浓较短的十字,这时垂直拉动鼠标,并保持鼠标左键始终处于按下状态,一直到最后一行,松开鼠标,就可以发现整列都被填充了分号)

5、新开一个记事本,并将移动电话列和分号列同时选中,并复制到记事本中。我们会发现在号码和分号之间有个TAB空,没关系,复制一个TAB空,并在记事本中打开“替换”功能,在“查找内容”空格中粘帖刚才复制的TAB空格,并使“替换为”空额一无所有(连空格都别有),并点击确定,这下就可以看到所有的号码都被整理成漂亮的格式了。

6、检查一下你的号码中是否有小灵通等号码,以及一些可能是错误的号码,就可以将它保存到文本文件中,并通过我的电脑中的“移动设备”复制到手机中,这个步骤就像操作一个U盘,很是方便。

7、在手机中找到并打开相应的文件,反选文本,复制到短信的“收件人”处,并编辑好祝福短信,点击发送。就大功告成了!
注意:由于群发祝福短信可能涉及几百个号码,所以短信可能一直处于发送中的状态,不要担心,这时候你放心去看春节晚会就可以了,大概十几分钟后短信就全部发送完毕了。这个过程可能比较长,但远比一条一条发送短信要来得方便。
还犹豫什么呢?赶快购入正版Office和带有Windows徽标的智能手机吧!

2008年12月21日星期日

[转载] VC/C++的中文字符处理方式

全文下载链接(可打印,已排版,并修改若干错误)
下文为原文转载,未经任何修改:

以下为原文转载,未经任何修改:
一 引入问题
代码 wchar_t a[3]=L”中国”,编译时出错,出错信息为:数组越界。但wchar_t 是一个宽字节类型,数组a的大小应为6个字节,而两个汉字的的unicode码占4个字节,再加上一个结束符,最多6个字节,所以应该不会越界。难道是编译器出问题了?
二 解决引入问题所需的知识
主要需两方面的知识,第一个为字符尤其是汉字的编码,以及语言和工具的支持情况,第二个是vc/c++中MutiByte Charater Set 和 Wide Character Set有关内存分配的情况.
三 汉字的编码方式及在vc/c++中的处理
1.汉字编码方式的介绍
对英文字符的处理,7位ASCII码字符集中的字符即可满足使用需求,且英文字符在计算机上的输入及输出也非常简单,因此,英文字符的输入、存储、内部处理和输出都可以只用同一个编码(如ASCII码)。
而汉字是一种象形文字,字数极多(现代汉字中仅常用字就有六、七千个,总字数高达5万个以上),且字形复杂,每一个汉字都有"音、形、义"三要素,同音字、异体字也很多,这些都给汉字的的计算机处理带来了很大的困难。要在计算机中处理汉字,必须解决以下几个问题:首先是汉字的输入,即如何把结构复杂的方块汉字输入到计算机中去,这是汉字处理的关键;其次,汉字在计算机内如何表示和存储?如何与西文兼容?最后,如何将汉字的处理结果从计算机内输出?
为此,必须将汉字代码化,即对汉字进行编码。对应于上述汉字处理过程中的输入、内部处理及输出这三个主要环节,每一个汉字的编码都包括输入码、交换码、内部码和字形码。在计算机的汉字信息处理系统中,处理汉字时要进行如下的代码转换:输入码→交换码→内部码→字形码。
(1)输入码: 作用是,利用它和现有的标准西文键盘结合来输入汉字。输入码也称为外码。主要归为四类:
a) 数字编码:数字编码是用等长的数字串为汉字逐一编号,以这个编号作为汉字的输入码。例如,区位码、电报码等都属于数字编码。
b) 拼音码:拼音码是以汉字的读音为基础的输入办法。
c) 字形码:字形码是以汉字的字形结构为基础的输入编码。例如,五笔字型码(王码)。
d) 音形码:音形码是兼顾汉字的读音和字形的输入编码。
(2)交换码:用于汉字外码和内部码的交换。交换码的国家标准代号为GB2312-80。
(3)内部码:内部码是汉字在计算机内的基本表示形式,是计算机对汉字进行识别、存储、处理和传输所用的编码。内部码也是双字节编码,将国标码两个字节的最高位都置为"1",即转换成汉字的内部码。
(4)字形码:字形码是表示汉字字形信息(汉字的结构、形状、笔划等)的编码,用来实现计算机对汉字的输出(显示、打印)。
2.VC中汉字的编码方式
vc/c++正是采用了GB2312内部码作为汉字的编码方式,因此vc/c++中的各种输入输出方法,如cin/wcin,cout/wcout,scanf/wsanf,printf/wprintf...都是基于GB2312的,如果汉字的内码不是这种编码方式,那么利用上述各种方法就不会正确的解析汉字。
仔细观察ASCII字符表,从第161个字符开始,后面的字符并不经常为用户所使用,负值也未使用。GB2312编码方式充分利用这一特性,将161-255(-95~-1)之间的数值空间作为汉字的标识码。既然255-161 = 94不能满足汉字容量的要求,就将每两个字符并在一块(即一个汉字占两个字节),显然,94* 94 =8836基本上已经满足了常用汉字个数的要求。计算机处理字符时,当连续处理到两个大与160(或-95~-1)的字节时,就认为这两个字节存放了一个汉字字符。可以用下面的Demo程序来模拟vc/c++中输出汉字字符的过程。
unsigned char input[50];
cin>>input;
int flag=0;
for(int i =0 ;i < 50 ;i++)
{
if(input[i] > 0xa0 && input[i] != 0)
{
if(flag == 1)
{
cout<<"chinese character"<<endl;
flag = 0;
}
else
{
flag++;
}
}
else if(input[i] == 0)
{
break;
}
else
{
cout<<"english character"<<endl;
}
}
输入:Hello中国 (“中国”对应的GB2312内码为:214 208,185 250)
输出:english character
english character
english character
english character
english character
chinese character
chinese character
vc/c++中的英文字符仍然采用ASCII编码方式。可以设想,其他国家程序员利用vc/c++编写程序输入本国字符时,vc/c++则会采用该国的字符编码方式来处理这些字符。
问题又产生了,韩国的vc/c++程序在中国的vc/c++上运行时,如果没有相应的内码库,则对韩语字符的显示有可能出现乱码。我个人猜测,vc安装程序中应该带有不同国家的内码库,这样一来肯定会占用很大的空间。如果所有的国家使用统一的编码方式,且所有的程序设计语言和开发工具都支持这种编码方式该多好!而现实中,确实已经有这种编码方式了,且许多新的语言也都支持这种编码方式,如Java、C#等,它就是下面的Unicode编码
3.新的内码标准---Unicode
Unicode(统一码、万国码、单一码)是一种在计算机上使用的字符编码。它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。1990年开始研发,1994年正式公布。随着计算机工作能力的增强,Unicode也在面世以来的十多年里得到普及。最新版本的 Unicode 是 2005年3月31日推出的Unicode 4.1.0 。另外,5.0 Beta已于2005年12月12日推出,以供各会员评价。
Unicode 编码系统可分为编码方式和实现方式两个层次。
编码方式:Unicode 的编码方式与 ISO 10646 的通用字符集(Universal Character Set,UCS)概念相对应,目前的用于实用的 Unicode 版本对应于 UCS-2,使用16位的编码空间。也就是每个字符占用2个字节。这样理论上一共最多可以表示 216 个字符。基本满足各种语言的使用。实际上目前版本的 Unicode 尚未填充满这16位编码,保留了大量空间作为特殊使用或将来扩展。
实现方式:Unicode 的实现方式不同于编码方式。一个字符的 Unicode 编码是确定的。但是在实际传输过程中,由于不同系统平台的设计不一定一致,以及出于节省空间的目的,对 Unicode 编码的实现方式有所不同。Unicode 的实现方式称为Unicode转换格式(Unicode Translation Format,简称为 UTF)。如,UTF-8 编码,这是一种变长编码,它将基本7位ASCII字符仍用7位编码表示,占用一个字节(首位补0)。而遇到与其他 Unicode 字符混合的情况,将按一定算法转换,每个字符使用1-3个字节编码,并利用首位为0或1进行识别。
Java与C#语言都是采用Unicode编码方式,在这两种语言中定义一个字符,在内存中存放的就是这个字符的两字节Unicode码。如下所示:
char a='我'; => 内存中存放的Unicode码为:25105
4.内码的相互转换
(1)vc中的实现方法
利用Windows系统提供的API:::MultiByteToWideChar::WideCharToMultiByte
::MultiByteToWideChar实现当前码到Unicode码的转换;
::WideCharToMultiByte实现Unicode码到当前码的转换;
(2)Java中的实现方法
String vcString=new String(javaString.getBytes("UTF-8"),"gb2312");
java的编码应该是UTF-8
(3)C#中的实现方法
??
四 vc中的MutiByte Charater Set 和 Wide Character Set
1.MultiByte Charater Set方式
这种方式以按字节为单位存放字符,即如果一个字符码为两字节,则在内存中占两字节,字符码为一字节,就占一字节。例如,字符串“中国abc”的编码为:中(0xd6、0xd0)、国(0xb9、0xfa)、a(0x61)、b(0x62)、c(0x63)、\0(0x00),就存为如下方式:

原始图片链接:http://p.blog.csdn.net/images/p_blog_csdn_net/fishinthewind/win_1.bmp




对应的类型,方法有:
char、scanf、printf、cin、cout …
2.Wide Character Set
这种方式是以两字节为单位存放字符,即如果一个字符码为两字节,则在内存中占四字节,字符码为一字节,就占两字节。例如,字符串“中国abc”就存为如下方式:

原始图片链接:http://p.blog.csdn.net/images/p_blog_csdn_net/fishinthewind/win_2.bmp



对应的类型,方法有:
wchar_t、wscanf、wprintf、wcin、wcout …
造成上面存储方式的根本原因在于,wchar_t类型其实是一个unsigned short 类型。如,存储上面字符串的数组的定义为:wchar_t buffer[8] 等价于unsigned short buffer[8].而所有以字母w开头的方法也都是以unsigned short类型,即两字节为单位来处理字符,因此,存储在wchar_t类型数组中的字符串无法用cout显示,只能用wcout方法来显示。
由于Unicode码也是采用两个字节,因此Wide Character Set方式能够很好的支持Unicode码的存储,但是在vc的环境下要将一个Unicode码存入两字节而不是四字节内存中,必须通过上面的API函数::MultiByteToWideChar首先,将当前的编码转换为Unicode码,然后,将每个字符的Unicode码放入每一个wchar_t类型的变量中。以下是一个实例代码:
char input[50];
cin>>input;
int size;
size=::MultiByteToWideChar(CP_ACP,0,input,strlen(input)+1,NULL,0);
if(size==0)
return -1;
wchar_t *widebuff=new wchar_t[size];
::MultiByteToWideChar(CP_ACP,0,input,strlen(input)+1,widebuff,size);
输入:中国abc
Debug断点调试:
size==6
数组widebuff[0-size]占12字节,存放了6个字符的Unicode码,码值为:
中(0x4e2d) 国(0x56fd) a(0x0061) b(0x0062) c(0x0063) d(0x0000)
这时,数组的大小size等于输入的字符个数加上一个结束符,符合我们的想象。
五 引入问题的错误分析
(1) 没有理解编译器中的编码方式
虽然vc/c++中汉字的编码占两个字节,但并不是Unicode码,是GB2312码。
(2) 没有理解MutiByte Charater Set 和 Wide Character Set的存储原则;
在vc/c++中,“中国”按char[5]来对待,而wchar_t a[3]实际上是三个unsigned short类型的变量,因此赋值时会越界。

2008年10月16日星期四

Received the MSDN Subscription compast disks

I have received the MSDN Subscriptions from the Beijing filiale of Microsoft in Oct 17, 2008. It's a large bag!It contains a lots of Microsoft products. Oh, I have nothing to say......! :) -_-"
Posted by Picasa