如何提升程序員的生產率 (2)

版權聲明:本文由韓偉原創文章,轉載請註明出處: 
文章原文連接:https://www.qcloud.com/community/article/252mysql

來源:騰雲閣 https://www.qcloud.com/community程序員

 

接上篇 如何提升程序員的生產率 (1)正則表達式

三. 開發過程

溝通

軟件一般都須要通過不少人和不少次的溝通才能生產出來,可是溝通自己又每每會影響軟件的開發速度。這是一段很矛盾的關係。好的溝通方法能下降開發中由於信息不透明致使的開發資源浪費,而又儘可能減小溝通所佔用的精力。算法

1. 需求溝通
在任何一個軟件產品中,如何應對需求的變動,都是相當重要的。需求一直是軟件工做得以成功或者失敗的最重要因素。軟件開發中不少技術和方法都是圍繞着需求來設計的。sql

需求的溝通是需求工做的第一個環節。首先溝通的對象必須是通過挑選的,以避免添加沒必要要的需求混亂。最佳的需求溝通是和用戶或者用戶表明。可是他們每每他們缺少必要的計算機知識。而程序員卻不多有豐富的需求領域的知識。這個鴻溝須要雙方共同去彌補,最重要的作法是,不要光靠口說。shell

程序員應該認真研究需求領域的知識,仔細查看涉及的單據、原型產品、現有工做流程等,並且必須用筆記錄下來,以後再去整理問題,逐條諮詢用戶。在仔細瞭解狀況以前,不宜開始設計總體程序結構。數據庫

當你有必定了解以後,程序員就能夠動手開發一個快速的原型,若是沒有足夠資源,一組界面圖也是很好的。以程序的外觀來幫助用戶來協助設計,是最有力的需求溝通方式之一。不斷的在用戶的幫助下完善這些界面圖,標識上那些可能須要的數據和流程,而後完善,而後再繼續找用戶確認。這個過程在前期可能會至關枯燥,由於那些溝通用的原型也許一點都不會給後續的開發帶來重用。可是能明確需求,倒是對開發最大幫組。編程

2. 需求評審
在需求基本有一個思路以後,須要開始準備需求評審。首先說說評審的材料,通常會是《用例圖》,《領域建模的模型》,用例規約,一些《非功能需求點列表》,甚至軟件的一些通過用戶確認的使用流程和使用界面。設計模式

評審的過程其實遠沒有溝通的過程重要。這個環節主要是給你們一個明確的開端:如今咱們開始作系統設計了。做爲在一些公司內部,需求評審是否獲得經過仍是產品是否能正式開始立項的一個流程。數組

對於評審,不少時候會認爲是,提交評審者來寫報告,而後向一堆專家或者上級來介紹,最後他們提出問題,幸運的話就蓋章承認。但我認爲評審不該該是這樣的。由於若是上級和專家沒有參與項目需求的溝通,他們對項目的瞭解是片面的,靠一些文檔和口頭介紹,必定會以「挑毛病」的姿態出現。而項目自己是否真的可行,卻不負擔真正的責任。

所以我認爲需求評審應該是項目發起者,也就是有權拍板是否是作這個項目的人,來主持這個評審會議,全部的材料由他宣講,疑問由他回答。而其餘的與會者包括專家團和可能的開發團隊,紛紛向他提出問題,以確認真正的可行性。最後主持者在蒐集了衆多意見後,篩選出有意義的意見,改善需求評審的材料,最後拍板是否完成需求評審。這種流程,無疑會要求公司的權力下放,而事實上,若是不是下放,又或者不是老闆親自主持,不少項目最後就輸在了起跑線上。

3. 合做溝通
程序員的溝通講求的是效率,準確是最重要的要素,若是沒法表達「準確」,那就只是在創做,而非溝通。對於須要高度注意力的工做——開發軟件來講,羣體創做的效率實在不夠高。所以提升溝通的「準確」程度是相當重要的效率因數。

開發中的溝通有不少種,其中最重要的一種是需求溝通。特別是做爲技術人員,和策劃、美術的溝通最多。這裏須要重視的就是,和非技術人員溝通,快速原型:如假的界面圖或者手畫稿,填寫了假數據的表格等等,是很重要的溝通手段。不少時候我都會要求把這些溝經過程中的手畫稿掃描保留下來做爲設計文檔的一部分。

另一種溝通是程序員之間的。我一直認爲程序員之間最好的溝通就是「不用溝通」。客戶端和服務端之間調整協議,最好的方法是直接兩個IDE聯調。關於工做任務的接口,最好是定義出接口代碼,而且有單元測試針對接口代碼作處理。固然拉,對於這些接口的設計,仍是須要當面溝通的。

最後要說說會議。我認爲溝通不該該打斷開發。無論是5分鐘仍是1個小時,會議都是一種打斷。而不少會議須要開前準備不少東西,你們試圖用這種方法減小會議的時間,但實際上卻佔用了一樣多的時間。咱們應該關注如何減小會議,以及減小會議對開發的打斷。在午飯的時候開會,我認爲是一個比較好的方式,這種打斷是自然的,不會產生額外的打斷。並且與會者一般不會睡着。午飯時的討論氣氛也會比較好,比起一本正經的會議要活躍的多。

4. 測試溝通
程序員和測試人員之間的溝通必定是密切與頻繁的,雖然咱們有JIRA、BugZilla之類的BUG跟蹤系統,可是每每不少問題仍是要經過口頭的溝通來解決,我認爲和測試人員的溝通關鍵是要分出優先級,對於「可重現」的BUG應該優先溝通,由於能夠很快解決。而那些偶現的問題,可能溝通中一大半都會是猜想,其實能夠先放後,這不表示那些問題不重要,而是應該在肯定能解決的問題都先解決掉,這些時間內測試人員也能夠努力把偶現變成必現。

測試溝通的內容中,對於「名詞」必定要明確,由於咱們會有不少個環境,必需要讓每一個概念有個清晰的表達方法。咱們常常會在「測試」這個詞上犯糊塗,好比「測試版」究竟是哪一個版本,「測試網」又是哪一個網?甚至「測試機」是個PC仍是個手機?這些都必須明確下來。好比用alpha網,beta網就清晰的多。

設計

