5/20/2016 2 Comments 卡尔加里复旦同窗在卡尔加里 李革胜 (一)莫愁前路无知己,天下谁人不识君? S同学在卡尔加里碰上他在复旦的同窗Mike。Mike是复旦计算机系本科,硕士,博士毕业生,他是通过S认识G同学的。当时,上海还没有因特网,只流行Novell网,它是用一种与IBM PC 兼容的ISA网卡来交流的互联网,大家都曾是电脑硬件发烧友。对于北美IT行业,Mike一向高山仰止,能在北美做IT是他多年前在复旦苦读计算机的夙愿。 Mike移民加拿大后,他发现加拿大人对上海的名牌大学复旦并不熟悉,加拿大人知道中国的大学有清华,北大,中科大,复旦计算机闻所未闻,卡尔加里的IT行业对复旦并不十分了解,很多加拿大人从没听说过在中国如雷贯耳的复旦大学。Mike人地生疏为了找工作,他只能和NAIT的专科毕业生在就业市场上竞争。看上去是没有办法的事,别人要挑错容易得很,本地的就是要挑剔外人? Mike在一家小软件公司找到程式设计员的工作,这对于复旦计算机博士来讲,的确大材小用。这虽是家电子商务软件小公司,却是给大名鼎鼎的IBM做合同Contract的,技术含量满高。因为是经济项目金融业合同,Mike被公司蒙在鼓里,一切在悄悄地进行。Mike的工作是给IBM的通用数据库DB2做外部链接程式设计,他用得最多的工具软件当然是微软的VisualStudio、Java JDK、Eclipse、Linux、Python与Siliverlight等。Mike一进公司就被经理Operational Manager Kevin安排给老印做软件测试员,老印原来是学会计的,因为听说写Code可以找到轻松的高薪工作,在NAIT学了个编程证书就匆匆忙忙做程序员了,他的capability与Mike十年磨一剑的编程能力相比差了十万八千里。老印当初为了得到程序员这份工作,就在申请材料里撒了个谎,说他有十年IBM编程经验及计算机博士学历等。当时公司正急着用人,鬼使神差,HR隔山买老牛,就把chief programmer 的位置给了老印。 上班第一天,Kevin就发现老印连股票系统单位脉冲响应就是系统闭环传递函数的拉氏反变换,二阶期货系统响应就是系统的导数等入门知识都不知道,没有想到HR招了个Y货。Kevin如鲠在喉,他亲自把老印叫到一边,开门见山,请老印做最简单的mason公式求股票系统的传递函数,并用劳斯判据近似分析股票延滞系统的稳定性。这些术语,一般计算机本科生都闻所未闻,老印更是丈二和尚摸不着头。第一天上班,Kevin就知道公司招了个大兴货(冒牌货)。人已经进来了,生米煮成熟饭,为了公司的声誉及其他不能言明的原因,也不能马上把老印打发走。Kevin知道如果现在把老印开除,IBM是不会再把合同交给公司了,Chief码工居然是个冒牌货,传出去公司的颜面何存?HR全部都要换人,小公司赔不起那么多遣散费。Kevin只好暂时把老印留在手下做些简单的Code,慢慢找机会再把老印扫地出门。再说,老印也不是一无是处,毕竟最简单的冒泡排序与桶排序伪代码,老印还是会的。 等到Mike这位复旦货真价实的计算机博士来应聘时,公司只有程序测试员的位子了。上海人讲英语有个弱点,重音不分,如character重音在第一个元音,importantly重音在第二个元音,他老是混淆不清。重音找不到,别人就不知道他在说什么。移民加拿大二十年了,说出来好笑,Mike连bike与 back,truck与track都分不清,别人不知道他指的是哪一个。搞IT的人大多耐心都不好,没有人当Mike是个人才。加上复旦计算机在卡尔加里的IT行业没有什么名气,Mike的上海腔英语晦涩难懂,HR吃一堑,长一智认定Mike也是个Y货。Mike就是这样空有复旦计算机博士学位只能做工资最低的软件测试员,他觉得委屈,自己的编程能力没有人能够理解,确实被埋没了。Mike刚到公司上班时,Kevin就担心Mike不懂北美IT行业潜规则给自己找麻烦。所以他宁可用狗屁不懂的老印也不愿用Mike这个新手,人人都有长有短,不管怎么说,老印那口流利的英语可以把大多数问题支吾过去。HR安排Mike当测试员,Kevin明知Mike大材小用,也就没有公开反对。 因为是小公司,Mike什么都要做,他既是源代码开发人员,又是软件测试人员与QA。一句话,Mike从程序规划,界面设计,算法选择,二叉树流程图,数据库连接,code 输入测试客服,事无巨细啥都要做,Mike天天在公司忙得团团转。此外,Kevin经常抓Mike做客服与软件新版本月发布人员。每个月都搞他一次,象女人来月经让他忒不舒服。这就是公司对外自诩的所谓Test Driven Development TTD管理新技术。Mike到公司上班以后就发现软件公司本质上是个血汗工厂,是非之地不可久留。所以,Mike刚开始工作不是特别上心,骑驴找马,他把大量的时间都用来找更好的工作了。Mike非常聪明, 他很快发现加拿大的工作是要看历史的,现在的工作是下一份工作基础。如果现在的工作没有做好,下一份工作会更糟。想到这些Mike安下心来,把这份测试员的工作做好,既来之,则安之,他这样安慰自己。 Mike一进公司就察觉,电脑公司里面同事间的竞争与角力相互交织,纯粹是rat race。Mike刚进公司时,老印经常以senior employee的名义,把没作完的程序存档,作为虫子(bug)来给他捉。名义上是Debug,其实是给老印的Code擦屁股。老印写的程序从头到尾全是小尾巴,根本没有办法拿出来见人。其实老印这么做也有苦衷,他有些bug确实看不出来。这位半路出家的老印基本功不扎实,连程序流程图都不会做,老是搞不清尚程序测试点覆盖不能代替边覆盖的道理,即使百分之百语句覆盖对于不可达代码Bug也看不出来,不会做指数增长边界值分析等。这是IT行业的普遍现象,北美很多程序测试员因为没有扎实的理论基础,拿个编程证书匆忙披挂上阵,大都不知道测试软件最多做百分之百点覆盖,很少有做百分之百边覆盖的,找不出的Bug当然多。越是新的程序, Bug就越多。 (二)九死南荒吾不恨,兹游奇绝冠平生 Mike回忆起刚来卡尔加里时,找不到工作,他不得不去gathering place蹭饭。吃每顿一刀一份的冰冻碎蟹肉,蟹肉据说是从美国东部曼哈顿运来的。以前在上海也就是过年才舍得吃一回鲜美的大闸蟹,现在天天吃蟹肉,却从没有想到过蟹肉这么难吃,蟹肉里面放了很多醋,要喝难以下咽的胡萝卜姜汁汤拌着圆须菜才吃得下去。Mike安慰自己,现在总算可以写程序做专业,强过在中餐馆洗碗吃冰冻蟹肉,能忍就忍吧。 Mike喜欢写信,他总是去邮局买Booked Stamp作邮票并把剩余的邮票放进皮夹子(钱包)图个方便,过一段时间,邮票拿出来看上去有些旧,没有想到白人竟然无缘无故怀疑他用假邮票。好几次,邮局把他的信退回来,刚开始,他也不以为意,白人莫名其妙的事情太多,他也没有去多想,默默地换上新邮票再把信寄出去。直到有次牧师阴一句阳一句地问他,把用过的邮票再贴回去对不对?Mike出离愤怒,我每年上千加元无偿捐给教会,我为什么要去占邮局块把钱的便宜?邮票看上去是旧的,就是假的吗?碰到有洁癖的白人,Mike默默地忍耐,他是不会把这些小事放在心上,自己的时间精力有限,太在意细节不合算,祷告是他的绝招。何况,Mike有天看到老牧师带着五个老太婆在逛公园,他心想牧师轧姘头其实也不容易。 Mike养成祷告的习惯完全是周围的白人逼出来的,刚来加拿大时,他发现白人们有意无意就祷告,对方祷告完后,自己莫名其妙觉得特倒霉,他也去书店买本《圣经》,无师自通也学会了祷告。 有一次在马路上一个白人莫名其妙向他竖中指,Mike过了很久才明白这个白人要平行泊车怨他没有预留足够空间,找碴欺负他。你要平行泊车应该事先打右灯,我怎么知道你是直行,右转还是泊车?Mike刚学会开车,那时年轻的Mike并不知道,还有一种可能性存在,那白人打了车灯的,只不过白人不知道自己的车灯坏了。他经常想起小时候国内流行的一句童谣:一二一,一二一,高鼻子洋人不讲道理,原来旧社会白人在中国欺负中国人是真的。 白人不讲道理起来比中国人还厉害,Mike有切肤之痛,他经常在马路上被白人拦住,甚至被吐口水,恶言相向。他过了很久才琢磨出可能白人骂是他走路没有让人,这能怪他吗?在人山人海的五角场你要是过马路让人,你永远出不了门,上不了公共汽车,你在上海任何地方都必须挤。没有想到加拿大人这么虚伪,后来,Mike学聪明了,一旦有白人在大街上拦住他聊天,Mike最多聊六句话扭头就走。根据六度理论,六句话就可以把所有的意思表达清楚。六句话说完后,他必须找借口走开。否则话不投机,对方就会不分青红皂白,骚扰他,开口骂他。Mike实在无法理解他们白人那一套所谓距离与隐私,慢慢地他也跟着广东人管白人叫“鬼佬”。 Mike有段时间特别不喜欢白人,比如他周围的白人都用中指开电梯,用手机,玩键盘,从没有遇到麻烦。他认为是时髦,一次他尝试用中指按电梯按钮,一个白人无缘无故冲他发怒,原来只许州官放火不许百姓点灯,中指只能是白人的专利。公开说F word,叉开两腿等行为也只能是白人的专利,民主自由在加拿大是空话?从心理学上讲,Mike碰到的大多是白人的“无意识攻击”,攻击的目的可能是想与中国人打个招呼,所以,Mike遇到老外的骚扰,他能忍就忍了。 有段时间Mike尽量避免和周围的白人同事见面说话,因为他知道一旦白人不喜欢你,任何语言动作都可能引起对方的误解,简直是群不可理喻的人种。Mike刚来卡城时,在大街上莫名其妙被白人骚扰是家常便饭。过分的时候,自己没有做什么也没有说什么,他被白人当街拦住劈头盖脸臭骂过好几次。英语不好会只有挨骂的份,就是打911,警察来了也不管。卡城的警察怪得很,当地人再坏也只当没看见,外国人犯一丁点错,警察就会来找茬。刚来卡尔加里时Mike发现周围的白人都飙车,自己随乡入俗跟着加快速度,因为稍微开慢了,后面的白人会追上来破口大骂。Mike没想到第一次超速就被警察抓了,被罚款还有历史纪录,汽车保险上涨。Mike有次开车下意识把手机抓在手里,并没有使用,被警察看见,“分心驾驶”挨了一张罚单。手机通信时间都是有记录的,他在挨罚单的前后三小时内都没有通话与上网记录,这就是没有使用手机的证明。卡城满大街都是边开车边抽烟的白人司机,手里拽着电话与叼根香烟有什么区别?夏天,很多白人司机大都在外国人面前把左手放出车外凉快,那和手里拿着手机”分心驾驶“有什么区别?警察为什么不管?Mike有时候甚至怀疑,这些白人司机与警察勾结起来钓鱼执法,白人司机给不了解情况的外国人做示范,警察在旁边蹲坑等着罚款,专门对付他这样的人赚外快。 Mike这么想是有原因的,刚来卡城时,一个上海老乡经常登门拜访,后来他发现这个老乡是当地赌场的托儿,找他是来为赌场培养赌徒的。Mike从来不赌博,他从不跟人打赌。周围的白人常常无缘无故地认定他好赌,这让他很无语。白人对非白人的偏见是根深蒂固的,可怕的是绝大多数外国人对此一无所知。Mike很理解钱学森终身不再去美国,因为钱学森对美国白人的丑恶有很深的印象。金无怠在美国有那么好的待遇,为什么选择背叛美国?因为他看透美国白人的内心世界,美国白人的种族歧视与对华人的无缘无故的敌视让他别无选择。有些白人对中国人这个种族无缘无故的仇视让Mike内心相当震惊,这是他在复旦读书期间万万没想到的,他想不通为什么远隔中国万水千山的白人会如此敌视中国。 其实每个城市都一样,有好的一面,也有阴暗的一面,卡城也不例外,哪里都有好人,也有坏人。白人里有好人也有坏人,碰上一个坏人,不等于所有的人都是坏人。哪里都有称职的警察与不称职的警察,碰上不好的警察不等于所有的警察都是坏人。 Mike为避免挨骂从不主动找白人说话,因为他不想自取其辱,就是这样他还是经常莫名其妙受到周围老外的搞怪表情,白眼与呵斥等隐形歧视。好在Mike抗压能力天生就强,习惯成自然,每当有白人给他隐形歧视,他就对自己说,对自己好点,你面对的是个没有感情的机器人,不要把别人强加给你的压力当回事。如果有白人对他破口大骂,他都把他们当成狗在吠。白人在那里骂得唾沫横飞,他心里暗答,“狗在叫。”人就释然了。他有上海男人的优点,脾气好能忍耐。白人对他百般辱骂,他从不生气,总是先找自己的不是,再总结经验。邻居的狗每天在Mike下班回家的路上都对他叫,在他眼中,两者没有区别。根据经济学上的科斯定律,邻居有养狗的权利,其他邻居也有享受安静的权利。Mike半夜下班路过邻居家,狗会吠,这样会吵醒其他邻居。邻居间协商成本太高,所以Mike宁可多绕个圈子也不愿吵醒邻居,Mike的确是个好人。 这种想法时间一长,只要有白人骚扰他,辱骂他,他条件反射地把对方看成一条疯狗,自己一点都不生气,狗要吠,你有什么办法?Mike的这种想法来自王阳明”此花与汝心同归于寂”的心外无物哲学思想,用虚无对付现实。他挺理解蒋介石作为一个基督徒却推崇曾国藩的儒家思想与王阳明的唯心主义,都是环境逼迫的。Mike也挺理解他在复旦的外教曾公开骂上海人象动物,独在异乡为异客的滋味真不好受。 Mike这种凡事忍耐的处事方式很快炉火纯青,每当有老外欺负他,他心里马上产生条件反射,对方又是一头两脚动物而已,他一点都不生气。一次一个白人无缘无故在大街骂他asshole,他听后微微一笑,狗又在叫了。骂别人asshole,其实是在暗示自己是个asshole,是在骂自己asshole。听的人把脏话当成耳边风,结果骂人的人反被自己的恶毒伤害,这是个很多人都不知道的心理学秘密。 很多中国人来北美抓狂,发疯甚至得忧郁症,是被白人迫害造成的。中国是个人情社会,被陌生人莫名其妙地歧视在中国现在很少发生了。如果一个素不相识的白人当着一群陌生人的面无缘无故突然用嘲弄的表情,撇嘴,皱眉等故意针对中国人,围观的白人也无缘无故地用语音动作表情等对势单力孤的中国人的歧视表示赞同,很容易让这个没有准备的中国人开始愤怒,继而害怕抓狂,自己还说不来。如果中国人这样对白人,白人就会依仗自己英语好,不依不饶揪住不放。在北美,只能白人歧视华人,华人不能歧视白人。Mike每天都看到有中国人高高兴兴,突然就变得愁眉苦脸,委屈与愤怒,有苦说不出。北美的华人都是一副苦瓜相,这大都是白人隐形歧视造的孽。蒋国兵跳桥、卢刚杀人应该都是在没有准备的情况下突然受到隐形歧视,心理承受不了而干下傻事。Mike自己也经常受到白人的这种无缘无故的隐形歧视,但他从不生气,他有心理准备对歧视无动于衷,犯不着为一个两脚动物怄气。动物凶猛,离对方远一点就可以了。 很多时候Mike那副不亢不卑,油盐不进的样子把故意欺负他的人气得咬牙切齿。真是”他强任他强,清风抚山岗;他横由他横,明月照大江”。(《倚天屠龙记》) Mike从来没有想过寻求警察或中国人的帮助,因为他知道没有用,白人永远是对的,警察与国人是站在白人那边的。每当白人无缘无故辱骂他的时候,Mike就象个小学生站在那里听对方的破口大骂,安静地洗耳恭听,等对方骂完了,他还客气地征求对方的意见,”can I go now, sir?”。否则,对方还可能恶人先告状,报警。唉,人在屋檐下不得不低头。太多数国人没有机会与白人近距离接触,很难理解大街上一个没有任何关系的人会无缘无故谩骂另一个陌生人,白人羞辱华人在北美其实是个常见现象。 Mike找不到高薪工作,他只能租红灯区附近的柏文。有天傍晚,他见工在回家路上,一个妓女把咪咪贴了上来。他只好把”黄蓉”推开,在«射雕»中黄蓉刚出场时就是个小乞丐,加拿大的白人剩女都知道中国嫖客喜欢”黄蓉”,就故意把自己打扮成”黄蓉”。Mike把所有的女乞丐通称为”黄蓉”,望着满大街的”黄蓉”,Mike开始反思移民加拿大这步棋是否走对了。 Mike对一个头发染绿的妓女印象非常深刻,这是个黑头发黑眼睛黄皮肤亚洲的女孩。他经常看见她在街边弄堂揽客,或楼着头小黄狗酣睡在公司楼梯间。她怀里的那只小黄狗,非常凶猛,每当有人靠近她,小黄狗就叱牙咧嘴狂吠。 他第一次见到绿头发妓女竟然是在他儿子所在小学的操场上,刚开始他并没有意识到这是个妓女,他只是远远望见一个染绿头发的姑娘把秋千荡得老高,并发出银玲般无邪的笑声。这是Mike久违的那种在中国内地才能听到了的那种发自内心的笑声,只有在没有种族歧视,人民真正当家作主的社会主义中国才能听到这样无忧无虑的发自内心的笑声。在资本主义社会,少数民族是不可能有机会拥有这样的心态,如果一个华人骤然在白人面前这样笑,肯定会把对方吓一跳,白人肯定会找机会报复修理她。当然,Mike不认为加拿大有这些社会瑕疵就不如中国,要不然他也不会放弃中国的工作毅然移民加拿大。他曾经把自己放在白人的位置上,互换立场辩证分析问题是Mike的长处。试想,一个白人姑娘在他没有准备的情况下驟然发出大笑,他也感到莫名的害怕。白人之间的人际交往远不如中国人,很多白人甚至不懂得如何与人深入交谈。Mike刚登陆卡城时,他与一白人在教会的饭桌上交谈甚欢,那白人谈话中突然变脸,一头钻到饭桌底下。Mike低头看去,那白人竟然在饭桌下用手捡掉在地上的面包屑,这让Mike郁闷,他心里堵了很久。多年以后,Mike才渐渐明白:那白人是不会如何与人交谈,用捡地上的面包屑掩盖自己的尴尬。 所以,Mike得出经验:在多元文化环境里他必须尽量装斯文,尽可能温闻而雅,这样才不会引起老外的恐慌。其实这样做没有什么不好,人与人交往本身就应该斯文,礼貌,逻辑性强。这都是他被白人百般辱骂后总结得出的经验,毕竟多元文化的处事之道与礼仪之帮一元化的中国完全不同。 绿头发妓女非常聪明,Mike有看到她竟然用手机自拍功能当镜子打扮自己。回去后,Mike在公司常用电脑摄像头当后视镜来观察Kevin的动向,这种反老板监视手法就是从她那里得来的灵感。绿头发妓女从来不说话,显得非常温顺,问她什么都是轻轻地点头,Mike估计她的母语不是英文,应该不是印第安人。印第安人在华人面前总是夸夸其谈地卖弄英文。这很正常,每个人都喜欢把自己好的方面拿出来夸耀,华人的短板在英文。在华人面前多讲英文可能找个英文家教工作,Mike估计她极可能是个偷渡来加拿大的广东妹。有年冬天他半夜踏雪下班回家,远远看见绿头发披着厚厚的毛毯在大街上惊慌失措地奔跑。看样子她是睡在某个地方忽然被人赶了出来,凌厉的北风冻得她嗷嗷叫。那年夏天,Mike看见绿头妓女穿戴整齐,在一家房地产公司当售楼小姐,他霍地明白房地产红火的原因了。 从内心上讲,Mike对乞丐与妓女没有多少同情,因为他租的房子就在红灯区,经常有乞丐妓女骚扰他们一家,对她们只能敬而远之。听到妻子惊恐的尖叫声,看到妻子被大黄狗吓得花容失色。他对乞丐们躲都唯恐不及,被妓女们搞得焦头烂额,哪里有心情谈得上同情?Mike从踏上加拿大土地的那一天开始就有这个感觉,加拿大的乞丐妓女都是为了某个目的装出来的,并不一定是真穷。加拿大乞丐与中国的有些不同,这一观点Mike虽然没有什么证据,但他莫名其妙就有这样的感觉。 Mike刚登陆加拿大时经常给乞丐施舍一点小钱,发现乞丐收了钞票后并不感谢他。可能是加拿大比中国富裕很多,连乞丐也见多识广,他施舍的那点小钱根本就是斗升之水,完全帮不了穷人。也可能是白人怕中国人的统战工作?或是为了自由的思想当乞丐?Mike印象最深的是他去Montreal 找工作,在灰狗长途汽车站一个乞丐拦住他要钞票。他给了个Loonie,对方居高临下对他说mercy ,但他忽然产生一个不好的感觉:他自己才是个乞丐,而对方是怜悯他才收了他的施舍。他知道这个想法肯定是错误的,不应该这样啊。 Mike从没有想过白人乞丐也会种族歧视,他毕竟是在复旦见过世面的人,他天生就懂得该大方的时候一定要大方。总的来讲,Mike是个慷慨的人,一点也没有上海人的小家子气。他的记录是一次性给教会捐献过$1,100,而那一年Mike失业在家,全家的总收入当时税前只有$11,000。Mike还是个热心人,他有次听到两白人老娘们在电梯里聊天,她们尿急想在电梯里小便,Mike急忙放下程序,告诉她们厕所位置,过了很久他才发现老娘们说”wanna pee in the pants” 是她们等电梯等得不耐烦的意思,并不一定是要小便。 Mike一个偶然的机会在药房发现一种浓缩咖啡因饮料,是美国陆军使用的,喝一点可以连续48小时不睡觉。这下他找到秘密武器,经常熬夜写程序,还不打瞌睡,让其他程序员羡慕不已。有时候Mike挺羡慕乞丐们可以睡在大街上,他经常在公司熬夜写程序,靠喝浓咖啡硬撑着不打瞌睡,偶尔把私家车停在在公司的车库,他可以卷曲着在车后座上打个盹。Mike工作如此用功,以致他的双眼长期发黑且浮肿。太太曾摸着他的黑眼眶怜惜地说:“知道的人理解你写程序太用功,不知道的人看到你这副模样会认为你性生活太频繁。” 每当夜深人静,Mike爬在计算机上写code,他望着窗外在路灯下熟睡的乞丐们,Mike心想,如果大街打扫干净了,平躺在地上应该蛮舒服,睡在大街上至少可以每月省下两千刀房租,那可是一大笔钞票啊。Mike甚至在网上与人讨论过乞丐妓女的收入是否要上税的问题,当然这是不应该发生的。肯定是什么地方错了,同情穷人是理所当然的事情,对弱者缺乏同情心是精英教育的短板,也是自己的弱点。 Mike从最开始就知道,Kevin故意让他去给老印做测试员,就是要他产生种族歧视感,给他传递一个明确无误的信息,加拿大不是中国人的。一个白人在大街上拦住他,理直气壮地冲他大喊,”chinada”。他才发现原来加拿大不是真正的多元社会,他刚登陆加拿大时,从飞机看见温哥华茫茫苍苍的群山,风光迤逦的UBC校园,一望无际的阿尔伯塔平原,加拿大到处都是青山绿水挺新鲜,他就把加拿大当自己的家,说话做事都把自己当成主人翁。这是任何一个新移民都有的正常反应,此外他并没有任何出格的言行,只是把他成功移民加拿大的喜悦之情表现出来了而已。没想到引起当地白人的猜嫉,中国人是来抢他们的土地的。一个白人曾声色俱历地对他喊,”Canada isn't yours!”这适得其反,Mike听后得出结论,原来白人还怕中国人歧视他们。 Mike认为祷告是解决问题的唯一有效方式。Mike长期被边缘化,得不到重用其实很正常,在任何地方,人与人都有个熟悉过程,人家不了解你怎么会重用你,想到这些他就释然了,毕竟现在的处境比原先想象的啜菽饮水的生活要好得多,现在可以写程序做专业,比在餐馆混饭吃要强得多。 Mike总结了一下,自己在公司错了三个地方,1中国人,2英语口语不好,3从不犯错。老印经常挑他的错,最后也很泄气,不得不承认you are always right。 Mike水平那么高,却一直做测试员的工作,无论如何都没有办法交代,必须给Mike安个罪名才能蒙混过关。Mike在公司没有朋友,很容易给他安个racist的罪名。根据Mike的观察,中国人在北美的职场再怎么努力也不会有真朋友,给所有的中国人戴上racist的帽子很容易。Mike在加拿大生活了20多年,他只见过盲目崇洋媚外的国人,还从来没有见过真心说中国人好话的老外。日本人,韩国人,俄国人,墨西哥人等少数民族都是这样的,不是他们天生苯,而是白人社会的排挤。当然,Mike也承认自己的看法有些偏颇,隐形歧视在哪里都有。 Kevin从小耳濡目染,挑拨离间是行家里手。具体过程是这样操作的,找一个印度合同工暗示他去给Mike自我介绍,名叫”阿三”。Mike信以为真,就在报告中写下”Asan”,再让老印读一篇关于中国俚语的文章,让老印明白”Asan”(阿三)是上海人专门骂印度人的话。这下白纸黑字,老印抓到Mike的把柄,Mike是个种族主义者。老印从此占Mike的便宜就心安理得,谁叫Mike无缘无故地骂印度人? 时间一长,老印根本就不干活了,他认为欺负中国人就是他的工作,没事就让Mike穿小鞋,因为他已经产生错觉只要天天欺负Mike自己在公司的位置就稳定了。周围的同事见Mike干活最多,工资最少,对老印的欺负逆来顺受,也想得通,都不同情他,道德水平低下的中国人当然不配拿高工资。 Mike道德败坏,Kevin还宽宏大量给他工作。中国人也好,印度人也好,大家对Kevin敬意油然而生,Kevin在公司的威信慢慢地树立起来。 Mike姓Li(李),Kevin故意叫他Mr.Lie。大家都很开心,心照不宣Mike是个撒谎的人。每当Kevin在公司高声喊”Mr.Lie”,大家开始窃喜,进而喜大普奔,跟涨工资一样高兴。当Kevin心情不悦,他就与大家聊天,李姓是加拿大最大的姓,大家这时都懂得起,Mike已经是公司的累赘了,Mike自己也觉得矮了一头。 这种职场上的阴谋诡计相当多,有次公司雇佣了个伊朗程序员。Kevin想把伊朗人赶走,自己又不愿意当恶人,故意找个中国临时工去给伊朗人自我介绍,名叫”chink”,伊朗人不知道”chink”是专门骂中国人的,他那天脑子也瓦特了,就在公司到处叫”chink”,把所有的中国人都得罪了,自己还不晓得。最后,中国程序员联手把伊朗人挤出公司,让Kevin不动声色就把伊朗人打发了,”借刀杀人”不是中国人才有的本事,老外一样会玩。一天Mike在lunch room看到有人用铅笔在老印的照片上画了小胡子,他马上知道这是老外在制造摩擦,干紧用橡皮把照片上的小胡子擦掉,免得老印误会。上海职场有坏习惯,有上海同事悄悄在别人的午饭中放安眠药,让同事上班睡觉。这个恶习不知不觉让白人学会了,有让人上班睡觉,老板抓个现行,找机会解雇同事的恶作剧。 这方面的例子很多,Mike又不是傻子,他看在眼里,但从不抱怨。Mike知道被人冤枉,被人愚弄是生活的一部分,他完全不放在心上。人无完人,狗要咬人,你有什么办法? Mike自己生活非常节省,他常年穿一件灰黑色帽衫,头发是他老婆推的板寸,经常左右不齐,在卡城就一屌丝形象。Mike在加拿大几乎没有任何娱乐活动,最多周五晚上去教会吃免费盒饭,然后就是周六蹭别人的车去中国超市买菜,他自己的车舍不得开,20年才开了15万公里。对他来讲,车就是个放在车库的摆设,因为车开得少,dash上积了厚厚一层灰。Mike在加拿大从没下过馆子,最多有时下班顺路在food court买点牛和带回家,他心疼老婆孩子。Mike能给教会捐十分之一的收入,真是大手笔。 多年后,Mike才学会遇到自己无法解释的事情,他总是祷告,要凡事忍耐,要用爱心去解决问题。在加拿大生活了20年,Mike什么都要事必亲躬,他相信多一事不如少一事的好处。用爱心与忍耐去解决问题会让生活更容易些成本低些,这是他的一个小算盘。 (三) 那天,Kevin要求老印把拓扑排序没有输出的入度indegree为零的顶点放在堆栈或队列里,这下把他难住了。老印有个小秘密从没有告诉过别人,有可能是NAIT的教材没有讲清楚,他花了很多时间就是不能理解数据结构中堆栈的概念。堆栈是最基本的数据管理概念,其本质就是线性表排列。提出堆或堆栈概念的程序员估计有仓储经验,会计背景的老印怎么会知道?老印曾seriously认真研读了半天,花了很多时间就是没有搞清楚什么是Stack,要命的是,他真不懂但还不能说出来。chief programmer不懂Stack,别人会笑掉大牙的,公司上层知道了,自己是要丢饭碗的。老印的Chief Programmer完全是为了饭碗装逼装出来的。Kevin曾否定了他程序里的遍历递归,耳提面命要求他用循环堆栈来代替代码中的遍历递归,这样可以节省大量内存,让程序速度加快。上帝啊,他哪里知道什么是二维结构线性化?老印认真研读NAIT的教材还是不甚了了,说出来好笑,他始终搞不明白堆栈的概念,后面的队列,树,堆,图,集合,排序,群,环,格和域逻辑,他就没有勇气读下去,NAIT的教材买回来放在书架上都积有一层灰了。这其实很正常,计算机学科是发展最快的领域,简直是日新月异,计算机软件教材大多是一线计算机技术人员编写的,这些技术人员没有受过教材编写专门训练,加上时间匆忙又是新技术,教材错误百出,把简单的东西复杂化了,别人读起来象天书一样难懂。 Kevin时有提到的素数,积偏序,格及补元等离散数学概念,老印更是一头雾水,只能顾左右而言它。一句话,老印写的程序完全没有结构的概念,他的程序别人读起来味如嚼醋,毫无美感,经常让人哭笑不得。深度优先搜索depth first search中的原路返回本质上就是堆栈树的先序遍历,老印连堆栈都没有搞清尚,深度优先搜索depth first search与广度优先搜索breadth first search二种遍历结合的项目自然做不下去。老印把原因归咎于他在NAIT的印度老乡,那印度老乡告诉老印:写程序容易得很,而且来钱快,模块都是现成的,象搭积木拼凑起来就成了。老乡在印度写了十年的程序,从没用过指针、队列、遍历、二叉树、堆栈树以及离散数学。所以,老印在《数据结构》这门课上没有花什么时间,Mike讲的东西他当然不明白。 Mike的到来让他明白了什么是程序,什么是真正的高手。Mike用一个网球筒子把网球一个个按次序放进去,又一个个按次序取出来,只花了10秒钟就让老印豁然开朗,明白了长期以来一直没有搞清楚的“堆栈”概念。还有一次,老印始终不明白“最小生成树“的概念,即是一副连通加权无向图中一棵权值最小的生成树。Mike用了个简单的比方让老印终身难忘,“简单点说,最小生成树就是在几个城市之间设计一个路线能走完所有城市,且路程最短”。复旦人的教学能力果然非同凡响,毕竟动作示范与比喻远比文字有效。 中国国内的程序员无知:他们认为白人程序员是最好的。看见的不等于是真实的,白人有作弊技术,他们知道如何瞒天过海骗中国人相信白人的水平比中国人高。白人在主场,又是游戏规则制定者,华人只是二等公民,在现实生活中,华人不得不伪装得比表面白人弱一些才能生存下去,所以,北美的大学、高科技,华人做的都是无名英雄的工作,露脸的事都是白人在干,国内那些无知的人才会自惭形秽:白人程序员是最厉害的。 老印很快发现Mike是块昆山片玉,绝对的编程高手,遂请Mike 帮忙找虫,Mike顺便就写了些code把程序中的漏洞补上,时间一长,老印就养成了依赖心理,最后干脆用visual studio做个界面糊弄Kevin,把所有工作交给Mike 去做,自己泡杯咖啡装模作样端坐在“无人值守性能测试机”前做甩手掌柜。倒不是老印有意想占Mike的便宜,代码太复杂,他又不会结构化程序设计,连最简单的堆栈, Stack概念都搞不清楚。老印面对如此复杂的系统,他也学Mike象个机器人样写了大量伪码,到下班时,他才发现自己都不知道自己在作什么。望着老印这个“史前动物“,Mike也觉得好笑,他有时好奇地猜,老印的程序连流程图都没有,那么复杂的股票系统,他知道自己在做什么吗?老印亲手写的Code时间长了连自己都看不懂,做项目确实是有心无力,没有Mike的效率,知识与经验,眼看着项目却做不下来。从此,老印对Mike 产生了依赖心理,什么都交给Mike这个工作狂去做。 Kevin做为Mike的顶头上司很了解公司为了生存的良苦用心,他也默许这种老员工欺负新雇员的行为。Kevin深深地知道错误发现越早成本越低,离bug越近的地方,程序恢复越容易,从源代码设计,单元测试 ,集成测试, 系统测试到维护阶段,source code设计阶段发现bug的成本最低,这时人员辅助越早介入越好。所以,尽量把错误压缩到萌芽阶段,最好在coding阶段发现Bug是公司节约成本与生存的秘密。公司硬性规定,单元测试unit testing与编码必须同时进行,所以,程序员必须身兼数职,Mike必须既是开发人员又是测试人员。小公司有小公司那一套冠冕堂皇的理由,一切都是为了节约成本让员工多干活。 读别人的code其实比自己写code要麻烦很多,你首先要彻底理解别人的逻辑关系图,成为别人肚子里的蛔虫才能顺着别人的思路写把程序写下去。老印利用其英语好的优势,写了很多断言assertation及伪码,对于程序本身只做了个界面敷衍经理Kevin,看上去工作已经完成,只需Mike把里面的瑕疵(bug)找出来就行了。这本质上是把别人未完成的逻辑思维写出程序来,这根本不是“捉虫”,而是重新做“蛔虫”。做别人肚子里的蛔虫是非常麻烦的一件事,北美的程序员大多宁可自己重新写code,也不愿意测试别人的程序。对于象Mike这样的快枪手来说,重新写程序比读懂別人的code花的时间要少得多。特别是公司要求一种在线处理算法提高软件收索分析效率,这种链表指针算法优点是快,但读Code的人很难读懂。 Mike最不愿意测试链表指针程序,测试数组就容易得多。恰恰公司安排Coding用链表,而不是用动态数组设计的程序。链表的优点是应变动态性强,速度快,不浪费内存空间,缺点是程序以反常识的结构指针, polynomial link办法写成,测试员难以读懂,调试困难。加上公司雇佣了大量业余程序员,这些业余程序员写程序从不加断言,他们不懂得事先做流程图的好处。程序短还好,程序大了,程序员写完code后,自己都忘了自己在干什么,何况测试员?因为公司要求网站加载时间不能超过三秒,一旦超过三秒就会流失用户。Amazon的记录是加载时间延长一秒,每年就会减少约15亿美元的营收。软件速度越快越好,公司程序员大量使用指针编程,这就苦了测试员。其实,链表只是一种数据结构,不一定只能在只有指针的C语言中实现,Java也可以有链表结构只不过是用数组形式来表达的。指针是C语言的优势,可以直接控制内存。Mike曾给老印建议别不懂装懂,多用没有指针的Java,C#自引用类,Python,或XML后台声明文档,这样就避免了晦涩难懂的链表结构,给自己减负,但被Kevin否决了,因为公司硬性规定用VC++,因为C++有delete功能来回收无用内存,C#,java虽然用现成析构内存垃圾回收功能,但资源占用多了点,象Mike这种高手程序员是不会这么做的。 Mike读着老印半通不通的代码,面对外行领导内行的窘境,他感到非常呃心,测试别人写的半通不通的程序对Mike来讲简直是一种折磨。Mike在上海接触的都是G同学那样的电脑高手,藏之名山,传之其人。在复旦,他是把程序当成艺术来做,把程序当成爱情散文来写。Mike到了加拿大才头一次见到这么恶心的程序,对方还是自己的chief programmer。Mike呃心了很久,极不平衡,却因为饭碗难以言表。Mike尽管心里瞧不起老印,为了饭碗,表面上还是对老员工唯唯诺诺,拍胸脯保证把Bug都抓出来。Mike程序写完后,他还要替老印做测试替身test double 替代远程数据库DOC depended on component实际用户界面,工作量相当大,而且老板好像还不知道自己一个人做了几个人的工作。为了保住饭碗,Mike只好忍气吞声。他确实喜欢写代码,甘之若饴。 老印虽然在NAIT学过《图论》的皮毛,那都是浅尝辄止,从没细嚼慢咽消化过,花了不少时间还是不会找“发现者”与“破坏者”。真正做起程序来,在老板的压力下,哪有功夫考虑树图的平衡,单旋,同构问题?那时还没有Java虚拟机或者C# common language runtime,老印内存管理常常忘记删除已分配的空间,造成系统出错,他一直不敢碰指针。搞得HR判断程序员优劣常常看他们写的程序是否用指针,用了指针就是高手,没有用指针就是Y货。现在年轻的程序员都使用没有指针的C#,年轻一代的程序员大都不知道指针的好处,就写程序而言,一代不如一代。 Bug free 只是合格程序员的基本要求,不是高手的充要条件。对于Mike来讲,判断一个程序员的水平很简单,给一个复杂多进程交替进行系统,内存管理或城市租车系统,如果用类似employee ID,那是小学生级别程序员。如果用时间做ID,如时间戳,time stamp,用面包店算法先来先服务,这是个入门级新手。时间ID的好处是唯一性,但系统需要维护时间全局变量及初始值,实现代价大。如果用时间优先算法服务,并用页码栈,并淘汰栈底页码,表明他会巧用堆栈技术,懂得服务效率,缺点是有饥饿问题存在,这算得上中级程序员。如果用循环队列并自动给每个进程分配相应数量的页帧 frame,懂得用电梯算法服务,那么这是个高级程序员。正是这种把程序员按等级贴标签的思想误导Mike抄袭了队列循环的黑客程序,一句话,”你相信什么?”才是最重要的。 Mike读着老印满是伪码的程序,阵阵反胃。逻辑错误与语法错误连篇,程序结构漏洞百出,到处都是小尾巴。他没想到老印连二叉树左小右大,图不考虑重边与自回路等入门常识都不知道。别人的时间就那么不值钱吗?Mike无语至极,甚至出离愤怒,这种小学生才写得出的程序,竟然可以做Chief Program,做IBM的经济项目合同。Mike 联想到一个久违的词,戆头(愚昧)。“要多用宏与函数,记得用类去封装底层函数,减少公用函数,一大堆重复语句白白浪费了大量宝贵的空间!”,Mike不得不给老印电邮指出什么是生成最小堆,什么是稠密图与稀疏图,图中的邻接矩阵指针数组表,table,只需一半的空间,应该选择点多边少的稀疏图。散列表4K加3时才可以用平方探测法,C语言的指针与Java数组指针是两回事等基础知识。Mike甚至感觉到自己成了大学老师,在教老印《数据结构》课程。电邮结尾他还一个劲儿提醒老印,别忘了destorytable释放内存空间,抄别人的Code不要用Copy加Paste,那样会把断言也一起抄进来,Kevin是内行,他一眼就能看穿。要不然干脆用.Net中C#托管堆装箱,垃圾收集器自动释放无用空间,但是装箱拆箱损失太大,垃圾收集器遍历整个内存开销也不小,C#也不支持多继承要用接口技术,说了你也不懂。 Mike相当聪明,他知道自己英语口语不好,老外经常把责任往他身上推,自己又讲不清楚。Mike一到加拿大就养成用电邮给自己留备份的习惯,电邮的好处就是发信收信有历史记录可以防止遗忘,email 有”见信如晤”的功能,有时间有细节,别人抵赖不了。把自己的经历写下来应该是人在生活不顺心时做出的本能,雅各能把約瑟小时候说的梦话,”太阳,月亮,11颗星向他下拜。”记在心里100多年,并让犹太人代代口传,由摩西写进《摩西五经》,流传至今,这就是日记力量强大的体现。 Mike的英语口语虽然不好,他写的英文却是少有语法错误,干净漂亮,复旦学生的英文听说能力一般,英文读写能力却是全国一流。 有一年公司把老印作为技术权威送到上海出差,当然,老印带到上海的Code全是Mike一手一脚写出来的,水平确实高。老印戴幅金丝眼镜,整个学者模样,老印那一副斯文读书人模样,看就是一个硅谷精英。伴随媒体轰炸,他在上海的学术交流竟然没有穿帮,中国的同行一致认为老印是个天才,印度的硅谷人才确实有很多地方值得国内的程序员学习。 Mike心急如焚,他曾用中国人的方式给Kevin写了封电邮,列举了他对老印能力的质疑,他在电邮里没有提老印的名字,用业余程序员代替,怕得罪老印,自己吃不了兜着走,毕竟老印是Chief Programmer。Mike是在用中国人际的思维理解加拿大的职场,他在电邮里写到: 1.业余程序员写程序有个通病,就是不懂编码二义性与数据结构,或者说写的程序数据没有结构,具体表现为使用大段语句重复与大量无效计算。业余程序员大都没有经过严格的专业训练,不会建造结构数组链表广义表,宏,类,子类,对象泛型委托与迭代函数来代替重复语句,不懂目录树分治的道理,而不得已采用“重复”这个笨办法。重复语句的问题就是难为测试人员,测试员必须花大量时间,才能发现是重复语句,从而产生大量无效劳动。原则上一个函数的代码不应超过百行,函数过大应该拆分。语句嵌套不应超过三层,类也不应过大,要多使用集基类分装公用代码。业余程序员的参数过多,应该把参数分装到对象中。 2.业余程序员不是不懂得解决问题方法的效率与算法的巧妙程度有关,而是经验与知识严重不够。业余程序员常常忽略表达式的条件,也不能发现每个条件的逻辑关系。First come first serve的周转时间不如短作业优先。业余程序员不懂”程序运行时内存重定位进行地址翻译,而不是加载时或编译时定”位的道理。业余程序员写代码只满足于满足功能需要,使用大量visual studio默认值。业余程序员类的耦合性太强,不懂牵一发动全身的道理,写的程序就像原子弹的链式反应。要么把所有的类设成public,要么把所有参数放在一个超大类里。 3.业余程序员只会费时费力笨的顺序查找,不会效率高的动态二分查找(log2)(N)+1,不会想到聪明的儿子兄弟,双亲二叉树方法,binary tree。业余程序员不懂同构判别,建造的树图中经常出现“同构”与“不平衡”现象,浪费大量空间与速度,本质上业余程序员不懂什么是”程序等于数据结构加算法,函数设计从粗到细,从上到下,避免函数跨层调用,面向对象,子类避免定义与父类同名的字段”等等。 4.业余程序员对变量,函数,类,包起名混乱,公司的代码竟然有用印度语、希腊语、西班牙语、日本假名起名的变量。除了原始开发者,别人要维护扩充程序根本没法望名知意,工作非常吃力。 新移民都是这样的,为了生计,八仙过海,各现神通。 Kevin收到电邮,他当然知道Mike说的是老印。Kevin把Mike叫到办公室,明确告诉他不要管别人的闲事,做好自己的事就够了。Mike知道老印写的Code根本入不了Kevin的法眼,才大着胆子写电邮告老印的恶状,原本想拍Kevin的马屁,没想到拍到马腿上了,自讨没趣。为了饭碗,Mike违心地接受了Kevin的劝告,他决定闭嘴,人在屋檐下,不得不低头。 平心而论,按中国人的标准,老印工作还是满敬业的,他的问题就是没有准备好而已。从中国人的角度,老印工作其实非常努力,他只是计算机专业知识准备不够。老印的一些做法让Mike感动得流泪,老印花了两个星期写”两个日期之间间隔天数,两个时间之间间隔小时数”,业余程序员不懂用类或宏去封装函数,一个看似简单的时间日期计算程序会写得相当复杂,工作量搞得非常大,而且容易死锁。Mike只用了一分钟就解决了日期时间计算问题,直接使用C语言中的日期时间组件库,让老印沮丧不已。 再比如,老印曾经为了解决程序死锁问题,整整花了一个月的时间。他只会用非常笨的银行家算法,不懂得“死锁忽略代价最小”的道理。老印甚至发明了一种延时回滚处理去解决死锁问题,他不知道解决死锁的程序非常冗长,不适合商业运作。根据”鸽子巢理论”,哈希表冲突问题不可避免,不管多高明的结构与算法都不可能彻底解决死锁问题。一般情况是程序员在操作系统中设置默认(default )状态降低死锁几率。在死锁发生概率不大的情况下,死锁忽略代价最小,电脑手机死机的最简单有效办法就是关机重启。 (四) Mike的优点就是他干活踏实,缺点就是不会装诚实。诚实的好处就是简单,诚实决不是愚昧而是智慧。诚实是需要伪装的才能在北美职场混得好,Mike 移民加拿大很久以后才知道公司里的白人对他没有好感,完全是因为他从没读过《圣经》。不懂得在老板面前装诚实,给白人第一印象不好。在复旦,你不会说谎活都活不下来,复旦人个个是人精,不会撒谎想出国门儿都没有。 在复旦,老师们一直教育他西方是个文明社会,人人都讲礼仪,原来哪里的人都一样自私,不讲道理。因为大白天在马路上无缘无故被白人多次骚扰,过分的时候Mike什么没有说,什么也没有做,白人也认定他有恶意,对他破口大骂。Mike开始产生卢刚那样的对白人社会的愤怒。他从不与白人打交道,总是敬而远之。在北美,一直有为了个人利益反华反俄势力。为了一己之私或蝇头小利,不惜挑起群族纷争,制造矛盾。中国人,俄国人,日本人,德国人在北美一直是防范对象,歧视在哪里都有,歧视中国也有。外国的月亮是圆的,这些负面的东西复旦是绝对不会告诉学生们的。那时Mike还年轻,还不明白任何种族里都有好人坏人,都有讲道理的人,也有不讲道理的人。 人类有个奇妙的能力,经过长时间祷告内心会变得非常干净。更奇妙的是干净的内心很容易获得别人的廉价信任。经常祷告的人嘴唇厚下颚发达,白人一看就是个祷告的人,印象就非常好。中国人从来就不祷告,长一副尖嘴猴腮,给白人第一印象就不好。很多中国人没有意识到这个,在北美吃了很多暗亏不知道。白人通常就是通过祷告获得信任后再作坏事,其隐蔽性比从不祷告的中国人要强得多。白人懂得反复祷告的好处,祷告的结果是内心非常干净,而且别人还能感觉到,每次祷告完毕自己头脑也清醒。白人都是祷告完,赢得别人信任后,就开始干坏事,干完坏事接着又祷告,把自己的内心洗得干干净净,一副无辜的模样,迷惑性非常大。那时Mike刚来加拿大,他还年轻,还不明白,好事与坏事是相对的,也是可以互相转换的。只是Mike运气不好碰到坏人多一些而已,其实任何宗教里都有好人坏人,不能因为一个人信仰基督教他就十全十美,不做坏事了。对于歧视与不公平,只能用爱心与忍耐去解决问题,这是Mike移民加拿大二十年后才琢磨出的心得。 Mike当然知道老印在占他的便宜,他也不是省油的灯,为了不让老印抢自己的功劳,他主动每天向Kevin汇报工作进度,来建立timely report 关系。Mike每天下班结束工作前,主动给Kevin写电邮,汇报一天的工作量,其隐含信息就是我Mike才是公司的老黄牛。一定要让Kevin认识到他在公司无可替代的重要性,才能保证其在公司的饭碗。Mike知道经常主动与Kevin交流,没话找话,迟早会有作用。Mike每次与老板的交流尽量给对方一些他从没注意到的有用的新信息,随时让所有的人都知道自己的工作,这样老印想抢功也抢不了。 Mike的工作哲学是亏要吃在明里,暗亏绝对不能吃。Mike为讨老板欢心挣表现可谓煞费苦心,他总结了一下就是”三看见”。一,吃一点小亏必须大家都要看得见,做一丁点儿工作最好有人能看见。二,工作量大一定要老板看得见。三,他对工作的拳拳之心老板必须要看见,最好天日可见,日月可昭。老板看不见的工作绝对不要花时间,精力要用在刀刃上,这才是快速成功的秘诀,毕竟人的时间精力是有限的。这是他在复旦读读书期间,长期观察教授们的工作方式得出的结论,当然,含蓄的Mike是不会把这些混社会的绝招轻易说出来的。Mike不愿做测试工作,因为测试工作老板看不见,这是最要命的。Mike内心极不情愿测试他人软件,就是因为软件测试纯粹是牺牲自己成就别人,老板看不见自己的努力,拼了老命累死累活把bug找出来只能证明别人的code写得好。自己累死累活,本质上还是为他人做嫁衣。这种吃力不讨好的傻事,精明的上海人是绝对不会干的。Mike从不认为这是市桧,这叫聪明。 而Kevin的策略micro-management则刚好是反过来的。就象约瑟夫·海勒《第22条军规》描写的一样,谁的活干得越多,Kevin越看不见,谁的Code要是写少了,他敏感得很。你今天写了200行语句,很好明天继续写200行语句,只许增加不许减少,结果搞得标准越来越高,大家都有苦说不出。半年后,Mike每天最少要写300行语句,才听不见Kevin的唠叨。Mike有段时间竟然形成了条件反射,只要看见Kevin苦口婆心找某人谈话,肯定是这家伙Code写得不够多。看到Kevin拿着本菜谱CookBook找人拉家常,如果程序没有写好,就没有饭吃。就是说,没有程序可写,就只能去餐馆混饭吃。Mike心有戚戚,在加拿大混生活好艰难。 在Mike面前,Kevin的策略是学中国人打太极,绝对不能让Mike知道老印每天最多只能写100行语句,以免Mike 怠工, 在工资上讨价还价,让他这个当经理的难堪。所以Kevin故意经常在Mike面前夸奖老印,把一些不是老印的工作也加上老印头上。他这么藏着掖着虽然滑稽,却让Mike觉得特不公平,Mike心里愤愤不平,Kevin在搞种族歧视,但他很快调整了心态,从不会因为不公平影响工作。没有人是傻子,他发现老印写不出合格的程序,老印在公司的日子也不好过。一切都是假象,公司如果没钞票可赚,大家都要做鸟兽散。 移民加拿大前,Mike就做过评估,自己除了写程序,能做的工作就是中餐馆了。Mike曾经短暂在广东人的餐馆做过帮厨,他非常勤快,最高纪录是他8小时用刀手工切过两吨肉。如果不是公司给了他程序员的工作,他可能一直会在中餐馆做下去。他天生喜欢工作,不管怎么样,Mike还是认为写程序强过做餐馆,能够在公司做测试员,有工作做,就有收入,这也是一种幸福。 Mike在中国是凭真功夫考上复旦的,没有头悬梁,锥刺骨长期勤奋的学习是不可能通过高考上复旦的。中国的高考也不是一无是处,最少它是个培养学生毅力的方式,高考的贡献在于给人类培养了大量优秀的基础知识扎实的脑力劳动者。Mike从不认为中国的考试制度是多余的,它至少在公平上是中国现实的最佳选择。衡量一个中国学生是否有真材实学其实很简单,除了相关知识,就是看他是否能够长期坚持艰苦刻苦学习工作,且工作业绩一直优秀。而Mike无论是在知识见识方面,还是在动手能力理解能力方面都是IT行业中的佼佼者。所以,公司高强度的码工劳动对Mike来讲并不痛苦,比起高考前长时间的海量习题,每天在公司创造300行语句对别人来讲很难,对Mike却是小菜一碟,他早就习惯长时间勤奋工作,并以苦为乐。 形式主义本是Mike在复旦混的优点,但却是他在北美工作的弱点,做面子功夫浪费了他大量的时间与精力,Mike过了很久才明白这一点。毕竟做面子功夫是复旦的特长,Mike最喜欢工作时忙得热火朝天被老板看见,他明白忙得满头大汗被老板偶然撞见是挣表现的最好机会,这可以给老板留下深刻的好印象。卡尔加里气候干燥,能喝杯咖啡真是一种享受。Mike最怕老印当着Kevin的面端杯咖啡找他聊天,要是给Kevin个印象自己也像老印一样,上班只喝咖啡不干活那就完蛋了。为了避免老板猜疑自己偷懒,和为了给老板留下认真勤劳的印象,Mike可谓用心良苦。他连咖啡这个词都避免提,实在躲不开他就用java代替咖啡,生怕同事把他的话录音,反正他的一部分工作是用跨平台的java写的。据传,Java这个词就是个爱喝Java咖啡的程序员带进IT行业的。 有段时间, Mike特敏感,只要看见谁端杯咖啡,他就站得远远的,生怕被连累,简直成了惊弓之鸟。他知道最容易碰到Kevin的地方就是两rooms,lunchroom与washroom,是人就会吃饭上厕所。Kevin怕程序员们不干活,常在这两个地方晃悠。所以,Mike上班前尽量少喝饮料或者只喝thirsty quencher的饮料,多吃肉,出门前只喝一小口浓咖啡提神,这样可以少上厕所而且中午不饿。这些混社会的窍门都是他在复旦打破头争先进学生过程中琢磨出的宝贵经验,Mike年轻轻轻就被复旦公派出国没有点绝招是来不了加拿大的。可惜加拿大职场是白人的天下,人种决定论一直占上风,不然Mike在公司还会再上层楼。 Mike做的是时薪工作,Kevin是个人精,程序员每天去了几次厕所,打了几个私人电话,读多少次个人邮件,上了多长时间网,他都清清楚楚。他只要打开公司的冰箱,扫一眼员工的lunch box,立马就能估算出程序员要花多长时间吃午饭。Kevin的绝招就是老三样:扣工资,放假与无薪加班。Kevin很少直接开除程序员,因为只要能够在公司连续工作三个月以上的人,都有些本事。一句话,Kevin是个精明的领导人,Mike在他面前做的面子功夫,经常白费力气。 Mike在加拿大一直得不到重用,他自己猜只有两个原因。一是来自中国大陆体制内的学者,二是他有高超的计算机技能,白人也有嫉妒心。当局一直扑风捉影他是黑客或间谍,所以总的来说,Mike在加拿大非常谨慎小心,为了不打扰别人,他夜班回家总是多走二十米避免邻居狗叫吵醒他人。房东那上大学的儿子没有结婚就把女朋友带回家过夜,深更半夜在他头顶上”嗨休”。加拿大的楼房楼层之间只隔一层木板,半夜听到楼上震天动地,Mike侧夜难眠。楼下的女房客是个神经过敏,三天两头跑上来纠缠不清,楼上太吵,她得不到休息。Mike有理说不清,他一天不说一句话,在家都是垫着脚尖走路。是他老婆孩子走路声音重了点,明明是环境嘈杂的红灯区,没有人守规矩,凭什么单欺负我们一家人?是他老婆孩子不服气,让Mike背了黑锅,当然他有教育责任。面对糟糕的环境,Mike从没抱怨过,只是默默地忍耐。 Mike无以恶小而为之,什么小错都不犯。如果白人不感冒你,任何芝麻大事情都可以拿来小题大做。对白人的浅薄与无知,他深有体会,举个例子,那年一个诺贝尔奖金获得者访问卡城,当地警察局收到二十多起炸弹恐吓。北美有个非常奇葩的现象,如果发生炸弹恐吓,多多少少与诺奖有关。一是因为诺奖和政治有千丝万缕的联系,二是因为炸药是诺贝尔发明的,一些人喜欢用炸弹恐吓来表达他们对诺奖获得者的一些政治观点或者科研成果不满。而且搞炸弹恐吓的人不少是高智商,有的甚至有获得诺奖的实力。Mike的一个白人同事异想天开,一口咬定Mike的电动自行车电池是炸弹,偷偷把Mike的电池电线剪断了好几次。Mike除了反复给他的白人同事解释那是自行车电池不是定时炸弹外,什么都没有做,凡事忍耐,白人把电线剪断后,大不了他又修好而已。我与诺贝尔无冤无仇,为什么要吃饱了没事干用炸药去炸他?新移民在加拿大混生活蛮难,难虽难,Mike常往好的地方去想,好的一面是移民生活的确培养了他的忍耐力,在苦难中自由快乐地生活。 (五) Mike经历新移民的窘境后,在加拿大的日子开始好过起来了。 Mike在公司的一切所作所为,Kevin净收眼底。兵来将挡,水来土屯。为了公司的利益与自己的地位,对于只做面子功夫的员工,Kevin有一整套管理办法。在公司股东眼里,公司雇员包括经理都是也只能是埋头苦干的骡子,不可能是其他角色,Kevin长期与雇主与雇员斗智斗勇深知这一点。Mike不是不愿意给他人做嫁妆吗?那好,让他去给技术上狗屁不懂的老印做测试员。Mike不愿意做什么,Kevin就让他做什么。他不是不愿意做测试员吗?那就让他天天去找别人的Bug,他不是愿意吃暗亏吗?就让他当无名英雄。Mike最后在公司脱翼而出靠的是真才实学,实干才是他真正的绝招。 Mike拿出他在复旦的绝招,做树形层次控制流图与control flow graph程序流程图,尽量使用测试框架开源工具cppunit提高效率,再根据业务流程图business based testing做百分之白边覆盖,他比老印清楚业务组合规则流程图里点覆盖并不意味边覆盖。试想在公司里就他一个人能做出逻辑清楚条理分明的流程图,老板也可以用他的流程图来做presentation 。客户大都是电脑土鳖,咋看到墙上贴满大字报般的二叉带权搜索Huffman树与条理清晰的流程图很容易就被蒙住,因为流程图简单一目了然,客户也原意接受。现在很多程序员不注意训练自己的流程图功夫,不会做面子功夫,在软件公司吃了不少暗亏还不知道吸取教训。在软件公司,流程图高手一般都会被老板挂目相看,这是IT行业秘而不宣的潜规则。 中国学生的优势在于基本功扎实,复旦的教育让Mike深信解决问题的效率取决于空间的利用效率。Mike写程序有很多别人没有的好习惯,非常符合数据结构原理,对程序大局掌握得恰到好处。比如,他喜欢用循环不是用递归,因为递归会占用大量空间,而循环占用的空间总是一定的,与工作量大小无关。他喜欢用SVD(奇异值分解),而不是用传统的高斯消元法来解方程。尽量多使用cpu计算指令少使用IO指令,多道程序交替执行,尽量用进程的概念去管理程序。Mike的程序都设计了PCB,并不仅仅修改寄存器PC,程序打包送往客户前,他都有附送远程激活自动下载更新程序,以防万一程序中有bugs,可以随时更换。在Mike眼里,程序分为主程序(只读),变量集(可写),函数库(同时载入),动态数组与栈(单向增长)。程序分段载入内存,而不是整个程序同时载入内存。因为基础扎实,Mike写的程序结构非常清晰,这是Mike写程序与众不同的地方。 Mike写程序的习惯非常好,也非常专业。他的程序都设计了统一函数接口,程序结尾从不会忘记释放程序开始声明的临时空间。控制全局变量的数目,合理利用内存。尽量使用宏函数,以避免象业余程序员那样笨得在循环中反复声明释放空间。Mike写的algorithm与宏几乎没有伪码,尽量使用二叉带权搜索Huffman树加堆遍历,因为他明白聪明的分而治之循环的在线处理算法是最合理的,选择Bug测试百分之百的判断覆盖能保证百分之百的语句覆盖。Mike写C语言程序喜欢用威力强大的指针的指针,对,是指针的指针,这是数据结构高手的编程特征,指针用于有序子列的归并排序非常有效。 在IT行业有个潜规则,就象土匪的暗语一样,对方问,”“天王盖地虎”,你必须答,“宝塔镇河妖”。如果程序员用递归数组,可能立马出局。如果程序员用指针链表,则被同行刮目相看。数组字符串不涉及指针但浪费空间,链表指针就没有这个问题。如果程序员会灵活运用指针的指针编程,一般会被其他资深程序员视为知己。试想大家都在用速度快效率高的链表指针,就你一个人用数组递归,所有的人不得不来将就你一个人的结构,大家恨死你,通常的结局只能是其他程序员联手把你踢出团队。当然潜规则不是绝对的,一切以公司是否能赚到钞票为标准。有时候递归数组也大量使用,如归纳证明tower of Hanoi 汉诺塔递归函数,这种情况下公司能盈利,大家只好放弃自己熟悉的编程技术,改用陌生的Coding。 大量使用指针是Mike在职场找回自信的秘诀,只要他在程序中使用指针的指针总能博得其他同行羡慕的目光,时间长了,他逐渐变得非常享受这种被人欣羡的感觉。在上海的IT行业,只要看到有人用指针的指针写程序,周围的程序员都会肃然起敬,这是行业内快速赢得他人尊敬的窍门。写这种大量使用指针的程序可以让他赢得称赞,赢得尊敬,感觉好极了,这是种被认可久违的感觉。毕竟在北美职场,大陆背景的亚裔做得再好也就是保住饭碗,仅此而已。 Mike知道他学计算机的动力完全来自自己的虚荣心,在上海,他迷上计算机的原因说出来好笑,完全是为了打电子游戏爱上电脑的,那时,年轻的Mike不喜欢动作游戏只喜欢智力游戏,他用civilization 来学英语,用“三国演义“来研究磁盘硬盘。他的很多软件技术都是无师自通。当时,DOS在中国还是新鲜玩意儿,他是计算机系第一个发现并使用PC Tool通过修改MS DOS文件属性的十六进制物理地址,把显性目录为隐性目录。这让他可以把大量游戏藏在系计算机里而不被发现,他为此暗自得意了很久。 Mike还是个汇编高手,在学校只有他能使用debug修改游戏存储数据打游戏过关,这让其他花重金通宵打关的同学羡慕不已。Mike通常是在其他前提一样的情况下对比fc存储文件的不同数据,两个存储文件只有金钱或血量不同,通过比较两个存储文件的数据差异,很容易找到所需的物理地址,再用debug修改游戏就可以通关。在游戏界能够在DOS环境通过修改游戏的物理地址通关是高级玩家的特征,绝对能得到别人的羡慕与尊敬。他非常享受这种尊敬的眼光,他知道他的虚荣心需要满足。说起来完全不可思议,这种虚荣心竟然是他十年如一日坚持研究计算机理论的动力。 他是计算机系第一个能用汇编改写引导扇区的学生,Mike曾在Linux 上设计操作系统,以便他能在32位机上使用十六位机游戏。Mike具备四位数的十六进制/十进制互换与两位数十六进制加减乘除心算能力,在Mike眼里文件目录程序都是十六进制的物理地址。一般的计算机本科生如果不打游戏,不做game buster ,应该不具备这个能力。《汇编语言》课程大纲也没有要求学生的十六进制加减乘除心算能力,连老师在课堂都给学生强调没有必要记,用计算器或查表就可以了。Mike具备十六进制乘除心算能力,他会背十六进制的九九乘法表(15*15乘法表)。全在他的背功好,肯花时间去记这些别人毫不关心的小事。Mike还有个心愿,就是把《没有准备好的学生》做成《G同学在加拿大历险记》手游,推销给全世界的大学生,让他们边娱乐边学习科研伦理,让全世界的科研人员少走弯路,少犯错误。 Mike还是计算机系里第一个可以更改BIOS的学生,毕竟那时BIOS都是厂商直接烧进电脑母板,连老师都普遍认为BIOS是不能更改的,但Mike有办法搞定。Mike逆向思维非常强,他天生就会把自己放在计算机硬件厂商的位置上换位思考,BIOS是可以用软件update的。在DOS时代,Mike 绝对是百分之百操作系统高手。正是因为Mike这种DOS高手的存在,才倒逼微软彻底放弃DOS转向视窗系统。视窗系统其实也难不住MIke这种人,他用Winhex等视窗工具一样可以访问硬盘的物理地址。这也迫使微软不停地升级视窗系统,在Mike这种人眼里,任何操作系统多使用几次,就很容易发现其瑕疵。 Mike的计算机能力对他在职场上站稳脚跟非常有用,Mike做得非常聪明,对于分支判定覆盖测试,他尽量所有原子条件与判断条件最少执行了一次取值,同时满足分支覆盖与语句覆盖,按80-20原则象用户那样测试Act like a customer,End User或者Use Case/Scenario才能把所有Bug排除。不能追求百分之百的覆盖率,不然工作量太大。要考虑测试质量,效益成本应兼顾。Mike写Code完全按用户需求Requirement来写,力求解决客户问题。做技术架构,树形层次管理流程图,特别是矩阵多重链表图,有很大迷惑性,既可以显示自己思路清晰,逻辑性强,理论水平高,又让老板看得见自己做了很多工作。 老印因为没有受过类似训练,而公司从没有告诉程序员们,项目需要很多《控制原理》方面的数学知识,一般的计算机本科生那点微积分知识根本看不懂结构图中的传递函数,也不明白并联,串联,反馈结构图等效变换准则,对于综合点引出点传递函数矩阵更是闻所未闻。老印私下议论公司没有给他足够的培训就让做股票系统分析全是阶跃输入时域分析,小公司也是有口难言。为了降低成本招了很多廉价程序员,却又派不上用场,白白浪费了时间金钱。 其实Mike也不懂《控制原理》,复旦的计算机博士与交大不同。复旦侧重理论研究而交大工程应用比较多。复旦学生写的Code就要中规中举些,符合数据结构原理。交大的学生写的程序就是天马行空,不拘一格,实用性强。计算机科学理论复旦博士比交大强,交大计算机动手能力与编程水平经验应该更丰富些。交大的计算机博士多多少少都有些《控制原理》方面的基础,因为《自动控制》是交大传统强项 ,复旦的计算机博士则不一定。不过在中国的一元化教育下,人都读到计算机博士了,复旦交大的痕迹并不明显。Mike文理双修长期与G同学等交大学生混在一起,对工程技术天生学得快却是个例外。Mike上班第一天就意识到公司需要控制方面的知识,他在开工第一周就把所需的知识准备好了。这是老印没有想到的,还一直腹诽公司没有给他足够培训。望着Mike做的条理清晰的儿子兄弟二叉树,老印心里埋怨公司,世界上只有犹太人与中国人有家谱,没有历史他怎么会做? Mike拿测试人员的工资却在做开发人员的工作,心理上多少还是有抵触情绪,工作进度当然就慢下来了。效率是软件公司的生命,结果,Mike因进度慢,被Kevin Stress Leave了半天。 那年夏天八月份卡尔加里还下了雪,这是Mike 在加拿大度过的第一个夏天,也是他头一次在夏天见到雪。落基山是石灰岩山,卡城的自来水是硬水,洗个手手会发干,洗个头头发会莫名其妙地毛糙,他望着自来水管上的铁锈,Mike 轻轻叹了口气。Mike望见窗外八月飞雪,室内空气中因干燥扬起的灰尘,想起每年夏天这时候他都光着膀子在五角场满头大汗吃着姆妈做的泡饭。Mike的眼圈不由自主红了,他想上海的家了,也开始反思移民加拿大这一步棋是否走对了。 的确,Stress Leave这事对Mike内心触动很大,资本主义无情残酷竞争给他留下很深印象,效率真是职场生命。从此,Mike再也没有怠过工。Mike曾小心地告诉Kevin 他在做开发人员的工作却拿测试员的工资,Kevin冷笑着回答:没人要你做开发,是你自己要做的。老印的断言写得很清楚,你只是在following up on 他的工作而已,你本质上还是在做测试工作。程序员多的是,你爱干不干。Mike非常聪明,他很快意识到如果现在的工作没有做好,下一份工作可能比现在还糟糕,加拿大的职场原来是要看历史纪录的。现在IT市场萧条,工作难找,Mike只好忍气吞声。 因为长期呆在复旦,Mike职场上的经验不丰富,但这并不妨碍他很快成为职场老油条。Mike从小就懂抓主要矛盾。在学校,他的主要时间用在功课上别的一概不管。所以在学校他一直是功课最好的学生,一俊遮百丑,Mike的学生时代日子过得相当舒服。在公司,他知道老板付薪水是要他多写好的程序赚钞票。所以Mike在公司的主要时间都用来写程序,同事之间很少来往,Mike朋友并不多。他知道只要把程序写好了,在公司会有更多自由。位置低有位置低的好处,公司那些破事与他无关,反正大材小用又不是他的责任。 Mike一次因故去了趟Kevin的办公室,喵了一眼公司工序进度表。他马上就看出工序流程是用“关键路径拓扑问题”思路安排的进度。“关键路径法”是基于数学计算的项目管理办法,一种有向无环图拓扑排序的动态规划法,非常有效,北美的工程师大都喜欢采用这种工序工期管理方法。Mike发现他自己总是被排在最关键路径上,几乎没有机动时间。他的工作几乎撑起公司的半壁江山,如果他的编程进度慢下来了公司其他程序员都要放假,看来他这个测试员在做CTO首席技术官的工作。Kevin还是知道自己的计算机水平的,Mike心里多少有些安慰。Mike拿测试员的低工资,做CTO的工作,他倒没有觉得委屈。Mike从没试过慢下来,他的大局意识还是有的,他没有觉得公司在占他的便宜,相反他非常高兴公司他的知识与经验公司可以用来赚钱。中国体制内出来的人就有这个优点,不计较个人得失,伊从来勿做一枪头额生意额,他看重的是与团队共进退。共产党的教育也不是一无是处,Mike从来不喜欢哗众取宠,在网上把共产党骂一通就解决问题了吗?他在加拿大不说共产党的坏话,其实是在捍卫加拿大言论自由的价值和利益。 从此,Mike知道每个模块的工期与权重,即每个模块开工时间,周期多长,他自己的模块需要的工期长度,机动时间在哪里。从那以后,全公司只有他一个人在没有supervisor 的情况下可以自己掌握进度,胸有成竹地按进度交code,从容不迫还有机动时间 。Mike虽是最低级别的软件测试员,却可以接触公司所有的技术机密,没有任何Supervisor监督他。很多时候,Mike都没有感觉到Kevin的存在,好像自己一直是在单打独斗。一句话,只要公司能扒分(赚钱),Mike上班做什么都行,也就是他什么都必须做。 Mike发现一个窍门,如果他一天不说话,他八小时可以做很多事。在上海他必须不停地用语言与周围的同事交流沟通,才能保证他在公司的人际关系和谐,非常累,一天下来什么事也干不了,光与同事学生讲话,打口水仗了。Mike在公司很少说话,一天到晚就是埋头写程序,,他是个高产的程序员。不说话就可以多做事,鱼与熊掌的关系而已。 公司给予MIke充分的自由,实际上,为了提高效率,加拿大的公司大都采用非常松散的管理制度,给予员工最大程度的自由,minimum supervision,据说这么做可以降低成本提高效率,可以省去不少行政费用。Mike每天都是自己给自己安排工作与作息时间,象个机器人写大量的code。对他而言,写程序其实是流水线作业,吃青春饭,体力劳动而已。老印把胃炎都写出来了就是每天百把十行语句外加一大堆bugs,有了老印这个参照物作比较,Mike知道只要每天写三百行语句就没有人会找自己的麻烦,程序员的饭碗算是暂时稳当了,因为全公司只有他能每天写300行语句。 这里讲的每天三百行语句从设计到测试必须都是原创,一个循环算一行语句,三百行语句不包括变量定义,初始化及函数引用行。三百行语句中最少五行要完成一个功能,全是指针链表结构,没有多余的小尾巴。而且每天都有变化,不能让人看出重复,所谓的copy加paste现成的源代码在Kevin那里是绝对不能接受的。Mike心里明白,公司总归是冰山难靠,Kevin很长时间没有找他的麻烦,完全是建立在他的海量code基础上的。如果哪一天他的code写少了,Mike绝对相信Kevin会像幽灵般及时出现找他拉家常,毫无根据地关心他的家庭、老婆与孩子。Mike也发现每天写海量程序的最大好处就是让其他程序员失去写Code的兴趣,Kevin就安排他们去做别的事情,自己在公司程序员的位置也安如泰山了,这个发现让Mike不禁得意洋洋起来。 Mike的经验让他测试过的程序总是Bug最少,效率最高,他在公司的位置也稳定下来了,老印的排挤让Mike轻松化解了。不仅如此,Mike拿测试员的工资在公司做的是CTO的工作,全公司只有他理解在大系统中实现小模块程序化,这个小模块最少应该通用并且易懂高效的概念。Mike依仗自己的技术优势, 在公司最得意的时候,甚至有一览众山小飘飘然的感觉。 (六) Mike不自觉地把大量上海的程序写作习惯也带到卡尔加里。在上海,他就是有名的快枪手,程序写得飞快,秘诀就是大段抄袭现成的源程序。Mike的计算机编程能力是靠使用各种各样盗版软件操练出来的,他抄程序一点心理负担都没有。Mike用过海量的盗版软件,全是最新软件的盗版。Mike完全没有任何内疚感,他只关心自己的编程能力是否在不断提高,自己是否在软件业见多识广,自己是否一流编程高手,盼望早日到北美做IT。Mike是高级抄家,他心安理得地抄。Mike安慰自己这是为了生存,一是源代码知识产权问题从来没有在IT行业提到桌面上,公司似乎从不关心抄袭问题。二是因为程序都是编译过了,技术上几乎不可能查出源代码是抄来的。要调查源代码知识产权需要高级软件人才,人工非常昂贵。三是抄袭源代码可以大幅提高工作效率,为公司赚得巨额利润,何乐不为? Mike主要是抄改结合,一般的程序根本入不了Mike的法眼,他大量抄袭经典《数据结构》程序,这些经典Code经过多年的千锤百炼,指针系统漂亮而清晰高效,只需稍加变化,很合Kevin这种内行老板的口味。Mike一般是抄写结合“标准模板”,只有傻子才一字不漏地完全抄别人的Code。如果逐字逐句地抄,老板用关键词到因特网上一搜就发现了,如果稍微改变一下变量名称或改变变量类型,语法算法都不变,老板不花时间不花功夫,就不易发现其中的作弊行为。这种做法速度快,工作量小,风险又低,何乐不为?为了讨好用户,公司软件采用短平快的新版本月发布制,象女人来月经一样准时,Mike哪有那么多时间写Code,不抄怎么办?真是逼上梁山。刚开始,Mike羞羞答答抄写结合小函数,小Component,发展到后来,取得公司信任后,干脆以文件为单位,整个File改个名字,把断言删除后原封不动地照抄,Mike曾美其名曰,这不是抄,是改写。 软件公司做法则简单粗暴,一旦发现有人抄袭,立马开除,员工就象破衣服一样想扔掉就可以扔掉。反正程序员满大街都是,想为公司打工的大有人在,不用担心招不到程序员。顾客只关心软件性能,谁会关心知识产权问题?公司上层明知下面程序员有抄袭作弊行为,大都睁一只眼闭一只眼。大家都是人不是机器,是人就会犯错误,谁没有犯错误的时候呢?抄经典C语言程序code其实法律上没有什么问题,既安全又没有知识产权问题还提高效率,何乐不为? Mike虽然曾经劝老印不要抄别人的Code,其实他自己就是一个大抄哥。Mike有段时间流程图作完了,哈西表也填完了,上班就用四个键,左键, ctl,c 与v写Code,连鼠标都不用,这四个键就够了,反正他的所需的Code都有现成的源代码可以抄。 Mike写的Code大都是从千锤百炼的经典C语言程序改写的,无论是结构,还是算法都无可挑剔,连Kevin这种内行都很难找到他的瑕疵。Mike在家里收藏了三百张DVD,里面全是各种语言写成的Code。他的卧室里放了八台笔记本电脑及五个台式计算机,全部用来写程序,装code。他从没有想过过量下载可能会伤害别人的商业利益,过量下载可能会有法律责任。十多年来,Mike从没停止过收集各种源代码,他家里的电脑光碟堆积如山。因为准备充分,Mike几乎所有犄角旮旯的功能都有现成的code可以抄,又快又好。如果有人怀疑他抄,Mike就叫对方自己去查Standard Library,反正C程序库里有的标准函数谁都可以用,没有知识产权问题。看着Visual Studio浩瀚的程序库,谁会自找没趣? 一山还有一山高,虚荣心必然导致过于自信,狂妄自大。 (七)山外有山,天外有天 强中更有强中手,能人背后有能人 自己看不出的code并不真的不存在。 任何事情都两面性,Mike虽然从用组件库尝到甜头,黑客程序却可能藏在现成的组件,这是Mike以前没有认识到的。 一天,Mike在公司服务器与集成调度中心从英特网浏览器镶戡程式中抄发现一段现成的程序,源代码是从Berkeley数据库通过SVN协议访问抄来的。Mike非常喜欢它威力强大的动态链表循环二叉树结构,有很多指针变量,但没有任何树“同构”。里面查找,删除,打印全是他喜爱的经典链表指针循环结构。每当Mike碰到喜欢的程序,他都会爱不释手习惯性地拷贝下来,带回家细心品味,认真背诵。真正的程序员会象背诵《唐诗三百首》一样背诵自己喜欢的程序,Mike不会背三百句算法也会背一百种Code,当自己动手写程序时自然下笔如有神。 这次也不例外,程序是典型的模块化结构化C++语言Code,可以根据需要随意拆解组合,语句优美简洁,用了大量的链表指针,特别是队列电梯隐藏在循环,在匿名借口对象注入的技术让他拍案叫绝,因为程序象有生命一样自动产生code。一句话,它具备Mike喜欢的程序的全部特征。美中不足让Mike有些疑惑的是该程序有些地方使用了非常原始的从循环到循环的数据流,看上去象小学生写的程序,第一印象这一段程序写得非常幼稚,仔细一看又觉得颇有深意。当时Mike理解为新技术就没有放在心上,按老规矩,先抄下来,拿回家再慢慢品味。 尽管程序有几个中位数的取法他不太苟同,链表接口与数据流循环看上去有些混乱,个人感觉那一段程序如果用递归函数宏展开可能更好些。程序只有优劣之分没有正确错误之分,没有瑕疵的程序毕竟是少数,也没有放之四海皆准的快速排序,不然就不需要《数据结构》这门课了。速度都是有前提条件的,递归需要不停地进栈弹出非常慢,而链表尽管难以读懂,但节省内存空间速度快。一句话,这是一段高效华丽值得收藏的程序。 Mike如获至宝,他用Git 在Linux上用email把程序传回家里,因为公司从来不会也不可能去查程序员的权限控制配置,Kevin对于手下程序员知识产权问题根本无法调查。Mike下班回到家,喜欢在家吃自己的狗粮(测试自己写的程序),用黑盒测试抄来的程序,用自己设计好的输入驱动模块driver与输出桩模块stub打桩模拟,抄来的非独立模块输入输出运行正常。没有发现任何问题。他用FTP从家里上传到公司的计算机上, 第二天再回到公司用Visual Studio编译出来,效果非常好。该程序使用大量指针循环,绝大多数加载都是不废时间的前端加载,设置不超过CPU的满载负荷,load,速度飞快。效率就是职场生命,它是Mike决定冒险使用这段抄来的程序的主要原因。Mike一开始就设计了自动下载模块接口,并从网上抄了个自动下载软件一起销售给客户,想到这些他心里就踏实了,反正可以事后诸葛亮,出了问题再打补丁。Mike的这些荒唐行为没有受到Kevin的怀疑,因为公司允许使用selenium软件测试自动化,grid hub远程harness IDE平台来调试脚本执行代码,白天工作,晚上由计算机自动测试。程序员白天黑夜连轴转,每天的工作时间无上限,跟高考一样紧张,谁会吃饱了没事干去关心知识产权问题? 在上海,程序员抄用现成的程序那是天经地义的事,反正最后都要用CPP翻译器完全编译一遍,没有人能看到源代码,谁会知道源代码是抄来的?当然,源代码也可以通过C语言或JAVA反汇编工具反编译灰盒窥豹看到,但那是极少数专家才有的本事。最终用户只看软件好不好用,其核心源代码的真伪并不重要。反正老板Kevin只关心数据信息是否正确地流入流出,Test oracle 预期输出是否正常,从不关心内部数据的形式是否合理,模块之间相互关系是否能保持完整,数据边界是否正确工作等单元内部与外部问题。最后,Mike借口全组合测试不现实,用t-wise combinatorial testing 抽样测试把自己用抄袭的事掩盖过去了。对于Kevin问的一些无知函数,Mike就指着开头的#include <stdlib.h>推诿这些函数都是从standard library 来的,保证没有知识产权问题。Mike给Kevin演示了一下程序的adaptive random test,ART效果不错,没有出现Bug。负载,压力,稳定性及性能测试performance testing ,auto scaling程序看上去也很好,Kevin当时就迷迷糊糊地同意发布了。在公司,程序员只要能跟老板交差,怎么做都行。 Kevin发现Mike工作进度特别快,他在卡尔加里的IT行业摸爬滚打十余年,什么样的程式员他没有见过?Kevin猜到Mike可能抄袭了现成的程式,不然他的工作进度不会那么快。 Kevin曾是Waterloo电脑系高材生,他深谙在IT行业的生存之道。那就是绝不能让别人拿住自己的错误把柄。他知道Mike用的是大棒模式big bang integration 集成模式测试软体,这种方式当然不好,但效率高。而且他也不可能去查程序员的权限控制配置,从服务器上查看下载的蛛丝马迹等。他知道Mike写程序不太干净,尽管Mike很会掩饰,一般的程序员都看不出其中斧凿的痕迹,不相信上帝的人那有不撒谎的?Kevin打内心对中国大陆来的技术人员不信任,一直找茬把中国人打发走。但Mike是属于那种出活的技术员工,而且是不可随便替代的稀缺技术力量。公司在用人之际,如果因为一点小错误就把自己的程序员开了,谁来干活呢?再到社会上招一个程序员替代Mike,不见得会比复旦计算机博士更好,耽搁了工期,顾客不付钱怎么办?找Mike的毛病就是与自己过不去,但不搞清楚程序的庐山真面目,自己又放心不下 。 Kevin做事非常有策略,别给自己找麻烦,否则公司总经理知道了,被开可能是自己,而不是手下的技术骨干Mike。Kevin知道要论计算机编程能力Mike绝对在自己之上,复旦计算机博士是那么好拿的吗?Mike写的程序太复杂,接口多耦合性高,单元测试其实别的程序员也没办法做,回归测试也是耗时间的工作,公司负担不起人工费。自己根本没有时间进行源代码白盒测试,让其他程序员百忙之中抽点时间做黑盒测试或用CPPunit进行白盒框架测试,短时间内估计也看不出端倪。Kevin能做的只能是黑盒测试一下Mike的程序功能是否合乎用户需求,别的他既没有时间,又没有精力,甚至连知识储备都不够,最好让Mike自己说出来。 Kevin在工休时间Breaktime严肃地找Mike私聊了一下,他问了Mike几个问题。你单元测试是Mock 仿制?fake伪造?还是用未使用占位符对象的Dummy哑元?test double用的什么mock工具?powermock还是easy mock? 这样就把Mike这个程序员放在测试员的位置上质疑,可以打击对方的自尊心,并降低自己的风险。要是Mike拿着自己的海量Code到总经理那里反咬自己一口,走路的可能是自己,总经理是个只看结果,不看过程的人。Kevin转弯抹角问这么多,就是要打击Mike的自信心,让他自己主动坦白哪些Code是抄的,哪些是个人写的。 Mike开始一口咬定是FTP被黑客绑架了,后见抵赖不过,承认他抄了一段在网上下载的程序,效率非常高,但工作进度时间紧迫,不如先用这段抄来的程序,以后再打补丁。Kevin对Mike的作弊行为非常愤怒,表示要向上面汇报处分Mike。Mike也是个职场滑头,当时他这样劝Kevin听他一回。其实微软一直都是这样做的,从视窗95到8.0,用户刚买的时候,视窗在计算机上运行得飞快,第一印象非常好,退货期一过,视窗就开始自动打补丁,因为安全问题凸显不得不打,接下来就是恶性循环,补丁越打越多,系统越来越慢,最后干脆淘汰旧的视窗版本,扔掉计算机,再买新的视窗版本与新计算机。听了Mike的陈述,Kevin不置可否,给自己一个台阶下,把Mike开除了,谁来做公司的合同?Kevin决定对Mike的抄袭行为暂时保持沉默,他没有把这个作弊事件报告上去,也没有记下来,反正公司允许事后诸葛亮,打补丁解决问题。 Mike没有想到的是他抄袭了黑客放在网上的镶歁对象模块化设计的木马程序。以功能块为对象单位实现逐步求精的求解算法程序的编写不是开始就逐条录入计算机语句和指令,而是用主程序、子程序、子过程等框架把软件的流程描述出来,并定义和调试好各个框架之间的输入、输出链接关系。对象模块化设计使黑客很容易通过功能块的输入、输出端来实现自己的意图,小的如在网站上链接小广告,增加点击率,盗取别人电子邮件密码,QQ微信密码,大到直接盗取别人银行密码,信用卡信息,随心所欲地从银行转账等,这时再打补丁就太晚了。 (八) 果然,公司的软件送到用户手中,刚开始获得好评,Kevin给Mike加了工资。因为是IBM的合同,很快有专业客服反映,他们发现了个快捷健ctrl+X+Y+Z 可以让密码失效。Kevin闻之大惊失色,因为外包合同书并没有要求设置快捷键,而Mike从没向他提及过快捷键的事体。Kevin仔细查看了Mike写的源代码,有在卡尔加里混了十多年的IT经验,他知道这是典型的模块化黑客程序,从逻辑上看没有任何问题,从算法上也看不出任何附加快捷键的语句,安全漏洞却是类似摩尔斯密码写在C语言程式逻辑上面,数据流通过循环表达出来的,如果在源代码上更改循环,整个程式就会瘫痪。Kevin大发雷霆,马上把Mike找来,要求他给个说法。 Kevin在小组技术会议上请Mike做个schematic 流程图Presentation给大家介绍一下他的新技术。Mike其实也没有真正看懂自己抄来的木马程序,因为每个循环程序后都有说明与断言,打印循环,查找循环,排序循环等,一目了然。他没有想到的是黑客程序也是结构化模块化组件化的,快捷键等黑客功能是通过众多循环来实现的,这是Mike所不知道的。很正常,用链表指针队列写的程序如果没有断言的确很难读懂,实际上这是黑客利用开源代码的惯用招术,把模块化黑客程序放进无知识产权的开源代码库,利用程序员喜欢追求新奇技术的好奇心理,让程序员自觉自愿把黑客程序抄进商业程序内,毕竟模仿能力是每个人的与生俱来,把别人的程序重抄一遍,是学习他人长处的有效手段。模块结构化黑客程序隐蔽性非常强。黑客程序只抄一段问题还不大,如果把几段模块组合起来黑客功能就出来了。黑客程序首先要好用兼容性好,容易编译,最好跨平台并功能强大,别人才愿意抄。其次黑客程序必须模块化,这样隐蔽性强,看上去与普通源程序没有区别。 Mike当初只读了附在程式后的说明,按照cookbook使用说明用C++翻译器编译一遍就与自己的功能模块联上了,并且效果非常好,从没出过Bug。从程式字里行间,Mike虽只看懂了个大概,但身为复旦计算机博士的他确实从逻辑循环算法上看不出任何问题,在断言assertion 中也看不出任何端倪,经过内部调试一段时间就交货了,因为时间紧迫,也不可能把test fixture里的cases 按suite一个一个拆开来仔细看 。Mike虽然在上海玩过黑客程式设计,在实验室偷懒骗导师设计“老板键”,但那纯粹是年轻好玩。而且他过去都是直接把快捷键或其他黑客程写在源代码里,用基数排序,多关键字次位优先排序,打开源代码输入关键词,一搜就找到了,容易得很。 Mike为了找出原因,他只好从程序主入口main函数,图定义typedef struct,静态字段,开始仔细查看源代码,从搭建程序框架开始检查。首先,变量必须先定义再使用,否则C++语言编译不会通过,快捷键只能是通过赋值全局变量void邻接表来实现的,即,快捷键可以巧妙利用全局变量或全局数组赋值二义性来实现。但全局变量在整个系统中就那么三四个,一目了然,跟快捷键根本没有任何关系。程序是用对象一对多,而非多对多的聪明的方式来组织的,Mike 从信息交换中心开始检查。 散列表也必须经过初始化才能构造哈希函数,但散列表的初始化也检查不出二义性。Mike看来看去散列表也不具备密钥矩阵的特征,他甚至考虑自己给视窗写个驱动程序来找出症结或病毒特征值标志,因为恶意代码必然占有一定内存空间,至少部分功能代码驻留在内存中,或者恶意代码以加密的方式存在文件中,仅在内存中被激活?对象之间的委托关系delegate与lambda表达式非常清晰,左看右看也看不出委托关系二义性。 他开始怀疑是visual studio或者视窗惹的祸,Mike把软件搬到他自己一手一脚逐行逐句设计出来的操作系统,这是一种基于linux的,兼容POSIX标准的操作系统,在该系统上只有他自己可以改动引导扇区bootsect.s,setup.s,head.s。这个操作系统干净得很,连鼠标都没有,主要就是汇编机器指令,加一点普通C代码和一些兼容UNIX的POSIX标准类fork , execl的重要函数以便system Call,linux kernel source tree一目了然,操作系统绝对安全。Mike发现就是在Linux上,快捷健还是存在,这让Mike非常沮丧,他有强烈的挫折感 ,frustrated。 运行时逻辑地址在PCB基址上重定义,数据段与代码段的ldt表与gdt表一清二楚。因为Intel说过系统调用system call,处理器硬件处理把内存隔成用户态与内核态,Intel的CPU不能随意调用户态的变量,在CPU上内核态与用户态之间的变量二义性问题完全应该忽略,莫非是Intel在CPU硬件上作了手脚?用jmp.cs的最低两位来表示0 是内核态,3 是用户态。CPL与DPL 检测,用中断指令int 0x80进入内核态是唯一的路径。用宏展开内锲汇编来展开进行系统调用,int中断要查IDT表,设置gate,返回值压栈system call相应系统调用处理函数入口,Mike打开Linux操作系统汇编,内核数据与用户数据之间的关系一清二楚。他到函数调用表里去查,用户态cpl3 dpl0调用中断dpl3 cpl0进入内核态,多进程多任务,fork 管理CPU进程,内存是由地址*p=7管理等,一点问题都没有。对于在调度中的共享数据语义错误,加空循环的办法不可行,只能在临界区上锁进行原子操作。 现在大学《软件安全》课程主要还是DOS那一套,只是介绍性的泛泛而谈,没有太多实质性内容。计算机本科生对于微软视窗的理解仅仅是从微软的宣传资料中得到的,此外并无其他可靠来源。老师只是把微软的那一套公开的资料拿到课堂照本宣科而已。微软一直给用户强调,视窗的两个虚拟内存空间,用户模式与内核模式是完全独立的。内核模式的权限虽然非常大,但虚拟用户内存空间是绝对相互独立,不可以跨进程去访问别的程序的内存,这在理论上是行得通的。Windows默认使用二级页表把虚拟地址变成物理地址,即页目,页表与字节索引。内核内存虽是所有进程共享。如果应用程序直接访问该内存空间内的地址将会发生地址访问违规,需要重新编写驱动程序才能访问内核内存。孔子振聋发聩早就说了,“学而不思则罔,思而不学则殆”。计算机专业人士从来不会去怀疑微软,谷歌的承诺,老师们的谆谆教导让计算机科班学生思想僵化,他们对微软,谷歌的说辞深信不疑,微软,谷歌怎么说,老师们就在课堂上怎么灌输。但大家都忽略了一个基本事实,微软,谷歌是私人公司,不是国营企业。自己的利益是第一位的,客户的利益是其次考虑的。 Mike兴趣广泛,他是没有时间,如果象文化大革命那样把他关进牛棚,Mike又是一个陈景润。他喜欢研究数学,特别是《数论》,《数论》是数学皇冠上的明珠,不仅可以用于密码领域,还有纯数学的美学价值。《数论》研究成本比写程序还低,写程序只需一台电脑,而研究《数论》连电脑都可以不要,只需时间与脑力而已。 软件接口是用Java写的,莫非是接口的问题?Mike自然先到类别(Class)里去找,从公司创建代理服务器8086端口开始纠错。Mike在复旦的博士论文是大型数据库管理,他的特长是把后台数据在不同结构的系统间转换,还不影响现有功能,即异构数据库管理。 尽管Mike并不擅长密码学计算机安全领域的研究,但他还是一眼看出,公司用的是RSA公钥密码算法。常见的公钥加密算法就那么几种,RSA、ElGamal、背包、Rabin等,这些常见的加密解密算法还难不倒Mike。RSA中p,q只能是素数且必须保密,RSA解明文时会出现大数冥,容易造成计算机溢出。Mike在上海玩过RSA签名,那时复旦的工作站都会溢出,大冥整数处理只能用特殊的工具软件才能算出极大整数,所以他碰到RSA一般都避开走,不想惹麻烦。Mike看到大冥数就头痛,又不是在找《数论》里的梅深素数,要那么大的冥干什么?可这次是逃不掉了,Mike在家通宵达旦地查文献,不停地用辗转相除法求最大公因数再求最小公倍数再求二元一次不定方程的通解与同余方程来分析超递增序列背包密文。Euclid算法,带余除法,辗转相除模,欧拉定律,费马小定律,椭圆曲线weietstrass密钥,同余方程,无穷多素数定律,孙子定律,物不知数定律......上帝啊,到底是哪里出了问题? Mike哪里知道,世界上还有黑客通过逻辑循环来实现快捷键的技术。Mike抄袭的是只在军事上使用过的黑客高级编程技术,功能是过众多普通或变型迭代法循环并用摩尔斯密码方式表达出来的,通过结构体的重新定义产生的。逐字逐句来读源代码根本看不出任何问题,源代码库repository 也没有瑕疵,就是把源代码完全恢复并搭建成更直观的程序框架流程图也看不出Bug来。程序运行完毕,指针却没有释放完,抄袭者还以为是外部模块接口,没想到让黑客钻了空子。黑客利用指针数组二义性,偷换指针变量概念。牵一发动全身,如果把指针变量去掉或改变结构,整个程序会完全瘫痪,几个月的工作全部浪费。改程序的工作量远大于重新写程序,况且程序已经送到用户手里。生米煮成熟饭,不可能收回。当时Mike是一头雾水,程序使用了大量反阅读常识的链表,读上去简洁精干,没有任何问题才抄进公司的商业程式,难道快捷键是从天上掉下来?他这才开始感叹山外有山,天外有天,北美的IT行业深不可测。 其实最早的程序设计都是通过众多的循环迭代实现的,比如找个小学生来写程序,他肯定只会从循环到循环,而不会从整体上进行模块化功能化。只不过这种嵌套循环的初级编程方式容易出错,还不容易找到Bug错误,数据流就象乱麻相互交织缠绕在一起,只有高智商的程序员才不会晕头转向,它当然不如模块化程序设计一目了然简单明了,容易OEM,编程效率高。IT学术界工业界早有结论,这种靠循环的编程方式应该摒弃。但这种编程方式写的Code一旦调试成功威力巨大,其最大优点是别人无法复制抄袭窜改,象癌症一样附在软件上,杀毒软件是一点办法没有,而打补丁实质上就是加个杀毒软件来修补软体的缺陷。 其实,多进程的组织用的是最简单的PCB, 队列,状态,各个进程都有映射表限制进程间的变量二义性。文件本质上就是一段队列字符串流,多进程中的用户级线程之间切换本质上就是循环到循环,因为线程之间的切换必须在不同栈之间切换,不能两个线程用同一个栈。必须用全局变量TCB,因为线程之间的切换本身就是从循环到循环,只不过多了个压栈弹出的过程。黑客功能就是这样巧妙地隐藏在循环之中的。 CPU的控制其实非常简单,就是调用中断函数与一些重要函数的过程。内核级线程kernel threads,TCB管理关联内核栈。通过TCB找到内核栈指针。然后通过re切到内核程序,最后用cs:pc切到用户程序,即所谓内核程序切换五段论。所以,用从循环到循环方式写Code的人不是小学生,就是电脑高手。稍微有点常识的程序员都不会写从循环到循环的语句,因为老师在课堂上反复强调灌输,程序要结构化,模块化,绝不能搞从循环到循环的恶性循环,死循环。 Mike在复旦从没接触过这种原始的编程技术,咋碰上,自然是一头雾水。这一点都不奇怪,就写程序而言,计算机专业其实优势不大。一方面,电脑编程门槛太低,数学逻辑几十年没有大的突破,小学生懂点数学逻辑都可以写Code。另一方面,计算机专业背景学生受的理论教育太多,染了不少学术界的酸腐气,写的Code虽中规中矩,在规范性标准性方面做足了面子功夫,但缺少了最重要的灵气,其程式质量可能远不如一些半路出家的天才程序员编的程序来得天马行空,洋洋洒洒,潇洒自如。半路出家的程序员写程式大多是出于天才兴趣,而电脑专业的学生写Code是为了养家糊口,说白了“码工”,“码农”而已,两者写出来的程式质量自然不可同日而语。其实电脑程序设计就象数学那样对于人的逻辑思维培养非常重要 ,从这一角度,程序设计应该象语文数学那样设置在小学课程中。 Mike从此不敢用FTP了, 在家里加班写的软件一般用Flash Drive 再带到公司,也不随便抄袭别人的源代码,因为不安全怕黑客做手脚。有段时间, Mike特敏感,特迷信,简直是八公山上,草木皆兵,整天神经兮兮,疑神疑鬼,任谁也不能碰他的电脑与硬碟,感觉谁都是黑客要破坏他的程序。那段时间,Mike的挫折感非常强烈,他甚至考虑离开IT行业,改行去做会计。 计算机科学不同于其他学科,对于数学物理你是在学真理,真理是永恒不变的,有了基础知识就可以举一反三,一通百通。“计算机其实不是科学“这句话指的是计算机组织结构标准一直在变化,计算机学科是由不同的公司发展出来的,各有各的标准。微软,IBM,苹果,谷歌,Borland各有各的的计算机数据组织结构与标准,每个公司计算机系统自举,磁盘中断,文件管理,目录解析等完全不同。计算机硬件速度日新月异,飞速发展,而软件则必须跟着硬件速度发展,不同位数的计算机其数据结构设计可能是完全不同。所以,计算机专业人士必须不停地学习各种不同的数据结构及其标准,尽管数学逻辑的基础知识都是一样的。从公司的角度,公司也有难言苦衷,计算机行业标准一直是远远落后于市场需要。为了扒分,公司只好先设计定义自己的标准,你不能让市场去等你。 实际上,学计算机就是在学别人随心所欲一直在变的标准。做计算机时间长了,都没有什么成就感,要不停地被动地学习别人制定的毫无道理的行业标准,一直被大公司不合理的标准牵着鼻子走,特累。比如视窗中的FAT表本质上就是磁盘数据文件索引和定位的一种单向链表,这是微软定义的,技术上没有什么大不了,你要想在视窗虚拟机上用你的程序,就必须照顾微软的习惯,不然迟早会出点什么纰漏。所以,公司硬性规定,文件系统必须采用用单向链表结构,紧跟微软的指挥棒。写程序跟着微软走绝对没有错,在这方面公司是有血的教训。公司规定必须用微软的MS FORTRAN与MS C,因为公司有深刻教训,用Borland C++兼容性太差,非出问题不可。公司一再强调必须紧跟微软的习惯,这时程序员也没有多少选择,很无奈。比如写外语翻译软件,用顺序结构效率最高,但为了与视窗兼容,公司硬规定必须用索引链表, 白白浪费大量效率。时间长了Mike 都形成条件反射,一切以微软为标准肯定没错 。实际上,在视窗平台上,程序员不可能有太多选择。 现有的计算机技术会被逐渐淘汰,比如花四年时间掌握C语言指针技术。但C#的推出就不需要指针,因为用简单的数组就足够了。Mike在复旦花在指针编程上的海量时间华屋山丘,白白浪费了,在职场上田忌赛马,不得不用自己英语不好的短处去比NAIT专科生的长处,海量的宝贵时间就浪费了还有苦说不出。 实际上,程序员花了很多时间学的只是随时在变化的标准。如果一些标准公司没有对外公布,却被黑客知道了,操作系统本质上就成了一段黑客程序,这时程序员对操作系统黑客就无能为力了。象视窗,ios,安卓等操作系统经数量庞大的软件工程师之手设计出来的,很难保证操作系统中的内部标准不会被泄漏出来。因为操作系统本身就有很多功能可以通过普通的指针链表进行控制,黑客只需利用变量的二义性就可以悄悄地把黑客功能隐藏在普通的语句中。大学计算机系《软件测试》课程几乎不讲如何测试指针变量二义性,计算机本科生只会做点测试边测试。指针二义性测试闻所未闻,因为工作量大实在麻烦,这给黑客作案提供了客观条件。 现在的大学《软件测试》教材很多内容本质上还是DOS程序设计软件测试那一套,DOS的好处在于单线程程序简单好讲,变量二义性问题不明显,所以,大学《软件测试》课程从来不谈变量指针二义性测试。测试员很少去检查指针变量二义性,无用的内存指针是否释放完等。但在视窗,安卓的多任务多线程系统里,变量二义性问题就凸现了,文本copy paste本质上就是个用户级进程之间的调用,视窗的很多功能都是用类似amazon的关键字遍历写成的,长期在内存里以激活状态存在,又快又好。Android系统中的intent关键字在activities之间传递信息等,这些关键字都是按标准定义的,很容易被黑客知晓。当然大多数情况下,程序员开发的开源代码是没有黑客功能的,黑客功能多是被程序员无意识写进程序里的bugs,只是被黑客钻了空子,恶意开发挖掘出来了而已。加上IT行业工作极不稳定,鱼龙混珠,程序员为了自己在公司的位置与将来的工作,在程序里加些后门是普遍现象。有些后门可能连公司主管也不一定知道,但后门一旦有,就很容易被无孔不入的黑客知晓。黑客有黑客的那一套逻辑与办法,如果程序员本人就是个黑客,这时整个程序就完全失控了。 公司为了自己的利益也不可能完全对外公布所有标准,公司的商业秘密当然需要保护。何况黑客是无空不入,没有道德底线的,特别是当黑客了解程序员的写作嗜好与习惯时就会乘虚而入,所以在资本主义社会,完全开放的操作系统是不现实的,毕竟公司为了自己的利益必须保护自己的商业秘密。 Mike在专业上有很多先见之明,在北美很多电脑专业的本地大学生毕业都选择硬件而不是软件。因为硬件在国外比北美要昂贵不少,外国学生一般都没有机会接触最先进的硬件,北美本地大学生近水楼台,见多识广,做硬件比外国学生事半功倍。北美软件业的主力军到现在都是靠外国人来支持的,外国学生学计算机可以用盗版软件,硬件就没有盗版软件那样成本低。利用硬件原子指令软硬件协同设计看上去是更好的选择,至少比面包店的纯软件效率更高,但受硬件控制适用范围窄,受多CPU限制,硬件软件化不受多CPU限制。Mike主攻软件的思路到现在为止看上去是对的,因为云计算开启了软件定义网络,即网络硬件软件化。实现硬件虚拟化,如虚拟路由器。这样用户终端就不需要硬件了。硬件越来越简化,小终端或零终端是趋势,计算全在云里实现。这一思路对国际学生有利,对本地学生不利。计算机公司搞标准化在云计算里就是给自己挖坑,因为标准化意味着特权化,搞自己的标准只会让市场恶性竞争。 计算机大学毕业生都是一个模子培养出来的,全世界的程序员写程序的习惯都大同小异,全是通过学习IBM,微软,Borland的数据结构培养出来的。特别是十年前,微软的程序员证书风靡全世界,人人都在用VC++写程序。时光荏苒,现在随着Linux,iPhone与Android系统的风靡,微软有点大江东去的感觉,没有以前那样抢眼了。 全世界的程序员都是用英语写程序,用日文,俄文,中文写源程序那已经是三十年前的事情了。黑客闭着眼睛都能猜出来程序员是如何实现某个功能的。业余程序员都喜欢用visual studio的默认值,定义i,j为整数,x为函数自变量,const, K 为常数,null 为空。词频统计肯定调用C的getword函数,排序用qsort函数,电话狂人散列表输出肯定用ScanAndOutput函数,哈希表散列表初始化用HashTable,通过位移映射获得相应地址等等。这时黑客也可以轻松猜到在你的系统里i为整数,null为空。在文件占用镞的对应镞号填下一个镞的镞号,镞链表,结束标记为FFFFFF0F。55 AA为硬盘主引导扇区结束标志。这些都给黑客提供无限想象空间,黑客不需要专门定义全局变量,就可以利用变量二义性控制计算机。 (九)山回路转 Mike找机会咨询了G同学,G同学一针见血地指出,黑客程序本质上是幅多对多的图,只要查看一下指针释放内存空间,就马上知道了,并不是所有的指针用完后都释放了,快捷键等黑客功能快是通过众多迭代法表达的,即用最简单的线形时间复杂度最大堆Maxheap把间隔的字符按等差数列抽出来组成一个小数据库放在内存堆栈里来实现的,对象序列化后XML或Json字符串内存流反序列化时可以变成具有黑客功能的对象,对象本质上就是一个黑盒,XML可以象钥匙那样把对象中的黑客功能打开,从而控制计算机。G同学的洞见让Mike幡然悔悟他上了黑客的当。黑客利用了Mike这种程序员喜欢循环指针的弱点,不疑有他,贪小便宜吃大亏。毕竟程序有多态”变色龙”特征,即同样的代码在不同环境有不同的作用。G同学并不反对使用安全的没有知识产权纠纷的开放性的源代码,G同学只是反对软件编程中作弊行为,因为直接使用别人的工作会让自己编程工作更富有效率,使用与购买现成的CSM源代码在北美IT行业是司空见惯的做法。 不懂装懂,说谎作弊则害人害己。 为了保住饭碗,Mike在Kevin主持的小组技术务虚会议上只好当众把自己的工作品头论足褒扬一番,推诿自己为了提高效率设置了快捷键。Mike以技术权威的口吻安慰大家,给Kevin吹风,问题不大,大不了给客户打补丁。Mike程序写得飞快,大家有目共睹。Mike故意回避他无法更改或删除快捷键,只是强调找快捷键就象大海捞针一样难,普通用户根本不可能找到。IBM的专业客服发现快捷键漏洞只是运气好而已,况且设置快捷键是计算机商家惯用伎俩,此乃行业潜规则,没有必要大惊小怪。复旦的特长就是口如悬河,可以找各种理由把程序说得一钱不值,也可以把一个程序捧上天。做思想工作是复旦的特长,Mike一番高谈阔论,就在大家将信将疑中把此事暂时支吾过去了。 Kevin听了还是不置可否,决定继续保持沉默,反正以后出了问题,公司还可以打补丁,大不了发布软件新版本把Mike的工作推倒重来。Kevin并没有发现Bug是隐藏在代码循环中的木马程序,也不了解问题的严重性,这样的源代码可读性可维护性已经超出Mike个人能力与精力范围。Kevin只能凭常识判断,如果因为Bug的存在,二话不说先把旧软件停了,再重新开始编写新程序。但在没有全面理解旧程序,分析清楚已有程序故障原因的情况下,就不能保证重新编写的新程序不会出现同样问题,更奢谈优于现有软件,毕竟Mike编写的软件平均页面响应时间小于2秒,看上去运行流畅自然,稳定性一目了然。目前的软件再不好,但运行起来看上去还比较顺畅,还可以用,没有崩溃,毕竟客户只关心是否好用,不会在乎源代码的来源。对于复杂系统,彻底推翻从头开始,成本太高,在现有基础上”重用”,并一点点地改进慢慢推出各种升级版,这才是合乎逻辑的方式。 项目后期程序完全失控,半年后,坏消息不断传来,象雪球越滚越大,软件兵败如山倒。有用户发现自己的浏览器经常出现一些小广告,继而在自己的Firebox浏览器中出现大量裸体女人照片,更有外部链接到公司网页非法索取电邮密码,用户开始向公司抱怨软件的不安全性,公司上层顿悟事态严重,指定Kevin亲自处理Mike的问题。Kevin最初担心的问题终于出现了,开始犯下的错误如果得不到及时纠正,整个过程都要为此付出代价。因为是抄袭的源代码,Kevin不得不用两个月的时间分析Mike的程式,而不是简单继续他的编程工作。Kevin开始怀疑Mike的研究诚信问题,对他参与的项目,程序与调试都产生了怀疑。 一个月过去了,Kevin发现只要是有Mike博士参与的项目都以失败告终,程序多少都有抄袭的疑点。一天,用户告上门来,有黑客盗录她女儿的真人影像,她忘了用电话及时确认,虽然她发现语音质量不好,但对方借口网络很卡,话筒丢了把她蒙过去了,她担心女儿在菲律宾被骗,一着急稀里糊涂往菲律宾的一个账号把钞票打过去,没有想到是黑客利用了Mike抄写的木马程式,在她的浏览器Skype上用她女儿的真人影像进行诈骗。 人在做,天在看。 (十)山重水复疑无路,柳暗花明又一村。 与此同时,Mike也没有休息,他在家夜以继日地工作,终于把程序重新写了一遍。新程序的每句code都是他自己的创造,每个变量都是用自创独一无二的非常复杂的关键字排序,完全没有变量二义性问题。新版本全是自己的创造,他坚信新软件绝对没有任何问题。好在Mike的程序事先设计了自动下载模块,可以通过远程自动激活自动下载。 Mike从网上抄袭了一个自动打补丁的程式,他悄悄把Kevin找到一旁,开门见山地告诉Kevin,退货期一过,程式就自动从公司的网站上下载补丁来补安全窟窿,神不知鬼不觉把旧版本完全改新Version,用户并不知道已经打了补丁,只是觉得计算机越来越慢而已,用公司的软件已经习惯,不得不再掏腰包买新版本,再打补丁循环下去。自动下载程序可以神不知鬼不觉把旧程序换成新程序。公司还可以推卸责任,黑客是从客户电脑上的其他程序进来的。公司免费给客户升级,客户还对公司千恩万谢,多好的商业模式。 Kevin只好默默地同意,他可以向总经理解释打补丁是IT行业的潜规则,所有的计算机硬件商都留后门,微软工程师发现过一个驱动器,可以在电脑内核(kernel)程序中执行最高层级的环形特权(ring-0)的后门[1]。连大名鼎鼎的苹果都承认它有后门,一个小小的软件承包商敢不留后门吗?言下之意在软件中留后门实为被迫行为。至于留了后门的好处到底是什么,大家都心知肚明,反正公司要在市场上立于不败,必须留后门,这是推诿”为了生存不得已的潜规则”。毕竟公司的每个环节都出了问题,Mike拿最低的测试员工资却在做CTO的工作,能把全部责任推给他一个人吗? 复旦同窗Mike博士现在北美IT行业登山临水,他已经习惯平视北美的IT行业,既没有高山仰止,也没有一览众山小。Mike非常清醒,他正在拥抱移动互联网+物联网+工业的浪潮。 青山不老,绿水长流。 2014-April-11(原稿),2016-June-11(第二次修改) Reference [1]http://www.wenxuecity.com/news/2019/04/03/8207055.html
2 Comments
源
1/20/2018 05:26:42 pm
据英国路透社1月20日报道,美国检方当地时间19日宣布,IBM中国公司前软件工程师许家强(音译)因盗用IBM专有源代码而被判入狱5年。
Reply
源
1/20/2018 05:28:26 pm
代码没什么用 ,是算法值钱
Reply
Leave a Reply. |
李革胜
CategoriesArchives
August 2016
|