ZKIZ Archives


如何管理飛揚跋扈的技術人員

http://new.iheima.com/detail/2014/0403/60150.html

開發是一切——何時寫文檔

對於技術管理來說,很多公司會非常注重文檔。雖然開發的結果是代碼,但對於管理來說,代碼往往難以閱讀,也很少有人擅長接手別人的系統。為了讓代碼不至於被丟棄,公司管理人員就祭起文檔這個法寶。我認為文檔是很重要的,但也發現這些文檔中很典型地存在幾個問題:文檔和代碼不同步;文檔的可讀性差,需要的文檔沒寫,不需要的文檔寫了一大堆;文檔和代碼脫節,文檔很多,開發出來的成果很少。

我們應該何時寫什麼文檔,這是需要有嚴格定義,並且有檢查過程的,而不是任由大家自然發展就可以完善的。代碼的編寫需要按不同類型,定義好在各個階段中所需要完成的部分。

設計類文檔—— 這類文檔往往在項目、模塊啟動的時候,大家都會想到要去寫,作為討論和最後決議的成果,顯然是很自然的。然而在項目進入開發之後,碰到實際問題時,往往就不能完全按照設計的初衷去做了,所以通常設計文檔就在這個時候和代碼脫離了聯繫。但有一點是絕對可以做的,就是在重構的時候,按照現有狀況,重新增加重構前的系統狀況說明,然後再添加上重構後的設計。這樣就把重構的設計和文檔的更新結合到一起了。

API(應用編程接口)文檔——現代軟件都希望能提高重用的程度,因此很多程序員都會自己構造自己的業務API,以便在之後的開發中使用。而這種業務API,也是很多分工合作的基礎。這種代碼的說明,會直接影響日常的開發,因此非常有必要保證和代碼的高度一致性。

使用文檔—— 一般來說,一個軟件的使用文檔必須包含以下幾個:《產品版本說明》、《產品安裝和部署文檔》、《產品使用教程以及例程》、《產品FAQ文檔》。這裡面的《產品版本說明》應該在每次發版的時候,作為發佈流程的一個固有環節來設計。《產品使用教程以及例程》是我認為所有文檔中,最值得花大力氣去寫好的。《產品安裝和部署文檔》內容越少越好,應該讓安裝部署儘量智能化、自動化。

瞭解什麼是軟件架構

瞭解軟件架構的範疇,才能有針對性地去把握軟件開發中的風險,從而管理好軟件開發的過程。簡單來說,軟件架構就是應對需求所產生的「一系列決定」。軟件會根據這些決定來開發。根據軟件需要應對的需求,軟件架構一般包含以下幾個部分。

邏輯架構 主要是為了明確「功能性需求」而做的設計,針對需求以及需求變化作為架構目標所做出的關於代碼之間的劃分、耦合、關聯的決定。採用合理的邏輯架構,將會大大降低需求變更對開發的延遲作用。邏輯架構最直接指導代碼中互相耦合的情況,仔細設計好耦合的規則,會讓後續開發事半功倍。

運行時架構 運行時架構是為了滿足運行期的質量需求,所做出的關於對象行文、進程結構、通信協議、數據結構等方面的決定。運行架構一旦確定,等於大部分的「實現」代碼都確定了,設計有足夠擴展性和可用性的運行架構,可以為後續工作節省時間,也降低了系統在運行期對開發工作的干擾。

開發架構 為了滿足開發時的需求所做的決定,主要是軟件根據分工開發、測試驗證流程等需求劃分的軟件層次和區域以及各種接口設計,也包含使用的軟件包、組件庫、開發工具,以及編譯構建的方法。一個好的開發架構,可以讓溝通成本降低,開發速度提高。

部署架構 現代軟件系統,基本上都包括了客戶端和服務端程序,如何快速、高效、穩定地部署和發佈這些程序,如網絡機房的分佈、服務器硬件的搭配、監控和維護工具軟件的安裝、開發測試網絡和運營網絡的設置。可以獲得安全性的配置,良好的部署能力,能推動軟件進行更頻繁、更全面的測試,從而提高軟件質量和開發效率。

數據架構 數據是軟件項目的核心財富,關於數據的結構,數據的存放、備份、傳輸會直接影響到運行性能、業務功能、部署、安全等需求。在面向對象的開發模式下,數據到對象的ORM架構也是很重要的設計。一個完整的數據架構包括了數據流圖、數據字典、ORM結構(如果需要的話)、數據索引和備份機制等幾個方面。

何時以及如何評審

相信大部分公司都有評審這個環節,評審可以包括方案評審、代碼評審、項目專項議題的評審,比如對存留Bug的處理評審等。而這些評審,常常會變成一個挑毛病的會議。要解決評審給產品帶來的負面影響,同時發揮這個活動的優點,我們需要關注以下幾個方面。

評審由誰發起 相對比較好的是,由負責此項目的「領導」來召集人員評審,並且一定要有負責開發的人員參加評審。參與評審的受邀請人員可能會與方案提交者就一些問題有分歧,但提交者有最終決定權。要把權力給有能力承擔它的人。這樣做可以讓「防止風險」的一部分人和「注重效率」的開發人員形成平等的意見交換。