1. 設計意見蒐集
負責設計方案的人必須負責蒐集設計意見。我不同意方案由下屬設計,意見由下屬向上級蒐集。我認爲方案應該由上級負責,而意見向下屬爭取。若是有一個上級並不負責設計方案,那麼他也不該該有權力去「評審」這個方案。這樣作看起來風險很大,由於咱們不少的上級並不負責具體的「設計」工做,可是對比起上級提供一些不知道該怎麼辦的「指示」,而非要加到方案中去的狀況,可能危害要少的多。

通常來講咱們認爲上級會比下屬的經驗更豐富,若是「無權」評審方案,就必須換一種工做方式:要不本身來作設計,要不採用建議的方式說服下屬——這樣作的好處是能讓上級對本身的概念講解的更清晰、更細緻。不然不足以說服下屬。

2. 設計評審
設計評審的形式每每是一個結論是yes or no的會議。可是實際上要用好這個溝通工具,卻不能怎麼簡單。首先,方案的評審提交者應該是最後決定者,固然應該在一個機制的監督下決定。這個決定就是,對於與會者提出的問題,包括提交者提出的問題,都要有明確的答案。

與會者可能會與提交者就一些問題有分歧,但提交者會有最終決定權。這個機制聽起來很荒謬,好像本身指定法律本身又能夠修改。可是,實際的開發上,若是方案和執行者並不統一,最後執行者仍是會有辦法「規避」一些決策。這裏也涉及一個重要的問題,就是要把權力給有能力承擔他的人。不能想着只是讓某些本身還不放心的人去作方案,而後試圖在評審的時候「把關」了事。

最後把關當然比不把關要好,可是把關要避免成爲扯皮或者陽奉陰違,就必需要權事統一。真正的把技術的知識灌輸到底,這樣會耗費指導者較多的精力,由於須要在提交評審前更多的溝通。固然了,雖然方案又提交者決策,可是,做爲業績考覈和技能評定,上級仍是能夠針對這些設計方案來給出專業評判意見。對於很是頑固者,實際上也有一個「秋後算帳」的「威懾」。

設計方案,也是開發者的一個重要輸出,表明了開發者的技術水平和工做績效。

對於設計方案的組成部分,下面架構設計章節會有更多的討論。

測試

1. 單元測試
單元測試的好處是讓你在設計代碼以前,就要考慮別人如何去使用你的代碼。代碼的可讀性是創建在讀者的前提上的,若是強迫第一個讀者和使用者就是做者本人,那麼在設計API和接口部分,就會考慮更少的耦合。由於強耦合會讓單元測試很是難寫。IDE和單元測試結合是一個很好的實踐,雖然並不能節省多少輸入的代碼量,但起碼會給與一個正式的環境。

每一個細節組成部分的正確性測試,會加強你重構代碼的信心。對於單元測試,我認爲最少應該覆蓋全部正確的路徑,以及重點防護的錯誤路徑。對於覆蓋了這些重點關注的地方以後,放開手重構代碼就很方便了。雖然不少語言能經過編譯就已經消滅了不少的BUG,可是起碼仍是要運行一下。而單元測試能夠分區域的運行完成的代碼,避免的整個系統一塊兒運行,忽然爆發一長隊的錯誤,讓DEBUG工做無從入手。

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

2. 系統測試
系統測試的自動化程度決定了其重要性。系統測試必定要先辦法找到測試的「切入點」,如對WEB系統測試,使用HTTP請求列表做爲測試發起事件。對於WINDOWS測試,則使用窗口消息。對於服務器,使用協議包。必定要想辦法把手工操做「記錄」成可編程控制的操做。第二個重點就是要有辦法用程序鑑別測試目標的輸出,這裏可能會用到正則表達式,詞法分析,圖形辨認等,可是若是一個好的系統設計,在考慮到測試時候,應該設計出儘可能簡單的測試輸出點數據。如一些結構化網絡數據,或者客戶端數據中的模型數據等。

系統測試的環境自動化部署是關鍵,其中測試數據還原也很重要。通常系統測試須要反覆執行——每次發版本都要。而測試結果不少和數據結果有關,所以必定要有辦法把系統的數據(數據庫內容)還原成每次測試的初始狀態。這個在創建系統測試的環境的時候就應該考慮,而且作成每次測試執行前都自動還原數據,不然最後的「斷言」測試極可能會失敗。

3. 壓力測試
咱們必需要作壓力測試。由於咱們要提供有限服務。服務器或者客戶端都應該對系統的最大能力值有一個設定,而後經過壓力測試得到最可靠的數據,用以設定這個值。這樣能保證程序在合理環境下正常運行。
壓力測試能夠經過蒐集、複製產生數據。好比服務器能夠記錄網絡請求包,而後按會話記錄成一個個隊列,最後經過併發一塊兒回訪,就能夠模擬多人同時的狀況。若是還不夠壓力,能夠複製隊列,而後修改一些互斥數據(如用戶ID),產生更大的併發壓力。這種測試每每能很真實的反應狀況,缺點是必需要蒐集必定的用戶操做。可是我以爲公司通常的QA的操做就是很好的複製源。

壓力測試若是用本身構建的壓力數據,須要注意的事項:密度、順序、覆蓋率。有時候須要本身構造壓力數據,我認爲最少應該有幾個可輸入的調控相:每秒併發發起多少請求,每一個請求的間隔時間;每一個請求的順序是否按預約順序排列好(由於有的操做是須要前後次序的),請求包是否覆蓋了系統的全部處理邏輯,而覆蓋的密度比例是否和真實的環境大致相似。如各類協議格式的包,是否按外網的比例來產生。

壓力測試必需要注意專用環境:帶寬、磁盤、硬件、測試數據還原。高速的局域網,最好和辦公網分開,不然會影響工做。磁盤要清空足夠大,不然可能會讓日誌把磁盤填滿。要用專用的測試硬件,以避免形成別的工做數據的破壞——同時也提供了性能指標的硬件基準,這個尤爲重要。壓測的數據包數量巨大,必定會產生巨大的持久性數據,爲了能夠重複操做,這些數據必定要能自動還原。同時也是保證自動化重複壓力測試的須要。

編寫

