Java編程——怎樣尊重一個程序員
很多不尊重人現象的起源,都是因為某些人偏執的相信某種技術就是世界上最好的,每個人都必須知道,否則他就不是一個合格的程序員。這種現象在Unix(Linux)的世界尤為普遍。Unix系統的鼓吹者們(我曾經是其中之一)喜歡到處布道,告訴你其它系統的設計有多蠢,你應該遵從Unix的"哲學"。他們仿佛認為Unix就是世界終極的操作系統,然而事實卻是,Unix是一個設計非常糟糕的系統。它似乎故意被設計為難學難用,容易犯錯,卻美其名曰"強大","靈活"。眼界開闊一點的程序員都知道,Unix的設計者其實基本不懂設計,他們並不是世界上最好的程序員,卻有一點做得很成功,那就是他們很會制造宗教,煽動人們的盲從心理。Unix設計者把自己的設計失誤推在用戶身上,讓用戶覺得學不會或者搞錯了都是自己的錯。
如果你對計算機科學理解到一定程度,就會發現我們其實仍然生活在計算機的石器時代。特別是軟件系統,建立在一堆歷史遺留的糟糕設計之上。各種蹩腳腦殘的操作系統(比如Unix,Linux),程序語言(比如C++,JavaScript,PHP,Go),數據庫,編輯器,版本控制工具,…… 時常困擾著我們,這就是為什麽你需要那麽多的所謂"經驗"和"知識"。然而,很多IT公司不喜歡承認這一點,他們一向以來的作風是"一切都是程序員的錯!","作為程序員,你應該知道這些!" 這就造成了一種"皇帝的新裝現象"——大家都不喜歡用一些設計惡劣的工具,卻都怕別人嘲笑或者懷疑自己的能力,所以總是喜歡顯示自己"會用","能學",而沒有人敢說它難用,敢指出設計者的失誤。
我這個人呢,就是這種"×××文化"的一個反例。我所受到的多元化教育,讓我從這些偏激盲從,教條主義的心理裏面跳了出來。每當有人因為不會某種工具或者語言來請教我時,我總是很輕松的調侃這工具的設計者,然後告訴他,你沒理由知道這些破玩意兒,但其實它就是這麽回事。然後我一針見血的告訴他這東西怎麽回事,怎麽用,是哪些設計缺陷導致了我們現在的詭異用法…… 我覺得所有的IT從業人員對於這些工具,都應該是這樣的調侃態度。只有這樣,軟件行業才會得到實質性的進步,而不是被一些自虐的設計所困擾,造成思維枷鎖。
總之,這是一個非常重要的"態度問題"。雖然在現階段,我們有必要知道如何繞過一些蹩腳的工具,利用它們來完成自己的任務。然而在此同時,我們必須正視和承認這些工具的惡劣本質,而不能拿它們當教條,把什麽事都怪罪於程序員。只有分清工具設計者的失誤和程序員自己的失誤,不把工具的設計失誤怪罪於程序員,我們才能有效地尊重程序員們的智商,鼓勵他們做出簡單,優雅,完善的產品。
分清精髓知識和表面知識,不要太拿經驗當回事
在任何領域,都只有少數知識是精髓的,另外大部分都是表面的,膚淺的,是從精髓知識衍生出來的。精髓知識和表面知識都是有用的,然而它們的分量和重要性卻是不一樣的。所以必須區分精髓知識和表面知識,不能混為一談,對待它們的態度應該是不一樣的。由於表面知識基本是死的,而且很容易從精髓知識推導衍生出來。我們不應該因為自己知道很多表面知識,就自以為比掌握了精髓知識的人還要強。不應該因為別人不知道某些表面知識,就以為自己高人一等。
IT公司經常有這樣的人,以為精通一些看似復雜的命令行,或者某些難用的程序語言就很了不起似的。他們如果聽說你不知道某個命令的用法,那簡直就像法國人不知道拿破侖,美國人不知道華盛頓一樣。這些人沒有發現,自己身邊有些同事其實掌握著精髓的知識,他們完全有能力從自己已有的知識,衍生制造出所有這些工具,而不只是使用它們,甚至設計得更加完善和方便易用。這種能夠設計制造出更好工具的人,往往身負更加重要的任務,所以他們往往會在被現有工具的用法迷惑的時候,非常謙虛的請同事幫助解決,大膽的承認自己的糊塗。
如果你是這個精通工具用法的人,切不可以把同事的謙虛請求當成可以顯擺自己"資歷"的時候。這同事往往真的是在"不恥下問"。他並不是搞不懂,而是根本不屑於,也沒有時間去考慮這種低級問題。他的迷惑,往往來源於工具設計者的失誤。他很清楚這一點,他也知道自己的技術水平其實是高於這工具的設計者的。然而為了禮貌,他經常不直接批評這工具的設計,而是謙虛的責怪自己。所以同事向你"虛心請教",完全是為了制造一種友好融洽的氣氛,這樣可以節省下時間來幹真正重要的事情。這種虛心並不等於他在膜拜你,承認自己的技術能力不如你。
所以正確的對待方式應該是誠懇的表示對這種迷惑的理解,並且坦率的承認工具設計上的不合理,蹩腳之處。如果你能夠以這種謙和的態度,而不是自以為專家的態度,同事會高興地從你這裏"學到"他需要的,膚淺的死知識,並且記住它,避免下次再為這種無聊事來打擾你。如果你做出一副"天下只有我知道這奇技淫巧"的態度,同事往往會對你,連同這工具一起產生鄙視的情緒。他下次會照樣記不住這東西的用法,然而他卻再也不會來找你幫忙,而是一拖再拖。
不要自以為聰明,不要評判別人的智商和能力
在IT公司裏,總是有很多人覺得自己聰明,想顯示自己比別人聰明。這種人似乎隨時都在評判(judge)別人,你說的任何話,不管認真的還是開玩笑的,都會被他們拿去作為評估你智商和能力的依據。
有時候你寫了一些代碼,自己知道時間不夠,可是當時有更重要的事情要做,所以打算以後再改進。如果你提交代碼時被這種人看到了,他們就會堅定地認為你一輩子只能寫出那樣的代碼。這就是所謂"wishful thinking",人只能看到他希望看到的東西。這種人隨時都在希望自己比別人聰明,所以他們隨時都在監聽別人顯得不如他聰明的時候,而對別人比他高明的時候視而不見。他們只能看到別人疏忽的時候,因為那是可以證明他們高人一等的有利證據。
當然,誰會喜歡這樣的人呢,可是他們在IT公司裏相當的普遍。你不敢跟他們說話,特別是不敢開玩笑,因為他們會把你稀裏糊塗的玩笑話全部作為你智商低下或者經驗不足的證據。你不敢問他們問題,因為他們會認為你問問題,說明你不懂!我發現具有這種心理的人,一般潛意識裏都存在著自卑。他們有某些方面(包括智力在內)不如別人,所以總是找機會顯得高人一等。我還沒有想出可以糾正這種心理問題的有效方法,但如我上節所說,意識到整個行業,包括你仰慕的鼻祖們,其實都不懂很多東西,都是混飯吃的,是一個有效的放松這種心理的手段。
有時候我喜歡自嘲,對人說:"我們這行業的祖先做了這麽多BUG來讓我們修補。現在你做了一坨屎,我也做了一坨屎,我的屎貌似比你的屎香一點。"這樣一來,不但顯示出心理的平等和尊重,而且避免了因為謙虛而讓對方產生高人一等的情緒。說真的,做這行根本不需要很高的智力,所以最好是完全放棄對人智力的判斷。你不比任何人更聰明,也不比他們笨。
解釋高級意圖,不要使用低級命令
隨時都要記住,同事和下屬是跟你智力相當的人。他們是通情達理的人,然而卻不會簡單地服從你的低級命令。像我在Google的隊友的做法,就是一個很好的反面教材。其實這位Googler只是想告訴我:"刪掉這行文本,然後改成這樣……" 就是如此一個簡單的事情,然而她卻故弄玄虛,不直接告訴我這個"高級意圖",而是使用非常低級的指令:"按Ctrl-k!……" 語氣像是在對一個不懂事的小學生說話,好像自己懂很多,別人什麽都不知道似的。
有哪個Emacs用戶不知道Ctrl-k是刪掉一行字呢,況且你現在面對的其實是一個資深Emacs用戶。我想大家都看出來這裏的問題了吧。這樣的低級命令不但邏輯不清楚,而且是對另一個人的智力的嚴重侮辱。你當我是什麽啊?猴子?如果這位Googler表明自己的高級意圖,就會很容易在心理上和邏輯上讓人接受,比如她可以說:"配置文件的這行應該刪掉,改成……"
在項目管理的時候也需要註意。在讓人做某一件事之前,應該先解釋為什麽要做這件事,以及它的重要性。這樣才能讓人理解,才能尊重程序員的智商。
不要期望新人向自己學習
很多IT公司喜歡把新人當初學者,期望他們"從新的起跑線出發",向自己"學習"。比如,Google把新員工叫做"Noogler"(Newbie Googler的意思),甚至給他們發一種特殊的螺旋槳帽子,其寓意在於告訴他們,小屁孩要謙虛,要向偉大的Google學習,將來才可以飛黃騰達。
這其實是非常錯誤的作法,因為它完全不尊重新員工早已具備的背景知識,把自己的地位強加於他們頭上。並不是你說"新的起跑線"就真的可以把人的過去都抹殺了的。新人不了解你們的代碼結構和工程方式,並不等於你們的方式就會先進一些。Google裏面真的有很多值得學習的東西嗎?學校的教育真的一文不值嗎?其實恰恰相反。我可以坦然的說,我從自己的教授身上學會了最精髓的知識,而從Google得到的,只是一些很膚淺的,死記硬背就可以掌握的技能,而且其中有挺多其實是糟粕。我在Google做出的所有創新成果,全都是從學校獲得的精髓知識的衍生物。很多PhD學生鄙視Google,就是因為Google不但自己技術平庸,反倒喜歡把自己包裝成最先進的,超越其它公司和學校的,並且囂張的期望別人向他們"學習"。
一個真正尊重人才的公司會去了解,尊重和發揮新人從外界帶來的特殊技能,施展他們特有的長處,而不是一味期望他們向自己"學習"。只有這樣,我們才能保持這些銳利武器的棱角,在激烈的競爭中讓自己立於不敗之地。如果你一味的讓新人"學習",而無視他們特有的長處,最後就不免淪為平庸。
不要以老師自居,分清"學習"和"了解"
如上文所說,IT行業的很多所謂"知識",只不過是一些奇技淫巧,用以繞過前人設計上的失誤。所以遇到別人不知道一些東西的時候,請不要以為你"教會"了別人什麽東西,不要以為自己可以當老師了。以老師自居,使用一些像"跟我學"一類的語言,其實是一種居高臨下,不尊重人的行為。
人們很喜歡在獲得了信息的時候用"學習"這個詞,然而我覺得這個詞被濫用了。我們應該分清兩種情況:"學習"和"了解"。前者指你通過別人的指點和自己的理解,獲得了精髓的,不能輕易制造出來的知識。後者只是指你"了解"了原來不知道的一些事情。舉個例子,如果有人把一件物品放在了某個你不知道的地方,你找不到,問他,然後他告訴你了。這種信息的獲取,顯然不叫"學習",這種信息也不叫做"知識"。
然而,IT行業很多時候所謂的"學習",就是類似這種情況。比如,有人寫了一些代碼,設計了一些框架模塊。有人不知道怎麽用,然後有人告訴他了。很多人把這種情況稱為"學習",這其實是對人的不尊重。這跟有人告訴你他把東西放在哪裏了,是同樣性質的。這樣的代碼和設計,我也可以做,甚至做得更好,憑什麽你說我在向你學習呢?我只是了解了一下而已。
所謂學習,必須是更加高級的知識和技能,必須有一種"有收獲","有提高"的感覺。簡單的信息獲取不能叫做"學習",只能叫做"了解"。分清"了解"和"學習",不以老師自居,是尊重人的一個重要表現。
明確自己的要求,不要使用指責的語氣
有些人很怪異,他根本沒告訴過你他想要什麽,有什麽特別的要求,可他潛意識裏假設已經告訴你了。到了後來,他發現你的作法不符合要求,於是嚴厲指責你沒有按照他"心目中的要求"辦事。這種現象不止限於程序員,而且包括日常生活中的普通人。舉個例子,我媽就是這種人的典型,所以我以前在家生活經常很辛苦。她心目中有一套"正確"的做事方式,如果你沒猜出來就會挨罵。你為了避免挨罵,幹脆什麽事都不要做,然後她又會說你懶,所以你就左右不是人 :)
IT公司裏面也有挺多這樣的人,他們假設有些信息他已經告訴你了,而其實根本沒告訴你。到了後來,他們開始指責你沒有按照要求做事。有些極其奇葩的公司,裏面的程序員不但喜歡以老師自居,而且他們"傳授"你"知識"的主要方式是指責。他們事先不告訴你任何規則,然後只在你違反的時候來責備你。我曾經在這樣一個公司待過,名字就不提了。
現在舉一個具體的場景例子:
A: 你push到master了?
B: 是啊?怎麽了?
A: 不準push到master!只能用pull request!
B: 可是你們之前沒告訴過我啊……
A: 現在你知道了?!
註意到了嗎?這不是一個技術問題,而是一個禮節(etiquette)問題。你沒有事先告訴別人一些規則,就不該用怪罪的語氣來對人說話,況且你的規則還不一定總是對的。所以我現在提醒各位IT公司,在技術上的某些特殊要求必須事先提出來,確保程序員知道並且理解。如果沒有事先提出,就不要怪別人沒按要求做,因為這是非常傷害人自尊的作法。其實,在任何時候都不應該使用指責的語氣,它不但對解決問題沒有任何正面作用,而且會惡化人際關系,最終導致更加嚴重的後果。
程序員的工作量不可用時間衡量
很多IT公司管理層不懂得如何估算程序員的工作量,所以用他們坐在自己位置上工作的時間來估算。如果你能力很強,在很短的時間內把最困難的問題解決了,接下來他們不會讓你閑著,而會讓你做另外一些很低級的活。這是很不合理的作法。打個比方,能力強的員工就像一輛F1賽車,馬力和速度是其他人的幾十倍。當然,普通人需要很長時間才能解決,甚至根本沒法解決的問題,到他手裏很快就化解掉了。這就像一輛F1賽車,眨眼工夫就跑完了別人需要很久的路程。如果你用時間來衡量工作量,那麽這輛賽車跑完全程只需要很短時間,所以你算出來的工作量就比普通車子小很多。你能因此說賽車工作不夠努力,要他快馬再加鞭嗎?這顯然是不對的。
物理定律是這樣:能量 = 功率 x 時間。工作量也應該是同樣的計算方法。英明的,真正理解程序員的公司,就不會指望高水平的程序員不停地工作。高水平程序員由於經常能夠另辟蹊徑,一個就可以抵好幾個甚至幾十個普通程序員。他們處理的問題比常人的困難很多,費腦力多很多,當然他們需要更好的休息,保養,娛樂,…… 如果你讓高水平的程序員太忙了,一刻都不停著,有趣有挑戰性的事情做完了就讓他們做一些低級無聊的事情,他們悟出這個道理之後,就會故意放慢速度,有時候明明很快做完了也會說沒做完。與其這樣,不如只期望他們工作短一點的時間,把事情做完就可以。
當然這並不是說初級的程序員就應該過量工作。編程是一項艱苦的腦力活動,超時超量的工作再加上壓力,只會帶來效率的低下,質量的降低。
不要讓其他人修補自己的BUG
這個我已經在一篇專門的文章裏討論過。讓一個程序員修補另外一個程序員的BUG,不但是效率低下,而且是不尊重程序員個人價值的作法,應該盡量避免。
在軟件行業,經常看到有的公司管理讓一個人修補另一個人代碼裏的BUG。有時候有人寫了一段代碼,扔出來不管了,然後公司管理讓其他工程師來修復它。我想告訴你們,這種方法會很失敗。
首先,讓一個人修復另一個人的BUG,是不尊重工程師個人技術的表現。久而久之會降低工程師的工作積極性,以至於失去有價值的員工。代碼是人用心寫出來的作品,就像藝術家的作品一樣,它的質量牽掛著一個人的人格和尊嚴。如果一個人A寫了代碼,自己都不想修復裏面的BUG,那說明A自己都認為他自己的代碼是垃圾,不可救藥。如果讓另一個人B來修復A代碼裏的BUG,就相當於是讓B來收拾其他人丟下的垃圾。可想而知,B在公司的眼裏是什麽樣的地位,受到什麽樣的尊重。
其次,讓一個人修復另一個人的BUG,是效率非常低下的作法。每個人都有自己寫代碼的風格和技巧,代碼裏面包含了一個人的思維方式。人很難不經解釋理解別人的思想,所以不管這兩人的編程技術高下,都會比較難理解。不能理解別人的代碼,不能說明這人編程技術的任何方面。所以讓一個人修補另一個人的BUG,無論這人技術多麽高明,都會導致效率低下。有時候技術越是高的人,修補別人的BUG效率越是低,因為這人根本就寫不出來如此糟糕的代碼,所以他無法理解,覺得還不如推翻重寫一遍。
當我在大學裏做程序設計課程助教的時候,我發現如果學生的代碼出了問題,你基本是沒法簡單的幫他們修復的。我的水平顯然比學生的高出許多,然而我卻經常根本看不懂,也不想看他們的代碼,更不要說修復裏面的BUG。就像上面提到的,有些人自己根本不知道自己在寫什麽,做出一堆垃圾來。看這樣的代碼跟吃屎的感覺差不多。對於這樣的代碼,你只能跟他們說這是不正確的。至於為什麽不正確,你只能讓他們自己去改,或者建議他們推翻重寫。也許你能指出大致的方向和思路,然而深入到具體的細節卻是不可能的,而且不應該是你的職責。這就是我的教授告訴我的做法:如果代碼不能運行,直接打一個叉,不用解釋,不用推敲,等他們自己把程序改好,或者實在沒辦法,來office hours找你,向你解釋他們的思想。
如果你明白我在說什麽,從今天起就對自己的代碼負起責任來,不要再讓其它人修補自己的BUG,不要再修補其他人的BUG。如果有人離開公司,必須要有人修補他遺留下來的BUG,那麽說話應該特別特別的小心。你必須指出需要他幫忙的特殊原因,強調這件事本來不是他的錯,本來是不應該他來做的,但是有人走了,沒有辦法,並且誠懇的為此類事情的發生表示歉意。只有這樣,程序員才會心甘情願的在這種特殊關頭,修補另外一個人的BUG。
不要嚷著要別人寫測試
在很多程序員的腦子裏,所謂的"流程"和"測試",比真正解決問題的代碼還重要。他們跟你說起這些,那真的叫正兒八經,義正言辭啊!所以有時候你很迷惑,這些人除了遵守這些按部就班的規矩,還知道些什麽。大概沒有能力的人都喜歡追究各種規矩吧,這樣可以顯得自己"沒有功勞有苦勞"。這些人自己寫的代碼很平庸,不知道如何簡單有效地解決困難的問題,卻喜歡在別人提交代碼讓他review的時候叫喊:"測試很重要!覆蓋很重要!你要再加一些測試才能通過我的review!"
本來code review是讓他們幫忙發現可能存在的問題,有些人卻仿佛把它作為了評判(judge)其他人能力,經驗,甚至智商的機會。他們根本不明白別人代碼的實質價值,就知道以一些表面現象來判斷。我在Google實習,最後提交了質量和難度都非常高的代碼,然而一些完全沒能力寫出這樣代碼的人,不但沒表示出最基本的肯定,反而發出沈悶的咆哮:"快——寫——測——試!" 你覺得我會高興嗎?
我並不否認測試的用處,然而很多人提起這些事情時候,語氣和態度是非常不尊重,讓人反感的。這些人不但沒有為解決問題作出任何實質貢獻,當有人提交解決方案的時候,他們沒有表達對真正做出貢獻的人的尊重和肯定,反而指責別人沒寫測試。好像比他高明的人解決了問題,他反倒才是那個有發言權的,可以評判你的代碼質量似的:"我管你代碼寫得多好,我完全沒能力寫出來,但你沒寫測試就是不夠專業。你懂不懂測試的重要性啊,還做程序員!"
人際交往的問題經常不在於你說了什麽,而在於你是怎麽說的。所以我的意思並不是說你不該建議寫測試,然而建議就該有建議的語氣和態度。因為你沒有做實際的工作,所以一些禮貌用語,比如"請","可不可以"……是必須的。經常有人說話不註意語氣和態度,讓人反感,卻以自己是工程師,不善於跟人說話為借口。永遠要記住,你沒有做事,說話就應該委婉,切不可使用光禿禿的祈使句,說得好像這事別人非做不可,不做就是不懂規矩一樣。
禮貌的語言,跟人的職業完全沒有關系。身為工程師,完全不能作為說話不禮貌的借口。
關於Git的禮節
Git是現在最流行的代碼版本控制工具。用外行話說,Git就是一個代碼的"倉庫"或者"保管",這樣很多人修改了代碼之後,可以知道是誰改了哪一塊。其實不管什麽工具,不管是編輯器,程序語言,還是版本控制工具,比起程序員的核心思想來,都是次要的東西,都是起輔助作用的。可是Git這工具似乎特別惹人惱火。
Git並不像很多人吹噓的那麽好用,其中有明顯的蹩腳設計。跟Unix的傳統一脈相承,Git沒有一個良好的包裝,設計者把自己的內部實現細節無情地泄露給了用戶,讓用戶需要琢磨者設計者內部到底怎麽實現的,否則很多時候不知道該怎麽辦。用戶被迫需要記住挺多稀奇古怪的命令,而且命令行的設計也不怎麽合理,有時候你需要加-f之類的參數,各個參數的位置可能不一致,而且加了還不一定能起到你期望的效果。各種奇怪的現象,比如"head detached",都強迫用戶去了解它內部是怎麽設計的。隨著Git版本的更新,新的功能和命令不斷地增加,後來你終於看到命令行裏出現了foreach,才發現它的命令行就快變成一個(劣質的)程序語言。如果你了解ydiff的設計思想,就會發現Git之類基於文本的版本控制工具,其實屬於古代的東西。然而很多人把Git奉為神聖,就因為它是Linus Torvalds設計的。
Git最讓人惱火的地方並不是它用起來麻煩,而是它的"資深用戶"們居高臨下的態度給你造成的心理陰影。好些人因為自己"精通Git"就以為高人一等,擺出一副專家的態度。隨著用戶的增加,Git最初的設計越來越被發現不夠用,所以一些約定俗成的規則似乎越來越多,可以寫成一本書!跟Unix的傳統一脈相承,Git給你很多可以把自己套牢的"機制",到時候出了問題就怪你自己不知道。所以你就經常聽有人煞有介事的說:"並不是Git允許你這麽做,你就可以這麽做的!Unix的哲學是不阻止傻人做傻事……" 如果你提交代碼時不知道Git用戶一些約定俗成的規則,就會有人嚷嚷:"rebase了再提交!" "不要push到master!" "不要merge!" "squash commits!" 如果你不會用git submodule之類的東西,有人可能還會鄙視你,說:"你應該知道這些!"
打個比方,這樣的嚷嚷給人的感覺是,你得了奧運會金牌之後,把練習用的器材還回到器材保管科,結果管理員對你大吼:"這個放這邊!那個放那邊!懂不懂規矩啊你?" 看出來問題了嗎?程序員提交了有高價值的代碼(奧運金牌),結果被一些自認為Git用的很熟的人(器材保管員)厲聲呵斥。
一個尊重程序員的公司文化,就應該把程序員作為運動健將,把程序員的代碼放在尊貴的地位。其它的工具,都應該像器材保管科一樣。我們尊重這些器材保管員,然而如果運動員們不懂你制定的器材擺放規矩,也應該表示出尊重和理解,說話應該和氣有禮貌,不應該騎到他們頭上。所以,對於Git的一些命令和用法,我建議大家向新手介紹時,這樣開場:"你本來不該知道這些的,可是現在我們沒有更好的工具,所以得這樣弄一下……"
寫在最後:歡迎留言討論,加關註,持續更新!
Java編程——怎樣尊重一個程序員