什麼時候做評審 應該在每個迭代、每個較大的版本開工前,或者僅僅是某個認為比較重要的決定做出前,都來一次簡短的評審。如果開始時只是做一個DEMO,那麼需要評審的東西也比較少,而隨著不斷的開發,評審也能遍歷所有的開發。

做評審的方法 真正對項目有幫助的,是瞭解項目的需求,分析面臨的難點,思考方案為何這樣做,提出自己的解決方案,給項目開發者以建議和啟發。多說「我建議這樣解決這個問題」,而不要僅僅去說「這樣做可能有問題,應該添補這樣的功能」。以建設性的心態和思路去做評審,而不是以找問題的思路去做,這就是兩種做法的最大區別。

分層開發,盡快運行

為了降低軟件耦合給開發帶來的負面影響,正確的做法是要高度重視軟件開發方法,從代碼風格、軟件架構、設計模式、開發模式方面來提高水平。其中一個最簡單有效的做法,就是分層。在經典的架構模式中,分層模式幾乎是所有模式的基本模式:把代碼按照你所需的範圍劃分層次,然後規定層次之間的耦合接口,層次之間只可單向依賴,而且儘量減少跨層耦合。劃分層次的範圍,由你的開發團隊水平和項目的複雜程度決定。

非功能需求決定成敗

世界上類似的項目非常多,但成功的佔少數,失敗的佔多數,這種現象的背後有一個重要的原因,就是非功能需求。非功能需求具體包括:軟件開發效率的相關需求,比如代碼結構、代碼風格、內容開發工具、自動構建部署工具;軟件的質量穩定性的需求,如測試方面的需求,產品結構對於缺陷的防範,代碼質量;軟件的運行承載力需求,包括可用性、容災性、可維護性、承載力、運行性能和成本需求;軟件的信息蒐集方面的需求,如故障上報、數據統計和挖掘。

如何才能做好這些非功能需求呢?

首先是在項目成本規劃時,分配足夠多的資源,比如人力和時間,去做好這個事情;其次是要儘量合理地規劃和設計這些非功能需求,既不能貪多求全,也不能無所作為。

追求代碼質量

代碼質量不高帶來的危害包括人員流動後沒法接手、Bug頻繁出現、效率問題難以定位、開發速度慢等。

什麼樣的代碼才叫高質量的代碼?代碼質量存在一個唯一標準,就是可閱讀性。可讀性好的代碼,結構通常更簡單清晰,Bug也少;更多人願意去閱讀的代碼,也會有更多的機會去改正Bug以及其他的缺陷。可讀性好,也意味著你能更簡單地去找到改進性能的方法,減少修改代碼帶來的風險。

提高代碼質量的手段,最簡單的兩條,一是執行代碼規範,二是進行代碼評審。除了規範制定和評審外,組織學習代碼質量的知識,提倡並獎勵高質量代碼的人員,也是提高代碼質量的有效手段。

搭好測試這個安全網

單元測試是最原始的工程概念之一。單元測試對於互聯網應用來說,一般會有一個困難,就是需要大量的「腳手架」,比如為了測試數據庫操作,必須要有一段代碼 「重置」數據庫的狀態;為了測試網絡打包解包,則需要用一個程序向某個網絡端口發數據。而準備這些測試工具代碼的時間往往會比較長,需要有足夠的耐心去做,但一旦做好了,往往能讓開發風險大大降低。

對於單元測試,我認為最少應該覆蓋所有正確的路徑,以及重點防禦的錯誤路徑。覆蓋了這些重點關注的地方之後,放手重構代碼就很方便了。

單元測試應該是屬於代碼的一部分,和源代碼一起存放。自動構建時也應該進行檢查輸出結果。提交代碼時都會自動運行單元測試,當「版本樹」需要合併「分支」 時,單元測試尤為重要,而最重要的是在分支上建立的單元測試。這些測試會大大加強系統的穩定性,因為檢驗了「合併」功能產生的代碼—這些代碼是最容易出錯的。

自己掌控開發方向

開發工作往往被需求變化「牽著鼻子走」,需求往往會有很多來源:產品策劃的想法、老闆的意見、用戶的反饋、數據統計的結論等。提出的各種需求,往往會對開發團隊造成很大壓力。這些問題都需要我們對需求做出有效的管理。然而我們應該如何去蒐集、記錄、過濾、實現這些需求呢?

我們需要很好地蒐集記錄需求。有的團隊會設立兩面故事牆,任何方面的需求,都可以減縮成一個故事,寫到一張便簽紙上,貼到故事牆上,專人處理,而不會石沉大海。

有的公司會試圖把這個事情用電子化流程來做,但電子化流程有個顯著的缺點,就是為了更多地自動化處理,會加入大量的字段,對於故事這種還未謹慎定義過的東西,要認真填寫太多的資料,無疑會給使用者造成額外的負擔。

告別救火隊員