1. 需求分析
KISS:保持簡單。需求之因此複雜,是由於人的思想難以界定,充滿了是和否的中間地帶。因此第一原則是:只認可肯定是的需求。將來的需求暫時不考慮,在第一批需求完成後,真實的第二批需求就會肯定下來。人類不可能未卜先知,因此不要妄想一開始就能準確的預測需求,只須要把肯定的需求理解清楚,就打下了基礎。以學習的心態去了解需求,不要被固定的合同束縛,才真正能跨過需求的第一關。軟件領域最大的、永恆的挑戰,正是需求變動!

面向對象分析:尋求領域概念。計算機把世界抽象爲0和1的序列,這種方式也影響了程序員。可是世界是複雜而多變的。固定的數據建模已經被證實了沒法很好的應對需求變動,因此真正的方法應該是去先認識世界,對於業務領域中的概念作學習和界定,而後用面向對象的方法去框起來。這樣「對象」和現實世界與0、1之間,就搭起了一我的類能夠理解的橋樑。所以咱們的需求應該從領域模型出發,使用業務領域的名詞做爲系統中對象的名詞,儘可能用對象去「描述」這個領域中的概念,而不是急着去完成一個個概念供使用者交互的「流程」。

需求分析有不少工具,如領域建模。UML中的用例圖和用例規約。針對非功能需求的「場景-決策」表格。還有著名的魯棒圖,能夠轉變成UML的模塊圖。這些都是值得學習的需求分析工具。並且不會太花費時間。

2. 代碼風格
這個方面《編寫可讀性代碼的藝術(ARC)》裏面說的已經很詳細。只須要認真的按照裏面所說的去作就能夠了。

另外有一些慣例,我以爲明確一點的好:

  • 關於英文縮寫命名,爲了簡單,通常只取前三個非元音字母爲好,並且單詞長度超過5個字母的才縮寫。
  • 對於C++這類兼容過程式的語言,若是是過程式的變量或函數,應該採用下劃線鏈接小寫單詞,如arg_num, get_file_name(),若是是和類與對象相關的,包括屬性、方法,就採用JAVA風格的命名,如argNum, getFileName()

3. 代碼重用
理論上代碼重用這是個大話題,不該該放在這麼小的位置來講。可是實際上軟件開發不少地方都涉及重用。因此這裏只提一些我認爲最重要的:能下載到的代碼毫不開發。——事實上不少程序員都以從新發明輪子爲榮,而且都認爲別人的輪子很差用,好比鄙視STL的C程序員比比皆是。我認爲老闆給你的工資不少時候並不包括從新發明輪子,無論你以爲怎樣,學會使用已有的輪子都是一個程序的義務。不然等於浪費老闆的投資,對於本身來講雖然好像技術長進了,可是整個項目都被你脫了後腿。與其你本身去寫STL,不如去認真讀一讀STL源碼,掌握它的內容,而後教更多的程序員去用他。不然我懷疑最後你只能去寫彙編了,那就隨便你了。

代碼重用每每和機器性能有必定衝突,可是在我看來,不多項目由於性能差那麼一點點而掛掉。可是由於代碼開發效率過低,跟不上項目需求變化而掛掉的項目多的多。因此那些只以性能做爲技術水平標杆的程序員,某些時候是項目的毒瘤!

4. 設計範式
過程式:C語言
結構化編程當中,最重要的設計方法是:自頂而下,逐步細化。不管你是否在寫過程式範式的代碼,這個方法都應該遵照,不然必定會出現劃分粒度不一,難以重用的代碼塊。大部分的巨大函數體都是忽略這個原則形成的。

通常來講C語言會要求對一個內存進行操做,而且反應執行結果在其之上。因此一般都會有一個相似g_Env之類的全局變量,用來存放多個過程須要的數據。爲了不多個函數須要反覆的經過不一樣的輸入參數和返回值來「串接」調用,一般都會設計成一塊兒去修改 g_Env變量。

同時也會有一個g_Cfg的全局變量充當配置文件。面向過程的代碼則不多使用全局變量做爲「操做臺」來處理數據,由於都被封裝到對象裏面了。

C語言的回調模式通常經過函數指針來實現,這個幾乎是作框架代碼的最好用的方法。而面向對象則採用多態來取代函數指針,會更安全一些。

對於函數的返回值,通常來講不會用來真正的「返回」某些數據,而是返回的是處理的結果是否正常\異常。而處理結果的數據每每經過輸入參數(指針)來獲得,這個是和麪向對象代碼很大的區別。面向對象的語言通常支持異常,取代了返回值的「錯誤報告」功能,而返回值則真正是一個處理的結果。這樣減小了輸入參數,會讓API更容易使用,符合理解習慣,也更不容易出錯。

整體來講,注意抽象好函數的層次,使用統一的,儘可能少一點的全局變量,使用函數指針實現回調,使用返回值做爲函數的錯誤報告,使用輸入參數,就是過程式C語言的主要特色。

OO:設計模式
對於封裝、多態、繼承的玩法,最後演變成GOF23種設計模式。說到底都是爲了實現幾個主要的原則,其中最關鍵的就是「開閉原則」。這方面的書籍也是汗牛充棟,特別須要關注的是《重構:改善既有代碼的設計》。

面向對象編程方式是如今最利用適應需求變化的一種技術。包括泛型這種靜態化的對象技術。因此不管什麼緣由,都應該掌握必定的這方面知識。

面向對象設計範式的核心點是去描述現實世界的概念,而非用算法和數據去模擬這個世界的運行。由於關注點在概念這種名詞特徵上,因此能夠先初略後精緻的逐步細化設計,正好符合需求變化的特徵。

動態模式:JS/PHP/PYTHON……
動態類型語言以其極致快速的開發效率,容易掌握的語法而聞名。其中最能提升效率的是動態數據類型。減小了大量的聲明、定義和侷限的代碼。甚至減小了大量的數據結構的使用。如PHP裏面全部的數組都是哈希表,而JS/PYTHON裏面的Object就是哈希表。實際上AS3.0也是有相似的特性。更好的利用這些語法糖和數據類型是提升開發效率的關鍵。因此我也反對在這類語言裏面本身從新包裝一套相似C語言的數據結構或者容器類庫,實在是不必。

動態類型語言另一個特色是腳本化解釋運行,不須要維護堆棧,也不須要考慮編譯的定義。甚至還有交互式終端一行行的去命令式運行代碼。把儘可能多的業務邏輯的處理細節「過程」用動態類型語言(腳本)來執行,是提升開發效率的重要手段。若是你比較一下用C語言編寫CGI和PHP比較一下,你就知道效率相差有多少了。

