這個是講軟件研發過程管理的系列,目標人羣是那些身處研發管理位置或想成爲研發管理的人。因此我不但願這個系列中出現代碼,也不但願出現和某種技術密切相關的代碼技巧。
可是沒有辦法,軟件開發過程管理,有個很重要的一環,就是軟件代碼編寫。不編寫代碼,說的天花亂墜,管理作的再扭,也成爲不了軟件。
最近blog好友到了上限,因此沒法加入好友了。因而就加入了N多QQ網友。大多數剛出道一兩年,還有很多在校學生,但願認識並聊聊,要和我聊設計模式、OO、SOA,還有人建議我去看看OO和UML的書籍。
我確實沒有閱讀過OO的書籍,我不是一個死鑽牛角尖的人。我只是有什麼問題,就去找解決問題的方法,能解決個人問題就OK,而不在意我用的正不正宗,也不在意我用的是否是OO。可能它是OO的外殼,可是它實質上多是僞OO,我也不想去深究和區分什麼是正宗OO,什麼是僞OO。反正能解決個人問題就行。
我首先趕上的問題是代碼大流水的問題。一個代碼3000多行,數不清的if..else。我實在沒法分析出這個代碼到底實現了什麼功能,它複雜的就像一把瑞士×××,若是×××裏面能出來一支小手電也以爲不奇怪。這段代碼我想它就是這樣。我想寫這段代碼的人必定是在學校作慣了《圖書館管理系統》,一個程序文件中實現了全部的功能。
因此,經歷了痛苦,我就一直要求手下的開發人員,一個函數代碼行數不能超過一個屏幕。若是超過一個屏幕,就須要來回滾動。一滾動,就容易把思路滾動的走神,亂了,還得回到上面去從新理邏輯。
這種規定,直接致使了一個後果,函數太多了。可是函數間是有關係的。有時候忽然須要增長一個參數,可是此函數已經被其餘代碼調用了,因而爲了省事不改動其餘代碼(固然,他可能已經忘了再哪些地方都調用到了),他就定義了一個全局變量,在函數之間傳。
新的問題有出來了,全局變量的問題。代碼在他一我的手裏還好說。被維護了好幾手,新手對日益複雜的代碼已經不太容易理出頭緒,但修改任務是有時間限制的,只能在現有理解水平上工做。這位新手看到這個全局變量的命名,感受是本身能用的到,就用了,還給賦了值。意向不到的事情發生了,數據庫中進了錯誤的數據,怎麼來的,不知道,看代碼,處理的都正確,代碼沒有問題,也不知道怎麼出現的。
因而禁止你們使用全局變量,能藏到多低的可見級別就藏的多深。可是仍然問題依舊。
因而,咱們就把這個全局變量封裝成屬性,給它賦予讀和寫的函數。無論有多少個地方調用了它,有誰給它亂賦值,這裏掐源頭,都作好日誌和異常保護校驗。
把全部函數,能變成私有的就變成私有的,須要公共供其餘人調用的謹慎的放出來。放出來的函數,必定要作好參數的校驗,什麼空指針,什麼沒有初始值,什麼非法參數值的,尤爲是臨界值上下邊界,都在門口就擋住,根本不往下執行進行業務處理,不然走的越遠引發的問題越大。
並且要求每一個函數都要作好本身的內存保護工做,本身函數內建立的就要在函數內釋放。每一個函數要作好異常處理和日誌記錄。
這樣,一個樣子像OO的類產生了。它可能只遵照了OO所提了封裝,它卻沒有實現OO所提的繼承和多態。因此它多是個僞OO,但它確實解決了咱們的問題。
封裝了類以後,又一個問題產生了。幾個類之間不知怎麼的,老是你中有我,我中有你,互相調用了。就好像左右手互搏,弄很差就會把本身給捆起來。
爲了堵住這個問題,規定只能單向依賴,若是發現你必須調用另外一個類,另外一個類也須要調用這個類,就以一個類爲主,另外一個類開放事件。這也許就是控制反轉,AOP的需求吧(我並無深刻研究AOP,我只記得控制反轉這個詞,好像是爲了解決相互依賴關係問題)。「Don't call us, we'll call you」。
可是代碼穩定性的問題仍然沒有很好解決,測試組也找出了許多BUG,可是一到客戶那裏運行,仍是出了很多BUG。怎麼本身運行的時候找不到呢?
因而,咱們在版本測試的時候、第一個版本小規模放給典型客戶的時候,都加了斷言。一旦軟件出現問題,就當即記錄日誌,並進行軟件中斷,而不讓錯誤繼續錯亂的不按咱們預想的代碼流程走下去。不少年前,我就驚訝於某公司的軟件的質量,怎麼折騰操做都沒有問題,我經常給個人手下拿這個例子來反襯你們的代碼質量。直到我有時隨便亂點,竟然軟件中斷退出了,報了一個錯誤號,我一會兒想通了,它用了斷言。斷言阻止了錯誤的繼續擴散,不讓惡果之鞭長袖善舞。因而,我要求開發人員常常性使用斷言,不少過去悄然發生的錯誤,測試員只運行可執行程序沒法捕捉到,如今都能明確的捕捉到,在測試階段就儘量的消滅了那些過去沒法明示的BUG。
我過去領導過架構組。架構組的人在2002年的時候,瘋狂迷上了UML和設計模式,人手一本《COM本質論》和《設計模式》。我手下有一個新手,就到處是類,到處是抽象,到處是封裝,到處是分離,儘可能使代碼高內聚低耦合。可是這樣的的代碼太麻煩,他花費了大量的時間,他看本身的代碼賞心悅目,別人看他的代碼雲裏霧裏,不閱讀懂《設計模式》就按照常規理解業務的思路去閱讀他的代碼根本閱讀不懂,不知道他爲何這樣寫代碼,怪異的很。原本,這位想達到可維護性,可閱讀性,卻真正的失去了可維護性、可閱讀性。這和我前幾天看個人朋友周愛民寫的《大道至簡》中寫到:有人但願拿UML去統一用戶和軟件設計者。卻不知UML有多難理解,而UML設計者卻認爲UML能夠描述一切。就這個道理,要理解你的代碼還要去讀懂《設計模式》,這要求過高了吧。
所幸這位新手本身都每次寫的累,慢慢的也就懶了,以爲確實須要分離的時候就分離,以爲沒什麼必要的就懶得作了。用他自嘲的話說就是:被磨平了。其實,依我看,他如今這個代碼狀態纔是剛恰好,即照顧了設計擴展,又照顧了實用。真正的純OO,純設計模式,可能只存在於教學和科學,而不在於咱們的商業軟件開發。咱們做爲商業開發,強調的是叫座的基礎上叫好,因此折中方案是必須的,客戶和咱們本身兩相宜就OK,是否符合正宗,就不在咱們的商業開發管理範疇了。
這位新手還寫了大量的註釋。在每一個源代碼文件頭都寫上幾月幾號,XX建立的,這個原代碼文件主要是幹什麼的,還多此一舉的寫上版權全部,公司名稱。好像這個代碼要開源,或者可能會被其餘公司竊取了好代表公司版權。甚至每一個函數都寫了註釋,每一個參數是什麼意思,每一個參數可能出現的值表明什麼意思,都寫的一清二楚。長此以往,也懶的維護了。代碼改動了,參數擴展了,參數狀態值有了變化,註釋說明卻沒有跟着改動,讓後來看代碼的人老誤解,還不如不寫這些註釋。
我告訴他:作事不能走極端。要麼全寫註釋,要麼不寫註釋,都是不對的。我只在我認爲要當心的地方,或者我本身都以爲很難理解懂的地方我才寫註釋。不然,我本身均可能會過段時間理解錯了。若是某段代碼我看看就能看懂,我就不寫註釋了。我們作企業管理軟件,深刻技術又沒有,只要代碼能把複雜的業務處理描述的邏輯思路清晰就OK。雖說理解能力不一樣,我能快速理解了的未必有新手可以理解,可是你看看個人代碼你就明白了。
這位新手去看個人代碼去了。個人代碼幾乎沒有什麼難度技術,但代碼也是看上去很舒服。他發現瞭如下幾個關鍵點: 1 代碼風格統一,從命名含義,到大小寫,到縮進,都一致。每一個源代碼文件都一致,確實出於一人之手。許多程序員,光本身的代碼就有好幾種風格,有時心情好,有時心情很差,有時頭腦清醒,有時沒有休息好,有時敷衍,有時多此一舉,有時急躁,從代碼就能看出來。而個人代碼就像穩定運行天天如一日的機器,好似每一個源代碼都是在同一天敲的。這就叫發揮穩定。這幾天要開奧運會了,運動員每天重複練同一個動做,把每一個環節都練的精益求精,其目的就是爲了在大賽緊張的壓力下也能發揮穩定。人在壓力下,很是容易發揮失常。若是人老處於這種壓力下訓練,那麼大賽就像日常同樣了。
2個人代碼竟然能看出業務流程。函數數量均衡,不像他的代碼函數太多,跟蹤跳轉的很累,也亂了頭緒。函數長度也正好在可理解閱讀範圍內。並且有一個流程控制函數,把流程處理環節串了起來。細深刻跟蹤某一環節,又發現了更細的流程。每一個函數都看起來簡單,但總體來看,卻實現了複雜的功能。他問我是怎麼作到的?我說,個人心中只有業務,業務和代碼,我認爲只是英語和漢語的區別,表達的是同一個思路。而在你心中,業務是DOC上的文字,代碼是你的技術表現,你老須要把業務和代碼映射擰在一塊兒,我則不須要。業務流程如何,個人代碼流程就是如何。
3因爲個人程序都是小函數組成的,都有明確報錯,因此錯誤很容易找到,即便出錯,也擴散不大,都是小bug,對系統總體沒有大影響。
他還對個人開發方法不理解,問我爲何要讓你們從後臺往前臺開發,他很不習慣這種方法。他過去開發都是先用開發工具拖拽控件畫出界面,而後一個按鈕一個按鈕的處理業務代碼,須要什麼字段就在數據庫裏設計什麼表加什麼字段。
我問他:你爲何要這樣作?
他說:我不理解需求,沒法憑空想象,只能先畫出來界面,而後有了直接感受後就在開發中理解業務,邊開發邊理解。
我問他:那你之前有詳細設計說明書沒有?
他說沒有。
我又問他:那你之前有人單獨設計數據庫和開發業務處理中間件組件麼?
他說沒有。
我說,問題就在於此。你沒有詳細設計說明書,因此你看不到一個形象的東西,而我們如今至少有PPT畫的業務界面,也有輸入要求說明,也有數據增刪改查說明,也有業務描述說明。並且數據庫,一箇中大型應用,性能、穩定性、可擴展性,都在於數據庫的設計和中間件的設計,若是每個程序員都要從數據庫設計到中間件組件開發到前端客戶端開發,那麼要想保證這個軟件的統一總體質量,那有多難。每一個程序員須要懂得多少的技術知識才能達到統一的質量要求。因此,讓不一樣技術高度的人作不一樣難度的事情,把重要的事情掌握在高素質的人的手中,這樣質量就不會跑偏到哪裏去。企業管理軟件,不外乎是數據的增刪改查。數據庫的視圖和存儲過程,已經屏蔽了複雜的表之間的關係,提供了統一的業務實體視圖和業務實體的增刪改操做。這樣中間件組件就容易處理業務實體間的流程,到了客戶端,就只剩下數據的輸入和輸出了,真正成了終端。
我還常常進行代碼複查工做。發現有人的代碼出現壞跡象,我就讓他整改重構本身的代碼。不然,定了規範,光喊口號讓你們遵照規範又不檢查又不懲罰,誰愛遵照規範?
在代碼複查的時候,我常常能發現思路侷限、想法繞彎、實現缺少擴展性可變性、缺少優化、判斷有遺漏有風險的代碼。我都一一給他們指出,而且告訴更好的方法應該是如何如何。
不少網友都問到如何培養開發人員、培訓開發人員、提升開發人員技術。我過去所在的公司是每一個週五都不按期召開技術培訓會。可是慢慢的也流於形式了。我我的感受,技術培訓會是個好事,但最終達到的效果多是增強了團隊的凝聚力和和諧力,有利於團隊建設,可是技術提升,並無給開發人員在實際工做中有應用。由於你們聽了也就聽了,會一散實際工做中仍然照舊本身的思惟習慣,很難落實下來。
經過代碼複查,這就是真真實實的代碼,這就是你們最實在的工做成果和每天接觸的東西,頗有真實性,不脫離,有針對性。經過這種方法,達到了你們對本身平常寫代碼的技術技能的提升。這就是我對程序員的培訓方法。
管理是什麼?有網友老跟我討論企業管理、企業文化、盈利模式、執行力、忠誠度。我不是很喜歡這些空洞抽象的主題,討論完了也沒法解決實際細節問題。而企業的運做,偏偏在於每一步的成功,最終匯合成最終目標的實現,沒有腳下的每一步前進,再好的設想也是空想。
管理,就在細節當中。
代碼高手,也在於細節當中。
質量、進度、成本、目標、折中,這就是核心。寫代碼,作管理,道理同樣。