什么代碼才是好代碼?這真是個老得能拔掉牙齒的話題。好吧,那讓我們再在這刮沙塵暴的無聊時光里重復一次。好的代碼要是易讀的代碼、要做到職責分離、要做到單一職責、要有高的執(zhí)行效率....
等等,等等,這才抽象了,太書面化了。我只是一個菜鳥,剛寫代碼幾年,也沒念過什么書,能不能說得通俗易懂一些?
好吧,我停下來,想,這真是個難纏的家伙。我說,這樣吧,我推薦幾本書你去看吧,《重構(gòu)》熊節(jié)最近再版了,建議你去買一本。恩,等等,有個省錢的招,去圖靈俱樂部討論組注冊下,蹭贈書也很爽,哈哈。
可是,你還沒告訴我什么代碼才是好代碼呢?知道你也沒什么好答案,我自己來說好了。
省略掉此時我內(nèi)心花花的汗水,下面是菜鳥的敘述:
1.一致
我發(fā)現(xiàn)自己有輕微的強迫癥,當我碰到以下代碼時,我就會沖動。
沖動前代碼:
def imgName
if(XXX){
imgName="meigui"
}else{
imgName=""
}
沖動后代碼:
def imgName=XXX?"meigui":""
盡管兩段代碼功能一致,但一旦我發(fā)現(xiàn)出現(xiàn)沖動前代碼時,我就會感到不舒服,感到難受,就好像看到閱兵正步走不齊一樣。方法名也是一樣:
沖動前:
def testXXX(){}
沖動后:
def should_XXX_when_XXX(){}
變量亦是如此:
沖動前:
def imgNode=resouce.adoptTo(Node)
沖動后:
def node=resouce.adoptTo(Node)
總之,我不愿意看到同一個事情有兩種實現(xiàn)方式,如果功能類似,那么不管是邏輯還是變量、方法名,我會強迫一致,整齊劃一。
關于一致,從調(diào)試代碼的角度看,零星的不一致比大量的不一致更加糟糕,因為這時大部分地方的一致性會令人麻痹大意。在實現(xiàn)查詢分頁功能時,我們有這樣一行代碼:
nodeIterator.size
這行代碼的意思是獲取查詢結(jié)果的總數(shù),大部分情況下它工作良好,但是在一種特殊情況下它返回了-1。這對我當時幾乎是災難性的,因為調(diào)試過程中我們始終相信這行代碼的行為一致,結(jié)果是花費了一個下午才找到這個問題。
2.簡潔
我喜歡短的代碼,對我而言,短的程序總是比更長一些的代碼容易理解,小學時學課文就已經(jīng)這樣了,一看到大段的段落我總是會暈過去(特別是文言文,首先我就
對自己理解這段文字失去了信心)。這里要提到注釋,即是這些注釋明確是為了提高代碼的可讀性,也會增加我閱讀代碼的困難,所以我不會在方法里的任何位置添
加注釋,撐死在個別方法聲明前添加,并且這種情況也盡量避免,如果這個類確實包含了重要的不易理解的算法,我也只會在類聲明前添加注釋。
關于自然語言,有一個基于經(jīng)驗的結(jié)論被稱為Zipf定律,即:自然語言中最常用到的單詞,其長度會趨于最短。
我寫代碼的時候,能夠簡寫盡量簡寫,例如,變量名,imageNode,我一定會寫成imgNode;方法名procedureXXX,我一定會寫成
procXXX,和討厭大段代碼一樣,我非常討厭命名很長的方法名和變量名,盡管這些名稱這么長是為了更好的增加可讀性,但可讀性不是這樣增加的。
在我的第一份代碼工作里,我們使用拼音來命名方法和變量(還好,沒有包括類名),我討厭這種命名方式的原因并不是因為我的語文老師不好以至于我前后鼻音不分,而是這種寫法根本排除了簡寫的可能性,甚至,為了避免歧義,有時不得不變得更長。
3.聯(lián)覺和順序
關于記憶,人類有兩種重要的記憶能力:聯(lián)覺和順序記憶。
關于聯(lián)覺,一個例子是:你總可以一眼記住一個人的臉,比如范冰冰,盡管我到現(xiàn)在也不清楚她到底是單眼皮還是雙眼皮,也不清楚她到底是厚嘴唇還是薄嘴唇。
那么,在代碼里,這里的表現(xiàn)就是局部,即一個功能的所有相關代碼都集中在一個地方。我最討厭的代碼是這樣的:最開始我打開一個文件,在閱讀的過程中,我發(fā)
現(xiàn)一個不清楚的方法,于是我按下ctrl并點擊鼠標,于是我跳到另外一個文件;接下來,在閱讀另外一個方法里,我再次發(fā)現(xiàn)了一個不清楚的方法,于是我再次
按下ctrl并點擊鼠標,哇哈,新的文件打開了....如此反復,終于當我打開最后一個文件時,我發(fā)現(xiàn)IDE的文件條里已經(jīng)密密麻麻的排滿了好幾排文件,
于是,我移動鼠標,右鍵,彈出一個關閉菜單,我選擇了close others,瞬間,哦米拖佛,整個世界清靜了,但是,等等,我最初是打算干嘛來著?
所以,請把所有相關聯(lián)的代碼都集中在一個地方,求您了。哦,對了,能不用接口請不要用接口,總會碰到這樣的情況,打開好幾排的文件,接口文件占了一半,我靠,少幾個接口會死啊。對了,這可能是您的一致性心理在作怪,對不起,對不起。
關于局部,一個范例同樣與調(diào)試有關,在很久之前的一次調(diào)試中,我們始終找不到一個變量錯誤的原因,因為在這段代碼里,根本找不到任何錯誤,很久以后,終于
發(fā)現(xiàn),這個變量竟然是個全局變量,嘿嘿,告訴你吧,這個變量在servlet里,04年的時候,網(wǎng)上很火的一篇文章,標題就是:不要在servlet里使
用全局變量!
關于順序,最典型的例子出現(xiàn)在高中化學里,我總也不能瞬間說出第12、13個化學元素是什么,我通常會這樣記憶:氫氦鋰鈹硼碳氮氧氟氖鈉鎂鋁硅磷,啊哈,第12個元素是鎂,第13個元素時鋁,合起來就是--美女!
所以,在代碼里,請將互相調(diào)用的方法按順序擺放,方法1先調(diào)用了方法2,那么請將方法2緊放在方法1后邊。我討厭這樣的配置:打開方法1,發(fā)現(xiàn)其調(diào)用了方
法2,點擊方法2,編輯器里的滾動條瞬間從最上端滾到最下端,緊接著,滾動條又從最下端滾動到中間,再接著,又是最下端,接著,歸零到最上端....人生
經(jīng)不起這樣的大起大落,真的,那得要多么大的心臟啊,麥蒂才有過那么一次,13秒....
還有,知道為什么goto為什么那么臭名昭著了吧。
4.自然
使得代碼具有輕松的表達方式,同時把錯誤率降到最低,一種最重要的方法就是代碼變得“自然”,即向自然語言靠攏。因為代碼并不僅僅是與機器交流的,更重要的是,需要在人之間交流。
機器語言到高級語言,面向過程語言到面向?qū)ο笳Z言,jdbc到hibernate,java到動態(tài)語言,這些都促使代碼變得更加自然。
Ruby里有個不起眼的特性,就是方法調(diào)用不用再寫括號,這一特性是如此的微不足道但是卻被很多人津津樂道,原因就是它更加自然,更加貼近我們的自然語言。于是,我看到,我的同事曉娜,在groovy里,一遍遍的將她力所能及的括號去掉。
此外,程序語言和自然語言是有區(qū)別的,除了不能在代碼里利用感情詞抒發(fā)情感之外(我想,如果可以,一定會看到很多的馮特),程序語言沒有口語。很少看到程
序員之間這樣交流,來吧,我們來說段代碼(當然也有,徐昊就可以,哈哈),他們更多的會使用白板和筆或者直接是編輯器。所以,結(jié)束招聘時是否需要筆試的爭
論吧,我真為那些不經(jīng)過筆試就直接招人的公司感到羞愧,因為他們根本就不懂程序語言。
此處省略華麗的分割線。
此文謝謝我們項目組WGSN的激烈討論,謝謝討論中徐昊的精彩點評。
posted @
2010-03-21 22:27 ronghao 閱讀(2133) |
評論 (2) |
編輯 收藏
唐僧與
QA MM
在一個典型的項目團隊里,包括了以下幾種角色(帽子):
PM(項目經(jīng)理)、
BA(業(yè)務分析師)、
DEV(程序開發(fā)者)和
QA(質(zhì)量保證人員),整個團隊的目標是向客戶交付價值。
那么,有一天,
QA MM來找我,我是開發(fā)人員。
MM說,一張圖片沒有正常顯示,我想知道原因,同時想知道你能否修復。我的第一想法是,這不可能,一定是環(huán)境的原因。我說,好的,稍等。接下來,我張大嘴巴看到了
MM給我重現(xiàn)的
BUG:本該顯示圖片的位置一片空白,就像此時我合不上的嘴。這怎么可能呢?我想,這個功能完成的如此之得意,以至于測試用例里的數(shù)據(jù)都是以我的名字命名的。
幾分鐘后,或者更長,我叫來
MM,說,找到原因了。
我打開編輯器,光標在源程序的某一行閃爍,我說,最根本的原因在這里。我看到
MM的眼中閃過一絲迷茫。接下來,我卻換到另外一個源文件,光標繼續(xù)閃爍,我說,這里的程序因此受到影響??吹贸觯?
MM有點發(fā)暈。終于,當我打開第
N個源文件并試圖繼續(xù)講解時,
MM昏過去了。
當
MM蘇醒過來時,我在她清澈的雙眼中看到了一只清晰的唐僧。
MM肯定感到了不好意思,因為我的講解中包含了比喻、類推、排比等我力所能及的各種語文知識,看得出,我很努力,我的語文老師也很努力,所以她委婉地說,能不能簡單一點?
我想了想,說,測試驅(qū)動時測試數(shù)據(jù)不全導致程序少考慮一種情況。
MM說,能修復嗎?
我說,可以。于是故事結(jié)束。
就
是這樣,當我們執(zhí)行一項任務時,圍繞這項任務必然會產(chǎn)生許許多多的信息,這些信息對于該任務的執(zhí)行者是必須的,但是對于其他人則不是,有效的溝通往往來自
于簡練的表達即只表達對方需要和可以理解的內(nèi)容,浩瀚的細節(jié)只會將真正想表達的內(nèi)容淹沒。其實這里還有這樣一層意思:我之所以用這么多的細節(jié)信息來淹沒
QA,實際上是不太情愿承認程序里有
BUG。
QA想要的結(jié)果很簡單,是否是程序
BUG,能否修復。而開發(fā)人員則往往把自己的程序與自己關聯(lián)在了一起,認為程序是自己的擴展,程序有
BUG則意味著自己有缺陷。這一關系明顯是矛盾的,可是一些團隊里開發(fā)人員和
QA能夠和平相處,而有些團隊卻勢如水火。
那么,對于單個任務而言,需要定義自己的變量,這些變量數(shù)據(jù)只與該任務相關,只在該任務里可見。典型的工作流應用于任務執(zhí)行期間的中間數(shù)據(jù)存儲。在文檔處理中,一個重要的功能就是需要提供版本管理,在單個任務實例里,辦理者能夠管理自己處理過的文檔版本。
描述
任務能夠定義變量,在一個流程實例里,該變量只能被其任務實例所使用。
圖
6-2任務級別的數(shù)據(jù)可見性
如圖
6-2所示,我們在任務
B上定義了一個變量
M,此時,在一個流程實例里,只有任務
B的實例才能使用該變量。
實現(xiàn)
存在兩種實現(xiàn)方式,一種是如圖
6-1所示的,在任務節(jié)點定義中聲明變量,運行期初始化任務實例的同時初始化該變量并使用;
另一種是在流程定義級別統(tǒng)一聲明變量,但是各個任務實例都獨立初始化并存儲該變量。第二種實現(xiàn)方式在各個任務都需要使用同一語義的變量時很常見,例如各個任務實例都會有參與者,我們在流程定義時聲明一個名為
userid的變量,在流程實際執(zhí)行時,各個任務實例都會獨自保存有自己的
userid數(shù)據(jù)。
posted @
2010-03-16 22:05 ronghao 閱讀(1636) |
評論 (0) |
編輯 收藏
和前面的章節(jié)一樣,我們先從一個故事開始,這個故事和晚飯有關。在我家,周一至周五,老婆做飯,我洗碗。每天做完
飯,老婆會叫我到廚房,說,看,這個盤要洗一下,另外,灶臺臟了,也要擦。如果放在以前,我會說,好,明白了。但是現(xiàn)在,程序員的生活讓我意識到,溝通永
遠不是一件簡單的事情,我說,好,知道了。
等等,這個故事和本章的主題-數(shù)
據(jù)模式有一毛錢的關系?這只是一個關于溝通的故事。是的,讓我們稍微映射一下:這里,晚飯這個流程包含了兩個基本的任務,分別是做飯和洗碗,在做飯這個任
務完成時,任務的執(zhí)行者(老婆)向下一個任務的執(zhí)行者(我)傳遞了數(shù)據(jù)(要洗哪些東西),正如語言是人之間的溝通方式一樣,數(shù)據(jù)是IT系統(tǒng)之間的溝通方式,語言之間的溝通總是最有效的,數(shù)據(jù)交互卻未必,因為IT系統(tǒng)里的數(shù)據(jù)交互除了讓計算機理解外重要的是還需要人理解,IT系統(tǒng)是對現(xiàn)實生活的映射,也正因為如此,現(xiàn)在數(shù)據(jù)之間的溝通也在向語言靠攏即語義化(REST/語義網(wǎng))。
好,言歸正傳。
在
前兩章里,我們分別討論了工作流的控制模式和資源模式,控制模式關注于如何合理調(diào)配業(yè)務流程里的任務,從而獲得理想的執(zhí)行效率和收益;資源模式則關注于如
何合理調(diào)配可用的資源來執(zhí)行業(yè)務流程。本章將介紹工作流系統(tǒng)里的數(shù)據(jù)模式,從數(shù)據(jù)的角度分析工作流系統(tǒng)對數(shù)據(jù)的處理。數(shù)據(jù)模式共計39種,在下面的介紹中,我們將這些模式分為了四部分,分別是數(shù)據(jù)可見性、數(shù)據(jù)交互、數(shù)據(jù)傳輸和基于數(shù)據(jù)的路由。
本章先會概要重復一下與數(shù)據(jù)模式相關的一些基本概念,例如流程定義、流程實例、原子任務、塊任務等。接下來會對具體的39種數(shù)據(jù)模式進行討論,討論的模式按照應用、描述和實現(xiàn)展開,分別對應著實際場景對模式的映射、模式的介紹和工作流系統(tǒng)對該模式的實現(xiàn)支持。最后是小結(jié)。
一、基本概念
1、工作流系統(tǒng)里的流程結(jié)構(gòu)
在正式介紹數(shù)據(jù)模式之前,讓我們先簡單回顧一下工作流系統(tǒng)里流程的基本結(jié)構(gòu)。
圖 6-1 工作流系統(tǒng)里的流程結(jié)構(gòu)
流程定義:對業(yè)務流程的建模和描述,其具有足夠的細節(jié)信息,能夠直接被工作流系統(tǒng)所執(zhí)行。典型的,流程定義由一系列的任務組成,這些任務以圖形的形式展現(xiàn)并被連接起來。
流程實例:流程定義的一個執(zhí)行實例被稱為流程實例。一個流程定義可以存在多個同時執(zhí)行的流程實例。這些流程實例互相獨立執(zhí)行。
任務:一個任務對應著流程定義里的一個單一工作單元。存在四種不同類型的任務:原子任務、塊任務、多實例任務和多實例塊任務。
原子任務包含簡單且獨立的任務定義,當其初始化時只會產(chǎn)生一個可執(zhí)行的任務實例。
塊任務是一系列任務的組合,典型的,工作流系統(tǒng)里存在的子流程任務(節(jié)點)即是塊任務,當一個塊任務開始執(zhí)行時,其將流程控制權傳遞給與之對應子流程的第一個任務,當子流程完成執(zhí)行后則將控制權返回給塊任務。如圖6-1所示,塊任務C對應著一個由任務X、任務Y和任務Z組成的子流程,實際執(zhí)行時,任務C會觸發(fā)任務X的執(zhí)行,任務Z執(zhí)行完畢即子流程執(zhí)行完成后則會觸發(fā)任務C執(zhí)行完成。
多實例任務在實際執(zhí)行時會產(chǎn)生多個并行執(zhí)行的任務實例,這些任務實例一般互相獨立執(zhí)行。當一定數(shù)量的實例執(zhí)行完畢后即會觸發(fā)后續(xù)任務的執(zhí)行。
多實例塊任務結(jié)合了塊任務和多實例任務的定義,其在實際執(zhí)行時產(chǎn)生多個任務實例,每個任務實例對應著一個子流程實例。
任務實例:任務的一個執(zhí)行實例。
2、數(shù)據(jù)相關約定
我們使用def var ${變量名}定義數(shù)據(jù)元素,同時def var ${變量名}的聲明位置決定了變量的作用范圍。如圖6-1所示,我們在任務C上定義了一個名為M的數(shù)據(jù)變量,其的作用范圍為任務C,任務級別。
我們使用use(${變量名})表明對變量的使用;使用pass(${變量名})表明數(shù)據(jù)變量的傳遞。在圖6-1里,變量M從任務C傳遞至任務E。
對于變量的數(shù)據(jù)類型,典型的有String、integer、float、boolean、date、time等,很多工作流系統(tǒng)使用序列化和反序列化支持存儲任意類型的數(shù)據(jù)類型,如數(shù)組、集合、對象。
3、類比的約定
在后續(xù)對各個模式的介紹里,我會圍繞一個項目團隊的故事進行映射,我們?nèi)绱思s定:
流程定義:我們認為所有成熟的軟件公司都會建立起其完整并適用的一套軟件開發(fā)流程,我們將這套流程看作是這里的流程定義。
流程實例:圍繞著軟件開發(fā)流程,我們會使用這套流程來開始我們實際的軟件開發(fā)項目,我們將所有的軟件開發(fā)項目都看作是開發(fā)流程的執(zhí)行實例,即流程實例。
任務:項目開發(fā)過程中的各項任務。
數(shù)據(jù):我們將團隊成員之間的信息交流看作是數(shù)據(jù)交互。
posted @
2010-03-14 21:14 ronghao 閱讀(2279) |
評論 (0) |
編輯 收藏
我們從一個最簡單的登錄例子開始。
最開始我們需要驗證在用戶名和密碼都正確的情況下,能夠正常登錄系統(tǒng),我們這樣編寫測試代碼(以下都是偽代碼,使用TestNG和Selenium):
@Test
def should_login_success_with_exist_username_and_correct_password(){
LoginPage page = user.open(LoginPage,"/login.html")
user.perform("login",['user1','1234'],on(page))
assert page.successLogin
}
恩,很不錯,運行一下,出現(xiàn)紅條。為什么呢?原來測試數(shù)據(jù)庫里沒有用戶名為user1的用戶,好吧,寫個數(shù)據(jù)庫數(shù)據(jù)初始化腳本。再運行,OK,綠條!
那么,接下來我們再增加一個測試,需要覆蓋密碼錯誤時不能登錄系統(tǒng)的情況,很快測試就完成了:
@Test
def should_login_success_with_exist_username_and_incorrect_password(){
LoginPage page = user.open(LoginPage,"/login.html")
user.perform("login",['user1','4321'],on(page))
assert page.successLogin,false
}
再運行一下測試,綠條。好啦,現(xiàn)在可以看下這段代碼,恩,有些重復,重構(gòu)一下:
@Test
def should_login_success_with_exist_username_and_correct_password(){
assert login('user1','1234')
}
@Test
def should_login_success_with_exist_username_and_incorrect_password(){
assert login('user1','4321'),false
}
def login(username,password){
LoginPage page = user.open(LoginPage,"/login.html")
user.perform("login",[username,password],on(page))
return page.successLogin
}
重構(gòu)完成,可以看到,我們的測試方法里現(xiàn)在沒有了任何行為,僅僅是數(shù)據(jù)!這樣讓我感覺有點怪,不管了,先用TestNG提供的@dataProvider整理一下:
@Test(dataProvider="testdata")
def testLogin(username,password,expected){
LoginPage page = user.open(LoginPage,"/login.html")
user.perform("login",[username,password],on(page))
assert page.successLogin,expected
}
@DataProvider(name="testdata")
def Object[][] dataForLogin(){
def data=new Object[2][]
data[0]=['user1','1234',true] as Object[]
data[1]=['user1','4321',false] as Object[]
}
測試方法只剩下了一個!如果要測試不存在的用戶不能登錄系統(tǒng)呢?很簡單,增加數(shù)據(jù)即可!
@DataProvider(name="testdata")
def Object[][] dataForLogin(){
def data=new Object[2][]
data[0]=['user1','1234',true] as Object[]
data[1]=['user1','4321',false] as Object[]
data[1]=['inexistuser','1234',false] as Object[]
}
在我們的測試方法里,測試數(shù)據(jù)和測試的行為進行了完全的分離。從系統(tǒng)的功能來說,功能一旦實現(xiàn),那么就是一個黑盒,我們只要提供數(shù)據(jù)即可進行測試,這個數(shù)據(jù)包括兩部分:輸入和期待的輸出。我開始暗自嘀咕:難道我以前那么多的洋洋得意測試方法很多都是不需要的嗎?這些方式為什么會存在呢?恩,想起來了,這些方法是為了覆蓋功能的各個路徑的,是提高測試覆蓋率的。那么為什么會產(chǎn)生這么多的測試方法呢?哦,在這些測試方法里,測試數(shù)據(jù)和測試行為是耦合在一起的!
我伸了個懶腰,突然想,這下好了,我已經(jīng)封裝好了功能行為,QA想增加測試用例只需要自己增加數(shù)據(jù)就可以了,嘿嘿,爽啊。說曹操,QA到。QA mm說,你的某個功能實現(xiàn)有問題。我瞅了一眼,說,不可能啊(這是dev面對bug的第一反應),俺有測試的,持續(xù)集成一直是綠條的。QA mm說,在你的開發(fā)環(huán)境下測試是沒有問題的,但是在QA環(huán)境,因為數(shù)據(jù)庫變了,數(shù)據(jù)變了,應用服務器變了,所以會有些問題。我極不情愿的登錄到QA環(huán)境,一測試,還真是,郁悶。
怎么辦?修復完BUG,第一反應就是自動化測試能不能跑在QA環(huán)境呢?一般情況下,這些測試需要干凈的測試環(huán)境,我們會制造很多的測試數(shù)據(jù),可是在QA環(huán)境下,QA有她自己的測試數(shù)據(jù),這些數(shù)據(jù)都不存在了哈。恩,看看剛才的測試代碼,哈,就用QA的數(shù)據(jù)也可以啊,心情愉悅的改下:
@DataProvider(name="testdata")
def Object[][] dataForLogin(){
def data=new Object[2][]
data[0]=['hrong','1234',true] as Object[]
data[1]=['hrong','4321',false] as Object[]
data[1]=['rhao','1234',false] as Object[]
}
OK,完成!為了該測試既能在開發(fā)測試環(huán)境運行又能在QA環(huán)境下運行,我們可以引入一個環(huán)境變量,將測試數(shù)據(jù)扔到文件里,通過環(huán)境變量來加載不同的測試數(shù)據(jù)(測試文件)。
好吧,喝點東西(甲流很厲害,喝板藍根好了),總結(jié)一下:
數(shù)據(jù)驅(qū)動測試:
測試數(shù)據(jù)與測試行為分離,通過數(shù)據(jù)來驅(qū)動測試。
好處:
在對測試行為封裝好的情況下,QA mm能夠自己通過數(shù)據(jù)修改自動化測試;
自動化測試能夠運行在多個環(huán)境下(開發(fā)環(huán)境、QA環(huán)境、產(chǎn)品環(huán)境)
測試的可讀性
測試方法大量壓縮
適用范圍:
功能測試(selenium測試)
通過環(huán)境準備測試數(shù)據(jù)(非測試用例自己準備數(shù)據(jù))
可能存在的問題:
比一般的測試編寫困難,特別是在靜態(tài)語言里
最后:該文章的思考來自于徐昊在團隊內(nèi)部的相應Session.
posted @
2010-01-17 12:08 ronghao 閱讀(2578) |
評論 (0) |
編輯 收藏
今天下午1時20分,百度首席產(chǎn)品設計師孫云豐在自己的博客中撰文關于谷歌退出中國,直指Google退出中國的姿態(tài)證明自己是市儈分子,對此感到惡心。
他的博客全文如下:
google宣稱要退出中國,所證明的,恰恰不是市面上的那些g粉所宣稱的那樣,google是個人權斗士,而剛好反了過來,正好證明google是個市儈分子。
google
的首席法律顧問的調(diào)調(diào)讓我感到惡心。因經(jīng)濟利益退出,就直白白的說好了,把自己涂脂抹粉一番,還煞有介事的提到google被中國人攻擊,中國異議分子的
Gmail信箱被攻擊,把這些事情作為退出中國的鋪墊,這種論調(diào)是侮辱中國普通老百姓的智商,但還真有可能迎合那幫目空一切,但從未到過中國、對中國沒有
絲毫了解,卻又喜歡對中國說三道四的西方人的假想。
只提一個假設,如果谷歌占據(jù)了中國80%的搜索市場份額,google的高管,還會這么高調(diào)的宣稱要do no evil,從中國退出嗎?
整個事情給我的唯一感受,就是惡心。
————–
以上是作為一個曾經(jīng)的忠實google用戶而說的,和百度無關。市面上沾沾自喜于了解一點google的產(chǎn)品技術細節(jié)將google奉為道德楷模而自封G粉的兄弟,請勿跟帖瞎噴,你們根本不懂什么叫搜索引擎,什么叫自由人權。
立此存照的原因在于,原帖 http://news.csdn.net/a/20100113/216459.html 被百度的人要求刪掉,所以本著對歷史負責的態(tài)度,保存與此,歡迎轉(zhuǎn)帖。
posted @
2010-01-14 13:29 ronghao 閱讀(425) |
評論 (0) |
編輯 收藏