特定領域:SQL/SHELL
SQL這類語言和通常的語言有比較大的設計差異,他更多的設計爲「表示」而非「命令,因此須要另一種思考方式。而這類語言由於和領域結合很緊,因此是強大的領域工具,包括SHELL和AWK這種腳本語言,具有別的語言很是費勁才能實現的功能。在這些領域,儘可能使用這些語言會有事半功倍的功效。

SQL中的函數和存儲過程,是強大的工具,有時候整個統計系統均可以直接在數據庫裏面運行。而不少運維的系統工具,用shell來實現則會簡單高效,由於須要操做的功能是操做系統自己。

函數式:強大的數學表達力
Lisp,schema,erlang這些函數式語言,採用鏈表來描述一切,只須要棧而無需堆,用遞歸代替循環,這些都很符合多核並行運行的要求,並且還能很方便的中斷和恢復程序運行。在業務需求變化較少的,而計算任務比較多的場景,是一種很是強悍的編程工具。對此我瞭解不是不少,可是很但願有機會能用函數式語言作一個東西看看。

構建-集成-部署-測試

版本管理-構建腳本-自動構建-構建包管理:
全部的源代碼都必須進入版本管理;全部的構建、部署、測試腳本也須要進入版本管理,全部的一切都應該進入版本管理。一個構建系統的運行,應該是能夠徹底從版本管理服務器上重建一切的。

Hudson是一個很好的自動構建服務器,可是構建腳本你仍是須要本身去寫。確保你的腳本能夠從零開始構建,而且在全部你可能碰到的平臺上正常構建,如32位和64位系統。

構建出來的軟件包,應該讓hudson這類系統自動發佈給全部相關的人,並且能夠很方便的經過網絡獲取到,如HTTP或者SVN。而且須要保留多個歷史版本以備回滾。

部署腳本-部署環境-自動部署
部署腳本每每是用動態語言寫成,還會帶有數據庫操做等複雜的內容,所以必須也歸入版本管理。部署環境應該是足夠安全並且和生產環境有足夠快速的網絡鏈接的。有了這些保障,才最後有自動部署的可能性。最好就是有一個部署服務器是和生產環境和辦公網絡,都屬於內網(局域網)鏈接的。簡單的自動部署工具必需要運維人員能掌握,而且取消開發人員的使用權限,避免開發人員直接修改線上服務產生的故障。

各種測試-自動測試-結果報告
代碼提交前應該運行完成單元測試,代碼在自動構建以及自動部署後,應該自動運行必定的系統測試腳本,結果放置到構建報告中。

通常來講,測試環境有幾種:開發環境、內測環境、外測環境、運營環境。

在開發環境應該是單元測試的運行環境。內測環境則應該是在自動部署後的其中一個環境,用以和產品人員溝通和驗證基本功能。外測環境應該和運營環境儘可能一致,自動部署後,全部的測試失敗和人員手工測試缺陷,都應該視之爲BUG進入跟蹤系統。並且外測環境應該是運維人員的工做範圍,不該該讓開發人員上去搗鼓。通過了這三層的測試環境,無論是代碼功能仍是部署設置,應該都能自動化的在運營環境上可靠的運行了。

重構

兩頂帽子:加功能、改結構
關於重構有不少經典的書籍能夠參考,好比《重構:改善既有代碼的設計》《重構與模式》。但其中很重要的一點,就是重構的時候禁止添加新的特性,由於會讓代碼在修改的時候陷入複雜的「連鎖」修改,從而讓重構困難增長。同時若是你修改了特性,也須要新的單元測試來保障重構的正確性,這些都是本身攪合本身的作法。而在增長特性的時候最好也不要重構,由於你在努力經過測試的時候,也是在整理和驗證需求。只有需求肯定了,重構的目標纔會清晰。

單元測試的重要性
重構的一個最大的困難,就是怕改的代碼太多,從而出現BUG。可是若是你有一個覆蓋率很高的單元測試集合,你就能夠比較放心的去修改代碼,由於一旦出錯你馬上就能知道。固然有不少時候單元測試並不是萬能,有些狀況單元測試確實沒法覆蓋,或者架設測試自己比較複雜。因此說重構仍是一個比較高風險的動做。測試的工做自己是重構成功的最重要保障。

明確重構目標
不少時候重構起源於某些需求難以加入現有系統,可是若是隻以這個做爲重構目標,每每結果並不是徹底讓人滿意。實際上重構的目標應該是一個對於需求變動的總結以及前瞻。某些時候是以實現某種設計模式做爲重構的目標。而選取的模式就是對於需求分析的結果。重構中目標的選取是相當重要的,這個須要對業務和技術有深刻的理解,從另一個角度看,重構目標和一開始的設計工做是同等的工做。因此說軟件開發的「架構設計」其實是持續在進行的。

加班

加班的緣由:學習、體力活
程序員的加班司空見慣,究其緣由,有兩種,一種是不知道如何實現,另一種是工做量大。

對於第一種狀況,有些人會寫一堆代碼而後調試,發現不對又改。而我建議是應該把「不肯定」的部分,設計一些代碼片斷功能(單元),而後使用單元測試做爲驗證,經過逐步掌握這些功能,最後造成可重用的代碼。這會是最節省時間的方法。

對於第二種狀況,應該多考慮設計一些工具。好比使用一些腳本語言來代替一些數據的體力活,嘗試抽取可重用代碼來簡化邏輯。作這些可能一開始會比較費時間,可是長期來看,倒是能夠節省下大量的加班時間。

實際每一個程序員都知道生命寶貴,並不會有意的拖延工期,除非以爲這個工做實在是不值得去作。因此由於進度緣由致使的強制加班,最後都會被「減班」還回來。損失比不加班還要大。《人件》裏對於這個有詳細的論述,我也不去重複了。

若是是自願性加班,本節會有用。若是是被迫性加班,其實是不管如何不會增長總體的開發效率。因此若是真的要用加班這招,最重要的是變「被迫」爲「自願」。

若是做爲團隊領導者,你看到整個團隊已經能在天天6小時內高效的工做,再強迫加班最後只能是下降開發速度。緣由再也不細速,能夠參考《人件》。所以,如何讓團隊加班的方法,應該改爲如何讓團隊不用加班的思考。改進開發工具,提升開發技術,增強團隊建設,這些都是有效的方法,惟一須要避免的就是如何「強迫」團隊加班。

