這裡將向大家分享的是一些我對編程的思考總結,這些經驗在我畢生編程生涯中曾幫助我在無數的事情上作出正確的決定。這些編程策略有些是很顯然的,但實際編程中往往被人們忽略。
下面的例子是用Python寫的,但這些概念適用於任何程式語言。
找出程序的主執行路徑——你的程序大部分時間都執行這些模塊。首先優化這部分代碼,但也不要在程序實現的第一次迭代中進行優化。那些處理邊界情況或失敗/異常處理的地方,這部分代碼不需要優化,除非它們引起了值得注意的性能問題。
不要試圖壓縮代碼行數,但你應該壓縮每個任務的代碼行數。寫簡單的函數/方法,每個函數/方法只完成一個任務,而不是多個,除非你有很好的理由。
人們通常喜歡為了減少代碼行數而在一個代碼片段裡完成大量的工作,這會導致代碼異常複雜,這種代碼試圖支持各種情況的處理,而大多時候只是其中的一種情況會發生。多餘的情況處理會給執行造成成本。
了解機器,理解機器內部裡事情是如何工作的。這將會幫助理解各種不同瓶頸產生的原因。這能幫助你找到代碼運行時為什麼會發生奇怪的現象。
在編程中運用管理技術。針對不同目的使用正確的工具。我有自己的喜好,但我努力克服。
編程的時候,有些邊界情況我們需要確保能正確的處理。對這些情況我們通常的做法是使用if語句來檢查是否是這種情況。當程序運行時,這些檢查動作每次都會執行,來驗證是否是遇到了這些特殊場景。如果你使用的程式語言有異常處理系統——你可以利用它們來處理這些邊界情況。
C語言裡沒有異常處理系統。它依賴於錯誤碼來通知調用的函數發生了什麼。返回0是成功,負數則表示失敗。所以,調用者需要用if-else來檢查返回碼。沒有其它的方法。
但對於那些有異常處理系統的程式語言,我們可以很好的利用它們。但我們需要使用if-else配合異常處理機制來處理這些邊界情況或錯誤。
一個簡單的例子 :-
想像有一個後臺運行程序,它在啟動和停止時都會檢查一個pid文件。它會調用下面的函數來獲取pid。主調函數使用異常捕獲來確保程序邏輯不會出現意外。
下列情況時這個函數會被調用 -
每種情況時主函數要做的事 -
下面就是我們上面提到的主程序會調用的獲取pid的代碼。注意我們使用異常捕獲和if-else語句來處理這些情況。
方法 1
# 這種使用異常的方式不好,屬於被動防禦式編程。def read_pid_file(): try: f = open('daemon.pid', 'r') pid = int(f.read()) return pid # 沒有發現文件,也可能是IO錯誤 except IOError: raise "Faild to Read file" # 有人在文件裡放的不是數字,這能怪誰? except ValueError: raise WrongPID # 捕獲所有其它異常 # 這個有點像 # 過度使用異常處理 except Exception: raise SomeUnKnownError
方法 2
# 使用If/else方法。主調函數需要檢查無返回值情況# 異常情況def read_pid_file(): if os.path.exists('daemon.pid'): try: f = open('file.pid', 'r') # 對於支持異常處理機制的程式語言, # 如果有操作失敗,拋出異常 # 這裡跟C語言有區別 return int(f.read()) except (ValueError, IOError): pass
方法 3
# 事實上,我們知道可能會發生什麼,如果pid讀文件# 文件時有錯誤,主調函數會捕獲它。# 我們使用的程式語言有異常處理機制。# 我們可以在這裡利用上。def read_pid_file(): f = open('daemon.pid', 'r') return int(f.read())
我喜歡方法 3,因為它在大多數情況下都可行。如果極少的情況下出現了錯誤,主調函數裡的異常處理會捕獲這種情況。
兩種錯誤處理方式都是我們保證程序無誤的重要途徑。
何時使用if-else語句
何時使用異常處理
有時候事情就是這樣!而且這樣並不一定是壞事。我們編程時經常這樣——當我們開發一個新原型,或針對一個特殊問題找一個解決方案,這時我們如何實現並不重要,重要的是在定型後我們如何完成它們。我想大多時候我們都是這樣做的。誰都知道,先打草稿,後動真的。
請在評論裡留下你對這些觀點的想法。