在產品進入運營期間,最牛的程序員似乎總是在充當救火員,各種各樣的突發事件、棘手問題中,我們的「高手」往往疲於奔命,永遠都在做一些補救的措施。有經驗的人員一直沒空做開發,因此大量的代碼由那些水平較差的人來完成,反過來埋下了更多的問題。然而,如果不是忙著亡羊補牢,我們的資深程序員就可以把更多的精力放在開發上,這些有經驗的程序員所生產的代碼,又會進一步降低出故障的概率,這才是走向良性循環的方法。

為了減少運營期間的壓力,在系統設計時,就要特別注意關於可維護性的非功能需求。運營事故當中,因為部署錯誤所導致的佔很大一部分,因此降低部署錯誤需要做到:全代碼包發佈,每個發佈版本要包含所有的可執行文件;所有的服務器上部署的配置文件和數據文件都必須做到完全一致,降低更新文件的複雜度。本機IP地址應該用代碼從網卡上直接讀取,但應該提供可以配置的選擇,預備多個IP的服務器使用;只使用命令行方式來啟動不同功能,如選擇配置文件路徑、輸入不同功能進程或服務器的配置;程序支持關閉、重載配置這兩個信號。在處理這兩個信號時,都不應該讓使用者感覺突然「掉線」;開發用於安全關閉程序、重載配置的腳本或功能;開發用戶自動重啟所部署進程的腳本,以及配置開機自動啟動所部署的進程;每個進程都不應該強行鎖定某資源,必須要能做到一份安裝複製多進程並行運行等。

每天發版

如果你想知道項目每一天的開發進度,你就必須要做到每天發版,測試每天的工作進度,如果要順利地每天發版,就必須建立一個持續集成的系統。一般來說持續集成系統會有以下的先後步驟:單元測試—自動構建—自動部署—集成測試—自動發佈。

單元測試關鍵是要能堅持覆蓋所有新加入的代碼;自動構建是由構建腳本、構建服務器、持續集成系統幾部分組成。

對於美術、產品或者別的非技術人員,添加的數據往往也需要有自動部署的工具,而且因為通常他們產生的文件比較大,每次的全體打包然後覆蓋,可能會非常沒效率。雖然事情要做得完美不是很容易,但絕對是物有所值。

版本列車

我們時常只是對技術工作有版本管理的過程,而對於其他環節,常常停留在最原始的狀態。我們需要在整個項目開發的每個環節,都進行合理的項目管理。在多個項目的經驗積累之後,提出了全過程的項目管理的概念:版本列車。

版本列車的含義是按照項目的工作流程,為每個有產出的環節都定義一個版本「車廂」,然後按照工作流程的先後依賴順序,形成一個完整的「版本列車」。第一個工作環節負責版本號,然後在這個版本號之下填充版本內容。當工作完成,此版本的工作內容則帶著版本號進入下一個「車廂」,依此類推。

這樣做的好處是,每個環節的每份產出都可以明確地知道其進度位置,安排在什麼時候做。對於需要提前準備市場推廣或者別的工作部門,有一個非常明確的長期計劃。對於進度管理來說,各個部門也能知道整個項目的當前狀態。

論功行賞(績效評估)

不管是對被評的人,還是對評價別人的來說,績效評估都非常難做。因為很多工作並非能很準確地列舉出一二三來,工作任務也可能有大量臨時變更。太過主觀會讓人覺得草率;非要去依據可量化的數據,又過於死板和片面。但沒有一個公司敢不做考核,所以說績效評估是「明知山有虎,偏向虎山行」。

績效考核應該重點關注的是做了什麼事,而不是做得怎麼樣。這個讓很多按「結果」管理的老闆很不接受。績效考核應該是推動別人去做某件事的工具。對於已經明確的方法或者子目標,通過這種細化的方式去指導下屬工作。因為是需要事後算賬的,而且是量化的,所以下屬會對這個事情很認真,同時那些不好量化的事情,管理者也很難執行績效考核。所以「去做某些事」,是績效考核最好的目標。

通過考核結果提供正式的工作方法意見。績效考核本身有個反饋的過程,這個反饋的過程應該提供給下屬針對每個具體事情的建議。這種具體地,單獨地,一對一地指導,會提高團隊的穩定性,而且也讓團隊成員獲得「受關注」的感覺,這種感覺是形成高效團隊的重要工具。

考核不能代替目標,不能阻礙目標,而應該是一個溝通工具。目標達成情況是考核的客觀指標,但不應該作為主要績效考核指標。最簡單的績效考核指標就是收入或者利潤率。但這種簡單指標除了在動機上提高下屬的工作熱情外,並沒有從方法和經驗上幫助團隊成員。有效的考核應該是引導下屬按照更有經驗的方法去實現目標。

本文節選自《世界500強互聯網產品經理管理筆記》一書,刊登時內容有修改。作者先後就職於多家互聯網公司,經歷橫跨技術開發、產品設計、團隊管理。通過梳理十年多從業經歷,將大型團隊管理和產品開發領域實踐經驗與讀者分享。電子工業出版社授權刊發。


PermaLink: https://articles.zkiz.com/?id=95036

Next Page

ZKIZ Archives @ 2019