避免加班的方法:思考設計、學習提升工做效率的方法、在上班時間內加班
根據個人經驗,若是一個程序員一天有6小時都高度注意力的作開發,實際上開發效率已經能夠達到很高,而不少一天工做12小時的程序員,其高度注意力時間每每只有4個小時。因此不加班徹底是可能的,除去別的因數,對於我的來講,避免本身玩死本身是最用的知識。在動手以前先仔細考慮清楚細節,能夠避免後期邏輯BUG的折磨,這種BUG是最難調試的。而學習各類工具以及關注代碼在提升開發效率上的知識,則是另一個重要的手段。所以再次吐槽那些不重視開發效率的程序員,大家輕視面向對象,輕視軟件工程知識,輕視那些對程序性能無關的知識,最後的苦果就是——一生加班!

程序員的狀態起伏

【設計-編碼-調試-總結】的循環
程序員在開發程序的過程當中,每每會經歷以上幾個階段,在編碼階段是狀態的高峯,調試階段開始陷入痛苦,不少時候會跳過總結。整個循環完成後,則是疲憊不堪,注意力沒法集中。所以咱們能夠注意幾個重要的環節,減輕這些壓力。

首先設計階段若是能儘快熱身,直接更專一的深刻細節,則會避免無休止的修改方案,對於開發的指導也會更明確。而編碼環節採用更多的工具和技巧減小體力和腦力的消耗。若是設計階段和編碼階段的工做能關注代碼可讀性和結構,最後的調試每每也不會很是困難,而後爲了獎勵一下本身,能夠寫一點總結。

打破循環形成的心理影響
若是在每一個階段中能儘可能多的融入下一個階段的工做,一樣也能夠起到下降壓力的做用。好比在設計階段就把不少重要的代碼命名工做作了,在編碼的時候就順手解決全部的語法錯誤,調試階段的測試用例就能夠用來做爲工做彙報的材料。

避免疲勞戰術的方案:縮小循環體
在開發的循環中,每一個階段越長,最後的疲勞就會越大,而每一個過程越短,則越容易被接受。因此儘可能在設計階段劃分的細緻一些,能夠明顯的下降後續的工做壓力。縮小開發流程也是敏捷開發模式的重要觀點。這對需求分析、代碼結構、測試技巧都有很高的要求。重視這些知識,就會明顯的下降工做壓力。

四. 架構設計

邏輯架構

邏輯架構主要是爲了明確需求而作的設計。針對需求以及需求變化做爲架構目標。所以邏輯架構在架構設計中,是對於提升程序員生存率最相當重要的一個設計。採用合理的邏輯架構,將會大大下降需求變動對開發的延遲做用。邏輯架構最直接指導代碼中互相耦合的狀況,仔細設計好耦合的規則,會讓後續開發事半功倍。

邏輯架構的經典模式有《POSA》中指出的幾種,其中以分層和微核模式最爲經常使用。MVC和管道過濾器模式則在特定系統中是最優模式。後續基於分佈系統的SoA等架構模式,則可能是創建在分層的基礎上。分層模式能夠按需求關注點來劃分層次,所以能夠安排不一樣經驗水平的程序員分別承擔。微核模式則直接按具體功能劃分代碼,適合水平相差不大的團隊進行功能的並行開發,由於能夠單獨測試。

無論何種邏輯架構,都是把功能-代碼劃分紅多個不一樣的部分。這些部分經過必定的規則互相耦合。這提供了最好的工做量劃分依據,以及互相之間的接口定義。因爲存在接口定義,未來人員流動的時候,也能夠根據接口來理解代碼模塊的邏輯。良好的工做劃分,能極大的下降程序員之間的低效溝通,使得工做能被多我的同時推動,而工做能被同時推動,則是軟件項目能利用好人力資源最直接緣由。

須要指出的是,不少使用非面嚮對象語言的項目,特別是C語言項目,很是蔑視進行邏輯架構設計,由於所謂結構化編程其實約束不多,而你們每每直接忽略掉。這是很是大的問題,致使一些複雜的「過程」最後徹底沒法維護。有不少項目到最後無論如何增長人手,都沒法提升開發速度,就是由於實際那些代碼沒法利用更多的人力,反而增長了更多的溝通成本,架構直接下降了開發效率——往進度落後的項目增長人手,只會讓進度更見落後。

運行架構

運行架構主要是爲了解決運行時的質量需求,主要分爲性能需求和可用性需求。系統的性能需求除了在代碼內部經過算法來提升,每每還要採用緩存和並行的方式來擴展。這就涉及到程序的運行時設計,如數據處理流,多進程間通信,數據的多種格式轉化。對於可用性,實際上也是經過並行熱備的方法來實現,所以運行時的各類控制命令、地址、消息數據流也是運行架構須要考慮的。

運行架構一旦肯定,等於大部分的「實現」代碼肯定了下來,設計一個有足夠擴展性和可用性的運行架構,能夠減小後期爲了擴展性能或提供可用性作更多的代碼。並且也下降了系統在運行期對開發工做的干擾——正在運行系統出了問題,每每是在節假日或休息時間,都會迫使程序員回公司或者上線維護,極大的增長了開發人員的疲勞,一樣會影響項目的進度。所以一開始就考慮可用性和性能擴展問題,而且實際的用代碼去實現好,絕對是一個未雨綢繆的好方法。明智的項目經理會願意在項目前期花多一些資源在這種「非功能性」方面的開發,從而獲得一支士氣水平穩定的開發團隊。

一般運行架構須要至少設計一個能夠水平擴展的接入層或邏輯層,以便經過增長服務器來提升性能擴展。所以也須要預先設計負載均衡的系統,若是是WEB系統,用DNS輪訓是最簡單方便的,若是是遊戲類用戶間交互比較強的,設計一個「目錄服務器」用來提供客戶接入地址是最少須要作的。

可用性架構中,最少要爲邏輯服務器和數據庫(持久層)服務器設計至少一個熱備服務器,在機器斷電或者機房斷網的狀況下,能夠通過程序本身的檢測機制,自動跳轉到備份服務器上處理。通常數據庫服務器mysql採用master-slave用來備用,而邏輯服務器則能夠使用目錄服務器來指定備份服務器地址。固然了,若是目錄服務器也須要熱備的話,則須要另一些代碼支持,如客戶端自己就會去屢次嘗試不一樣的目錄服務器。

