論程序員的自我修養,寫好代碼的實踐經驗分享

作為一名資深老程序員,也來談一談什麼樣的代碼算是好的代碼,以及怎樣寫出好代碼。

其實一個人寫的代碼跟這個人的性格是大致吻合的,房間很亂的人寫的代碼大概率也雜亂無章,現實世界還有物理規則的限制,代碼世界裡隨心所欲,程序員在無拘束的代碼世界裡必須要提升自我修養。

論程序員的自我修養,寫好代碼的實踐經驗分享

最近看到幾篇討論代碼好壞的帖子,不少人的觀點中,好的代碼應該具備良好的可讀性,清晰的註釋,要符合編程規範,變量命名要具備可讀性等等。

這些都對,但是如果一段代碼只符合這些,那是隻注重了表面功夫,一段代碼質量的核心要求還是這段代碼要好用,畢竟,代碼是要來用的而不是拿來看的。

功能完備

完整的功能是第一要素,這裡強調完整性,要求代碼實現十條功能,一條也不能遺漏。

有人說這還不簡單?其實真的不是太容易,因為大多數時候,只是程序員認為自己功能全部實現了而已,程序員自己理解的功能跟實際需要的功能往往差距很大。

比如客戶想要一個美女,這個客戶說想要美女的時候心裡想的是林志玲,因為這個客戶喜歡溫婉的古典美。

論程序員的自我修養,寫好代碼的實踐經驗分享

程序員表示收到了,但是別看這個這個程序員是個宅男,但那只是表象,當他聽到美女的時候,心理想到的卻是火辣的性感女神。

論程序員的自我修養,寫好代碼的實踐經驗分享

當客戶拿到程序員實現的美女時,內心肯定是崩潰的,因為客戶也不知道該喜歡好還是不喜歡好,你說性感美女不美嗎?也美,但就是不能打動客戶的心啊。

這只是個通俗的比喻,造成這種現象的原因是因為對一個需求的量化準則沒有進行明確的規定,靠人的感覺去做往往南轅北轍,因為人和人的差異性非常大。

做過測試的同學應該非常清楚,很多問題單都是因為規格的問題跟開發人員吵來吵去,測試人員認為手機溫度達到75度就應該過溫保護降低CPU功耗,但是程序員認為80度才應該過溫保護,為了這5度的事爭論不休。

所以,真正實現一段程序的完備性並不是那麼容易的,那我們應該怎麼做?

  • 需求澄清:好的程序員會在這個環節花費大量的時間,那些說聲好嘞就去寫代碼的程序員一般我都會把他們叫回來跟他們談談人生。要想做出客戶想要的林志玲,你得跟客戶反覆的溝通,鼻子多大嘴什麼形狀都得問清楚,程序員需要設計好問題去深入發掘客戶這個需求的原動力是什麼,明白客戶的需要究竟是什麼。
  • 快速原型:如果有可能,最好先實現一個簡單的原型讓客戶確認,原型最大的作用是有一個可以進行討論的實體,而不是憑感覺泛泛而論。客戶如果說對對對我就是要這個,那就繼續實現這個原型的細節,如果客戶說這裡不對那裡得修改,那請跟客戶把需要修改的點討論清楚。比如客戶覺得林志玲有點瘦,胖一點就完美了,那請跟客戶討論好是胖到100斤還是102斤。
  • 測試驅動開發:最近幾年比較流行的方法,開發之前先把驗收用例寫好,並跟你的客戶達成一致。手機過溫保護就是80度,驗收用例寫得清清楚楚,高一度低一度都不行,其實這樣程序員實現起來反而省心,因為不用去猜80度合適還是75度合適。

要寫出功能完備的代碼就不能偷懶,請多花點時間細緻澄清你的需求,別怕浪費時間,如果你實現偏了最後返工,只會浪費更多的精力,還會導致你的客戶對你的不滿。

可靠性強

這個要求一定要放在第二位,這比後面的要求更重要,如果說完備性決定了代碼能不能用,可靠性就決定了代碼好不好用。

