本文作者崔康,分享了Facebook老員工王淮:軟件開房原則與構架。產品中國摘錄如下:
王淮是Facebook的早期員工,也是Facebook內部第二位中國籍工程師和第一位研發經理,曾經負責支付后臺和安全系統,擔任反欺詐部門的技術經理。最近,他分享了一些基本的碼農原則,包括代碼結構、測試重要性等。
正確性是第一要求,他認為“不能解決問題的代碼是耍流氓”。
然后是代碼結構,王淮覺得結構體現邏輯:
第一步,第二步,需要什么數據,需要做什么處理,處理完了結果到那里去,都應該在結構中被很好的體現出來。
結構體現設計。 設計一定要清晰。我的經驗來看,一般來說,在設計結構圖上面的每個組件都對應著自己的類,然后之間或類內部的通信通過成員函數來完成。
他提供一個可借鑒的做法:在一個大的功能實現過程中,給出第一個diff(提交代碼增量)的時候,可以只把結構當做一個diff,里面的函數可以是空的(place holder,作為占位符)。 把數據的生成和界面的展示分開來。典型的可以按照MVC的模式來,但也可以只把數據和UI界面分開來的比較輕量級的做法。結構應當是提交代碼審查的時候最最關注的地方。最需要問的問題就是“這個diff號稱要解決的問題被正確解決了嗎?”
測試的重要性不言而喻。王淮指出:
不論你再正確,還是有錯誤的時候。通過(相對)公正的測試一是來減少自己被繞到代碼里的幾率,二是讓后續的或者別人的改動對自己代碼不經意的破壞被最快的展現出來。測試應該把類主要的功能都測一遍。測試也應該把類和其他類最重要的集成部分也測一遍。
對于提交代碼增量的問題,王淮說了幾個需要注意的事項:
Bug修改,無所謂,該多大就多大。一般bug fix不會超過100行。超過的要特別重視,想想究竟是什么原因造成。會不會是當初設計的問題。一個diff,原則上不應該超過200-300行修改。但多了怎么辦,把一個diff變成多個。
每個diff應該只做一件事情。每個diff盡可少的做一個改動。這樣可以盡可能的方便自己的管理(學會用git branch),和方便審閱者的代碼審查。如果diff越集中做一件事,審查代碼的人需要越短的時間來審查做出高質量的,整體效率越高。
一個功能超過一屏,則將其分割。
面向對象還是面向函數,王淮指出,Java本身就是面向對象,所以這個問題不大。但千萬不要出現披著面向對象的外皮,在類里面寫超長的面向函數的處理。這種情況下,盡可能的分流成輔助函數。
關于代碼規范,他舉了一些簡單的例子:比如文件名,變量或函數名的命名規范,分行的前置空2個空格或4個;每行的字數(不應超過80字符);如何使用public/private/protected;用左右括號的原則;空行的使用;文件和代碼comments的位置 (比如,代碼注釋只能單獨成行);對“// TODO:”的使用規范;宏、常量的使用。這里沒有特別的哪一種樣式一定更對,但是需要有一個大家統一的指南,一起遵守,讓整體的代碼有統一的風格和標準。最大的好處就是有利于可讀性,可讀性的好壞決定著維護成本。
注釋應當簡潔但充分。有些人覺得代碼應該自說名。王淮不大同意,代碼是實現細節,適當的在意圖上給予說明,可以大幅度的減少讀代碼的人的煩惱。
代碼審查越來越受到重視,王淮指出:
作為審查者,一定要讀懂diff;所有被接受的diff必須是在讀懂的前提下。做審查者的人要有“將來如果這些代碼線上出問題,我要幫助支持”的心理準備。
代碼審查應該被每個工程師當做工作的重要一部分。
應當在24小時內給回復,這應當變成共識。
感覺有問題的代碼,一定要在相應的行上做出評論 (inline comments),以讓作者明白問題所在。
盡可能把對修改的所有意見一次性給出,減少來來回回的次數。比較復雜的建議審查者主動找代碼作者來進行線下溝通,達成一致。
一般的diff,來回次數不宜超過3次;如果超過3次,想想看,是不是diff 太大,太復雜了。
說到代碼審查,thoughtbot公司最近在github上發布了自己的代碼審查原則,其中幾個值得關注的要點包括:
接受這樣的現實:很多編程上的主張都是一種個人觀點。應該討論它們的利與弊,提出你的傾向觀點,迅速地達成一種解決方案。
提問,而不是命令。(“把這個變量改成:user_id,你覺得如何?”)
請求給予說明。(“我不明白。你能解釋一下嗎?”)
避免代碼的歸屬之爭。(“我的”,“不是我的”,“你的”)
避免使用一些會被認為是有關人身特征的詞語。(“笨蛋”,“愚蠢”)要把所有人都看作是有魅力的、聰明的、善意的。
要明確。要記著并不是每個人都能理解你的意圖。
要謙虛。(“我不能確定——我們來分析一下。”)
不要用夸張修辭語。(“總是”,“從不”,“永遠”,“毫無…”)
不要諷刺。
展現真實的你。如果你不是幽默型的人,不喜歡使用一些表情符號或動畫gif圖,不要勉強。如果你是這種人,請自信的發揮。
如果有太多的“我不理解”或“另一種方案:”的評論,請專門針對這個人進行交流。可以把你們線下的交流總結成一個帖子附在后面。
對審查者的建議表示感激。(“謝謝提醒。我會把它改正。”)
理解審查是對事不對人。審查的是你的代碼,而不是你。
解釋為什么代碼寫成這樣。(“因為xxx原因我才寫成這樣。如果我把這個類/文件/方法/變量改個名會更清晰些嗎?”)
整理所作的改動,在以后的迭代中重構它們。
在做修改的版本上注明代碼審查的鏈接。
push提交要基于最早的一輪反饋,并形成一個獨立的分支。等這個分支上的任務完全完成了再合并。這讓審查者能夠根據早先的反饋找到你的單獨的更新。
努力站在審查者的立場上理解。
爭取回復每個評論。
直到最后一個人退出登錄后再合并分支。
直到持續集成測試(TDDium, TravisCI,等)告訴你這個分支的測試套件通過后再合并分支。