通常有「架構設計」的系統都會有運行架構的設計,因此我並不認爲須要如何強調其必要性,反而須要強調的是,系統架構設計,遠遠不止是運行架構的設計。

開發架構

開發架構通常用於知足開發時質量需求,和邏輯架構有密切的關係。開發架構定義了源代碼、二進制和發佈包的文件、路徑、負責人的劃分和依賴關係。一個按照固定開發架構設計的系統,能方便的開發出持續集成的各類工具。

開發架構通常的主要呈現形式爲SVN目錄構造方式,或者在makefile、IDE的項目設置文件中。一個軟件一般分紅多個不一樣的「系統」或者「項目」。不少如Eclipse須要每一個項目只存在一個執行入口main(),因此開發架構在這種狀況下同時也收到運行時架構的進程設計限制。

通常來講功能相對獨立的代碼會成爲一個「模塊」或者「系統」(項目),經過提供程序連接接口,如DLL,.a和.h文件,JAR文件,或者SWF文件來提供。這個粒度的劃分有多種標準,如按功能的,按開發者的。可是有一個通用的準則,就是若是已經設計的不一樣「模塊」中都有調用同一個或者相似的代碼塊。這塊代碼就有資格本身成爲一個平行的「模塊」,以便往後修BUG能夠單獨升級。

我的比較喜歡按業務功能的層次來劃分模塊,這樣有利於劃分任務,減小代碼互相影響,最重要的是比較容易讓人理解。可是就必須常常把工具類模塊協商抽取成爲「公共模塊」。

部署架構

部署架構對於持續集成,下降程序員的運營期壓力,有相當重要的做用。一個好的部署架構能夠提升性能和可用性。讓程序員能夠循序漸進的去解決問題。

運行時架構在軟件層面提供性能和可用性。而部署架構考慮的更可能是硬件層面。好比網絡機房的分佈,服務器硬件的搭配,監控和維護工具軟件的安裝。開發測試網絡和運營網絡的設置。關於安全性的配置。

幾個比較明確的經驗是:

  1. 儘可能靠近用戶部署機房
  2. 全部機房間應該有一條專用的局域網鏈路,讓服務器間數據能夠有專用線路可用。
  3. 運營網絡的防火牆對於公網接口設置爲只開啓服務端口,運營和維護端口所有放在局域網線路上。
  4. 開發辦公網絡不能直接和服務器的局域網直接鏈接,下降我的PC被入侵形成的影響。全部運營網絡的服務器都必須限定有限IP的機器去鏈接遠程登陸,而且這些機器須要是LINUX的。
  5. 對於服務器硬件按照磁盤IO密集型、網絡IO密集型、計算密集型、存儲空間大需求型、經濟節省型的分爲5種型號,由業務技術人員仔細選擇。
  6. 在測試、開發、管理等資源要求很小的服務器上,儘可能採用虛擬機,最大化利用硬件,同時減小維護成本。
  7. 對於平常服務器的維護和監控,創建報警和預警機制,如磁盤、帶寬、CPU、特定進程、監聽端口。
  8. 對於機器和帶寬的部署,採用最少可用性保障的策略,就是最少有2份服務器以及2倍預計帶寬需求(或其餘需求)。
  9. 對於部署過程須要的腳本、配置文件、安裝包,必需要有本身獨立的SVN或者文件服務器管理。同時也須要創建「自動化」部署的工具。在這些工具完成以前,不該該正式對外運營。而部署工具自己應該在「外測」環境下通過詳細測試,才更新到正式運營網絡上。

數據架構

數據架構對於任何業務都有很重要的影響。對於用戶產生的數據,架構自己須要容易備份和恢復,數據就是財富,而數據架構是存放財富的方案。對於開發團隊產生的數據,則須要完善和方便的管理工具,便於修改和增長這些數據。

數據架構自己還涉及性能、易用性等多個方面。通常來講分爲使用關係型數據庫和不使用關係型數據庫兩種。可是無論那種,對於數據的備份(熱備)和恢復都是最首要應該考慮的問題。數據的結構過於複雜其實不利於備份和恢復。而不少時候大數據量又產生「分區」需求(分庫分表),這是分佈數據存儲的課題。

對於使用關係型數據的,通常須要依賴數據庫服務器本身的熱備功能和分區功能,或者本身去實現。而後使用ORM軟件來操做這些數據。因此關係型數據不宜作的過於複雜,太多的「外聯」表會讓整件事變得很複雜。
若是不使用關係型數據庫,如今的NoSQL風潮提供了不少可選的方案,這些方案最大的特色就是對於結構複雜的數據有良好的擴展性,對於大數據量也有優秀的擴展功能——重要的是不用你本身去代碼實現。缺點則是可能沒法保證「統一性」。比較實際的觀點是,儘可能少使用關係型數據。雖然它的概念已經深刻人心。

每一個模塊均可以作架構設計

上面的幾個架構,基本包含了整個軟件架構應該涉及的方面。而咱們每每比較重視一些「大項目」的架構設計,而比較忽視一些中小項目的架構設計。實際上大部分項目並不是「大項目」,而大型項目自己也極可能劃分紅更小一點的項目來外包,因此咱們應該對於每一個項目,都以架構設計的觀點去分析和設計,只是不須要陷入文檔的案牘之中就行了。

一些好的架構設計,也能夠在多個模塊和項目中共用。這種共用的好處很是多,一個是能夠節省開發時間,另外也能夠少走之前的彎路。最重要的是若是積累下這種設計的文檔和思想,可讓整個團隊的開發效率都獲得提升。

五. 管理激勵

明確目標

目標管理是現代管理學的一個重要成果。明確團隊的目標,而後讓全部人都理解並認同這個目標,是管理中最重要的工做。只有每一個人明確了目標,纔可能發揮出他的主觀能動性。並且要有明確的目標,團隊成員之間纔可能合做。不然成員之間可能會互相拆臺或者推卸責任。

目標應該是整個團隊的目標,而不該該是隻劃分到我的,由於這樣不利於團隊的整合,而會造成嚴重的我的主義。固然咱們最多見的是團隊中對於目標不明確。

目標應該包括如下內容,才稱得上明確。首先是項目要知足的市場需求,這是項目的願景。其次是項目怎樣才叫作的好的標準,通常是和競爭對手比較的結果。最後是項目目標和我的發展之間的關係。三層目標必須都讓每一個人明確和認同,才能真正激發出團隊的動力來。

市場需求若是你們不承認,就會以爲項目不值得作,這個時候就須要領導者來用數據和事實證實給你們看。

項目優秀的標準,不可無限拔高或者虛無縹緲,明確的競爭對手數據是最好的標準,雖然這個信息一般很難得到,可是這個是團隊中很是有凝聚力的信息。應該儘可能的獲取,而後公佈給團隊。

每一個人和項目成敗的關鍵,則是核心的激勵機制,雖然不少時候開始很難明確到金錢上的獎勵,可是應該起碼提供一個「最好狀況下」的許諾。不少項目以收益分成,或者過程評價來加工資做爲明確的激勵。

主要手段

人在集體中能發揮的做用必然比單我的要大,這是人類做爲羣居動物的天性所決定的。若是你有必定的工做經驗,一定會體會過一個團結的團隊所發揮的良好做用。如何能構造起一個真正的高效的團隊,我認爲最重要的方法是「溝通」。這種溝通必須是全方位的,包括團隊成員之間的私交,他們互相之間在工做能力、人品性格、興趣愛好方面的瞭解。在管理者和團隊之間,對於項目前景、公司情況等一切和團隊切身利益相關的方面的信息,都必須有良好的溝通。若是程序員以爲你在隱瞞些東西,你必定就是在某些方面有所保留。這種猜忌會破壞團隊的造成。因此對於大量看起來是「保密」的信息上面,對團隊儘可能多的公開,是能讓團隊獲得主人翁感受的重要手段。傳統管理方法中不少時候強調公司的信息保密,我的對於團隊的效忠。而這些在高科技開發企業中是行不通的,由於他們就掌握着公司的最大機密——產品開發。

管理者除了對「人」作事,直接作事也必不可少,開發工做有不少方面是在作設計,因此開發工做自己並非所謂的體力活,而是一些精巧的設計工做。除了本身參與開發工做,對於團隊其餘部分的設計工做,特別是其中的重要決策,管理者也須要儘可能多的參與。一方面這種參與能夠培訓團隊成員,另一方面能增強對於項目控制。在決策的過程當中,經過普遍的討論,也是團結團隊的一個手段。固然剛愎自用的處理方法就會產生反效果。

由於程序開發自己是一種高度自律型的工做,因此管理者的「不作」比「作」更重要,並且應該提供不受干擾的環境。在程序員注意高度集中的狀況下,工做效率是最高的。試圖不斷的「參與」開發而打斷程序員的工做,實際上是在下降工做效率。好的管理者應該能讓程序員沉浸在開發工做當中,徹底不去考慮什麼進度報告,工做彙報之類的事情。

由於程序員對於電腦的熟悉,因此常常會把一些別「專業」的行當混合起來交給程序去作。好比寫代碼的同事去處理數據庫,由或者讓程序員同事負責運維服務器和網絡……術業有專精,若是一個程序員專心的作數據庫的工做,他會比同時作其餘幾個事情作的更好。更不用說讓程序員去夾網線搬箱子這些了。整體來講,提供資源支持,下降團隊的「非專業」精力消耗。

人力分工

按照專業領域分工;專業再細分分工;軟件開發團隊應該學習外科醫生的團隊,採用嚴格的分工合做,來下降混亂的溝通。每一個人只負責本身的事情,會作的很是好。所以若是程序能很好的分紅5個模塊,就使用5個程序員,而後爲他們配上專業的祕書,數據庫管理員,測試人員,項目經理,運維人員,IT人員,以及其餘的資源處理人員,好比美術資源處理專員。

關注工做分切點的協議,由於人力分工是提升效率的重要手段,因此人員之間的切分點——協議或者流程,就是很關鍵的東西。客戶端和服務端程序員之間,一般就是直接的通信協議,應該把通信協議變成一種代碼,而後雙方都使用這種代碼。客戶端程序員和美術之間一般也應該使用某種基於軟件工具的格式文件,好比是UI編輯器的結果。處理WEB的團隊每每由美術提供圖片,而後由專人切圖變成HTML,而這個HTML文件就是很好的協議文件。有些數據錄入人員使用JSON格式的文件,或者是某種嚴格定義的EXCEL文件做爲協議文件。

不少團隊喜歡「廣播」方式的溝通,任何一個事情都讓全部人在一個QQ羣裏面看到,或者任何一個事情都抄送郵件給一堆人。實際上這種溝通只會浪費別人的時間,因此管理者應該下降溝通範圍,減小「噪音」。

在《人件》中,提到了高效團隊的形式——膠凍團隊。也就是咱們所說的很是團結並且互相信任的團隊。不少公司會以拓展訓練和部門活動的方式去推進造成團隊互信,這些都是有用的。可是在工做過程當中,更重要的是讓信息共享來打破可能存在的隔膜,給與更大的自由發揮空間讓團隊成員有機會互動,組織團隊成員間一塊兒討論和解決問題。讓團隊成員都感受到受關注,而且提醒他們互相關注。多讓你們一塊兒吃午餐。

績效考覈

績效考覈應該考覈作了什麼事,而不是作的怎麼樣;這個和不少按「結果」管理的老闆很不接受。可是若是你只是想把績效考覈做爲一個發獎金的機制的話,單獨使用獎金考覈機制就能夠了。績效考覈應該是推進別人去作某件事的工具。對於已經明確的方法或者子目標,經過這種細化的方式去指導下屬工做。由於是須要過後算帳的,並且是量化的,因此下屬會對這個事情很認真,同時那些很差量化的事情,管理者也很難執行績效考覈。因此對於「去作某些事」,是績效考覈最好的目標。

經過考覈結果提供正式的工做方法意見。績效考覈自己有個反饋的過程,這個反饋的過程應該提供給下屬針對每一個具體事情的建議。這種具體的,單獨的一對一的指導,會提升團隊的穩定性。並且也讓團隊成員得到「受關注」的感受。這種感受是造成高效團隊的重要工具。

考覈不能代替目標,不能阻礙目標,而應該是一個溝通工具。績效考覈一般會涉及大量的文檔工做,也會有不少量化的工做,可是這些工做,每每不能徹底表明商業目標的完成狀況。因此有些時候只是平白的增長了管理工做量。績效考覈的設定首要須要考慮是不能阻礙團隊目標的實現。不少時候甚至難以覆蓋目標。因此績效考覈應該是成爲一種溝通的工具:定時、定量、定人的交換對於工做方法的意見。

目標達成狀況做爲考覈的客觀指標,但不該該是主要績效考覈指標。最簡單的績效考覈指標就是收入或者利潤率。可是這種簡單指標除了在動機上提升下屬的工做熱情外,並無從方法和經驗上幫助團隊成員。有效的考覈是引導下屬安裝更有經驗的方法去實現目標。

進度掌控

經過測試來了解進度;一切軟件的開發,若是沒法測試,就是沒法瞭解的。沒有人回去經過讀代碼瞭解項目的進度。因此項目自己必須具有常常提供「可測試」的功能。一旦進入測試,項目完成的數量和質量都馬上一目瞭然了。
用提升工做效率和提供資源的方法推動進度,而不是經過加班。加班是最有效的下降工做效率的方法。只有下降自己進度推動的損耗——內耗,改善工做方法——更好的工具和更多的知識,除此以外很難有別的加快進度的手段。可是,你也能夠經過增長更多的資源,好比人力或者機器。如何把資源放在合理的地方,自己是一門學問,本文在上面不少節都有提到如何有效的使用資源——人力和金錢。

慶祝每個進度節點。團隊須要鼓勵,才能保持速度。慶祝自己又是凝聚團隊的一個契機,讓成員以爲在這羣人中間能不斷取得成功,自己就會增長互相合做的意願。若是無故端搞一些團建活動,會讓人以爲厭煩,可是慶祝進度節點,則你們都會認同,可能只是一塊兒吃個飯,可是也是很是有效的一頓飯。

確保公佈進度的目標,而且爭取團隊支持。進度的目標必須能達成共識,「無理」的目標實際上不能成爲目標,團隊今後也會陷入最差的情況——沒有目標。因此進度目標自己須要讓全部人理解而且願意去努力。經過共同的進度目標,來促進團隊中全部人的積極性——那些喜歡偷懶的傢伙也會很差意思。

在重視質量的狀況下推動進度,而且爲質量犧牲必定的進度。項目質量是團隊和我的爲之「自豪」的重要因數。若是你想擁有具有榮譽感的團隊,就須要爲此付出必定代價,可能犧牲一些時間,來得到更好的產品質量,實際上這是個事半功倍的事情。由於產品質量在長期來看,仍是能提供更好的效益的。進度壓力若是形成太多的粗製濫造,會讓後期的團隊愈來愈沒信心遇上進度。最後被迫推倒重來,或者陷入一個「長期的重構」工程中。這些都是缺少遠見致使的問題。

預算制訂

放鬆固定資產的預算,儘早投入固定資產預算。項目初期成本中有很大量的固定資產投入。而這些預算看起來能夠用更便宜可是質量更差的替代品來替換。可是從長期來看,人力成本纔是最重要的大頭。而若是你的固定資產太少,也會難以招聘或者穩住最優秀的那批員工。優質的固定資產不但折舊率更低,並且能讓程序員發揮出更好的功效,直接節省那些高額的人力成本。
收緊人力資源預算,重視10倍效率員工的做用。人員的溝通成本,是全部關於人員的成本中最高昂的。人越少,須要的溝通就越少。不少公司在發展期喜歡快速擴充團隊,但願能抓住機會盡快佔領市場。可是請記住,一個母親懷一個孩子須要10個月,100個母親去懷一個孩子,一樣須要10個月。團隊和項目的進度並不是靠人的數量增長就能加快的。並且更重要的,優秀員工的工做效率最大能夠比通常員工的效率高10倍以上,你只須要給他們5倍的工資,就能節省下另外50%的工資,同時還有不止50%的固定資產投入和其餘費用。少而精的團隊在更方面都比龐大參差不齊的團隊更有效率。
針對風險,不斷修改預算,項目進度越後期,預算越準確。軟件項目開發和拍電影同樣,具有很高的風險。不但成本難以預料,並且收益也要最後才能知道。所以對於預算來講,不斷的記錄和回顧預算執行狀況,以及其效率,修改現行預算方案,才能真正適合開發的進度。那種一年都按年度預算去執行的死板方法,是沒法適應快速變化的軟件開發項目的。

風險防護

留出過冬的口糧,定出必須籠絡的人員,儘早進入資金循環。軟件項目風險之高,難以用其餘行業徹底類比。就算最著名的公司如微軟、IBM也頻頻推出失敗的產品。所以在資金上留有儘可能大的餘地很是重要,不少項目經歷過瀕死體驗後,才能實現商業成功。軟件項目能繼續高效的開發下去,核心人員是相當重要的,讓他們擁有足夠的耐心和薪水,和項目繼續下去,纔有收穫那天的但願。而下降風險的最好方法,則是儘快去接觸風險,儘快讓產品上市,讓產品開始嘗試賺錢,能讓開發方向儘快明確到最實際的內容上來。團隊內的爭論和疑惑也會由於實際的財務數字而消散,你們的目標會更清晰——賺錢。

師徒制度預備人員流動。人員流動是不可避免的,就算你作到100分,仍是會有別的緣由致使程序員離職。所以除了在代碼上提倡可讀性和良好的結構,重視文檔和過程記錄,採用預備接替人員是很重要的手段。讓資深程序員和一個學徒程序員一塊兒工做,能儘快提升學徒程序員的能力,同時也讓代碼能有多一我的熟悉。在師傅離職後,徒弟就能夠升職到師傅的地位,也是一種良性的激勵。而徒弟對於這個代碼的感情,是別人所沒法比擬的。

儘早進入團隊和項目估值,尋找合適的買家。項目除了直接到用戶市場上去實現商業價值外,還應該看到,軟件項目由於他的結構性和擴展性,每每會在更大的範圍內具備價值。一些其餘商業方向的公司或者投資人,可能會看重你的項目的擴展價值。而這些擴展價值須要必定時間來讓別人認識到,所以對於管理者,在清晰的掌握項目的全面價值的狀況下,儘早的介紹給潛在的投資人和客戶,能讓項目擁有更廣闊的前景,從而下降其自然的風險。

相關文章
相關標籤/搜索