可靠性通俗點來說就是不管你怎麼折騰,程序就是不會掛,你的代碼放在那裡好幾年都佈滿灰塵了,但是運行起來還是槓槓的,從來不需要人來操心。

論程序員的自我修養,寫好代碼的實踐經驗分享

可靠性比完備性更難達成,你能保證一次運行正確但是難保證一直運行正確,能保證一天運行順暢但是難保證幾年運行都不出問題,能保證過得了夏天但是不一定能搞定冬天(我沒有影射蘋果手機)。

可靠性難做的原因主要是要應對大量的未知的、不可控的應用場景,做功能完備性是做確定性的事情,保證可靠性是做不確定的事情。這就好比把橋修通車是做功能完備性,但是貨車一上就坍塌,一點洪水就翻倒,過了幾年就變脆,這都是可靠性沒做好。

論程序員的自我修養,寫好代碼的實踐經驗分享

一段代碼的可靠性更像是良心工程,因為代碼還沒有橋那樣的實體摸得著看得見,可靠性到底好不好也要等代碼運行一段時間後才能檢驗,所以有些程序員就會忽略這方面的考慮。

那麼怎麼做好代碼的可靠性呢?

  • 變量邊界值保護:變量的邊界值是觸發可靠性問題的重災區,邊界值不僅僅是0和256這樣的整數邊界,還有大量功能上的邊界。一般0和256這樣的整數邊界和溢出邊界都保護不好的程序員我覺得應該先下崗反思,很多定位困難的踩內存程序跑飛問題都是由於邊界值溢出導致的,隨手一段代碼讓別人熬夜定位故障好多天。功能性的邊界也需要仔細考慮,我見過有些電機控制程序在器件移動到頭的時候還一個勁猛轉,什麼樣堅強的結構都擋不住金剛鑽成年累月這樣折騰。
  • 處理所有程序分支:很多程序員很懶,寫代碼只寫正常功能那一個分支,他們腦子裡事物的發展只有一條路徑,不存在任何的異常和干擾因素。如果現實世界都是那麼單純就好了,可惜天不隨人願。請在所有的程序分支都寫上異常處理,否則一旦跑入沒有處理的分支,程序就有可能崩潰。如果不方便所有分支都詳細寫異常處理,那請在函數結尾處做兜底。
  • 完善單元測試:這麼多年編程經驗告訴我,哪裡沒有測試到,哪裡就肯定會出問題。寫作單元測試用例是有完善的工程方法的,別因為測試用例多就偷懶,請把單元測試用例寫完備,從代碼的最底層就把測試做好,這些測試用例自動化以後,可以長久守護你的代碼。
  • 加強系統可靠性測試:很多人做測試大多數集中在測試功能完備性上,按我的經驗,你要想保證程序的可靠性,需要的測試用例至少是功能測試的兩倍以上。各種使用場景、各種嚴苛環境、跨月的長期運行測試,條件允許的話建議都要考慮。有些人可能會說這樣做是不是成本太高了?我的建議是測試用例的考慮要儘量完備,如果覺得有些沒有必要可以評估後裁剪掉,那種考慮都沒考慮全面的測試是不能滿足要求的。

再次重申,程序可靠性最考驗一個程序員的良心和修養,這是個需要大量精力才能做好的活。

性能優秀

性能在目前的高性能硬件環境下並沒有那麼重要了,或者說大多數情況下並不是主要矛盾。

但是在特殊的應用環境下,性能要求還是非常非常高,比如春節搶紅包、通訊設備大批量用戶同時接入、雙11搶購、國家骨幹網服務器等。

論程序員的自我修養,寫好代碼的實踐經驗分享

高性能和低性能的代碼效率可能相差千百倍,提升代碼性能是個技術活,必須對代碼運行機制和操作系統的原理有深刻的理解,否則你不知道代碼性能從哪些方面入手。

一個好的程序員不僅要會寫代碼,還要把數據結構、操作系統、編譯原理等專業課知識學精學透,那些覺得只需要學好一門編程語言就可以做程序員的人,很容易變成只能編碼的底層碼農,這不是開玩笑。

  • 好的系統架構:架構一定簡潔,不要有過多的分支和循環往復的複雜依賴。太複雜的架構不僅會導致很低的運行效率,還會導致程序難以維護。如果你覺得你的架構就是需要這麼複雜,那請找更高水平的人討論,大道至簡,你的複雜性只是因為你對事物的總結不夠深刻。
  • 高效的數據結構算法:算法一定要高效,如果沒什麼好的想法,建議複習下大學課程《數據結構》,簡單的排序算法也可以提升一百倍效率。如果你簡單的使用一下哈希算法或者折半查找,你的算法就可以昇華,所以一定要有設計高效算法的潛意識和能力。實在設計不出來,上網找個編程社區搜索一下。
  • 減少進程切換:進程的切換往往伴隨著保存現場,數據壓棧出棧,內存反覆尋址讀取寫入等一系列複雜的操作,如果你的一項需要高性能的代碼在計算過程中產生了進程切換,那性能的影響是災難性的,所以這方面在實現的時候一定要格外注意。
  • 少讀寫內存:儘量在高效運算時不要讀寫內存,CPU的運算速度極快而讀寫內存極慢,CPU停下來等內存的感覺就好像等了一個世紀那麼久。所以請將一切數據都準備好再開始計算,實在不行就一次性讀取大段數據,不要讀一點算一點,那樣子效率最低。
  • 宏的效率比函數調用高:函數調用是個非常複雜的過程,而宏在編譯的時候是直接在調用宏的地方就地展開的,實際運行的時候不存在調用函數的那一堆動作,所以,如果你需要高效率,可以把簡單功能適當封裝成宏。

性能的提升確實需要一定的技術含量,個人建議在需要性能的時候再刻意的去考慮性能提升,優先把功能完備性和可靠性做好。

可擴展性強

可擴展性時常被程序員忽略,因為這是個後效性的質量品質,一般都不會當場就被檢驗出來,都是在用了一年半載以後,需要增加功能進行軟件升級的時候,才會集中爆發。

本人就曾經遇到過一個案例,只需要將一個模塊的用戶數從50人修改到100人,整個軟件產品竟然涉及幾百個修改點,客戶覺得兩分鐘就改完的工作,連修改待驗證折騰了兩個星期。

論程序員的自我修養,寫好代碼的實踐經驗分享

當然這只是一個例子,可擴展性的含義不僅僅是修改軟件的規格,總的來說,可擴展性是為了應對未來的變化。

  • 從架構做起:在設計你整個軟件架構的時候,要充分考慮你軟件所實現功能的未來發展可能性,以便未來增加新的功能。比如你做了個軟件可以發送文字,你自然要考慮到未來可能會發送音頻或者圖片甚至視頻,擴展性做得好的,會將這些的擴展接口都留下來,未來新增這些模塊甚至不需要修改老的功能任何一行代碼。
  • 處理好善變的那些規格:使用人數、允許接入的連接數、溫度的上下限、告警門限,可以講這些規格就沒有完全穩定的時候,一直處在變化中。這些數據都需要集中進行管理,嚴禁個人私自定義甚至直接使用具體的數值來做控制,要按照可配置的思路設計規格變量。

可擴展性很難用一種量化的標準去衡量,多數時候依賴軟件設計人員的經驗。

基礎要求

代碼邏輯清晰可讀性強,有完備的代碼註釋,統一的變量命名規則,符合較低的圈複雜度,符合編程規範,所有這些個人認為都是程序員的基本功,本文就不展開詳細論述了。

論程序員的自我修養,寫好代碼的實踐經驗分享

如果有人不太理解編程規範是個什麼東東,可以網上搜索華為的編程規範來學習一下,規定的都是一些非常基礎,但是一不小心就會犯錯誤的編碼技術問題。

總之,想要寫好一段代碼也不是那麼容易的,資深程序員需要在軟件工程能力和計算機基礎科學理論上多投入精力,幹一行愛一行,努力提升作為一個程序員的自我修養。



分享到:


相關文章: