1.程序員的工作

很多時候,新手程序員對程序員工作的看法與經驗豐富的程序員的看法完全不同。

初學者經常會說“程序可以運行,您還需要什麼?”之類的話。有經驗的程序員都知道,“能正常工作”只是對程序的要求之一,甚至還不是最重要的

代碼可讀性

最重要的是程序代碼對其他程序員來說是可以理解的這比正確運行的程序更重要。多得多。

如果您的程序無法正常運行,您可以修復它。但是如果你有一個代碼難以理解的程序,你就無法對它做任何事情。

只需將任何已編譯的程序,如記事本,將其背景顏色更改為紅色即可。你有一個可以工作的程序,但你沒有可理解的源代碼:不可能對這樣的程序進行更改。

一個教科書示例是 Microsoft 開發人員從 Windows 中刪除了 Pinball 遊戲,因為他們無法將其移植到 64 位體系結構。他們甚至有它的源代碼。他們根本無法理解代碼是如何工作的

考慮每個用例

程序的第二個最重要的要求是考慮到每個場景。很多時候,事情比看起來要復雜一些。

新手程序員如何看待發送 SMS 消息:

一個正常工作的程序

專業程序員如何看待它:

一個正常工作的程序

“工作正常”的情況通常只是許多可能的情況之一。這就是為什麼許多新手抱怨 CodeGym 的任務驗證器:10 個場景中只有一個有效,新手程序員認為這就足夠了。


2.異常情況

異常情況

任何程序的執行都可能出現異常情況。

例如,您決定保存文件但沒有磁盤空間。或者程序正在嘗試將數據寫入內存,但可用內存不足。或者您從 Internet 下載圖片,但在下載過程中連接斷開。

對於每一種異常情況,程序員(程序的作者)必須 a)預見到它,b)決定程序應該如何處理它,以及 c)編寫一個盡可能接近期望的解決方案。

這就是為什麼程序在很長一段時間內都有非常簡單的行為:如果程序中出現錯誤,程序就會終止。這是一個很好的方法。

假設您想將文檔保存到磁盤,在保存過程中您發現磁盤空間不足。你最喜歡哪種行為:

  • 程序終止
  • 程序繼續運行,但不保存文件。

新手程序員可能會認為第二種選擇更好,因為程序仍在運行。但實際上並非如此。

想像一下,您在 Word 中輸入了 3 個小時的文檔,但在您編寫過程的兩分鐘後,很明顯該程序無法將文檔保存到磁盤。損失兩分鐘或三個小時更好嗎?

如果程序不能做它需要做的事情,最好讓它關閉而不是繼續假裝一切正常。當程序遇到無法自行修復的故障時,它能做的最好的事情就是立即將問題報告給用戶。


3.異常背景

程序並不是唯一面臨異常情況的程序。它們也出現在程序內部——方法中。例如:

  • 一個方法想寫一個文件到磁盤,但是沒有空間。
  • 一個方法想要在一個變量上調用一個函數,但是這個變量等於 null。
  • 除以 0 發生在方法中。

在這種情況下,如果調用方法知道被調用方法中發生了什麼樣的問題,它可能會糾正這種情況(執行替代方案)。

如果我們試圖將文件保存到磁盤並且這樣的文件已經存在,我們可以簡單地要求用戶確認我們應該覆蓋該文件。如果沒有可用的磁盤空間,我們可以向用戶顯示一條消息並要求用戶選擇不同的磁盤。但是如果程序內存不足,它就會崩潰。

曾幾何時,程序員思考這個問題並得出以下解決方案:所有方法/函數都必須返回一個錯誤代碼,指示其執行結果。如果函數完美運行,它會返回0。如果不是,它返回錯誤代碼(非零)。

使用這種處理錯誤的方法,在幾乎每次函數調用之後,程序員都必須添加檢查以查看函數是否以錯誤結束。代碼的大小膨脹起來,看起來像這樣:

沒有錯誤處理的代碼 帶有錯誤處理的代碼
File file = new File("ca:\\note.txt");
file.writeLine("Text");
file.close();
File file = new File("ca:\\note.txt");
int status = file.writeLine("Text");
if (status == 1)
{
   ...
}
else if (status == 2)
{
   ...
}
status = file.close();
if (status == 3)
{
   ...
}

更重要的是,發現錯誤發生的函數常常不知道如何處理它:調用者必須返回錯誤,而調用者的調用者將錯誤返回給調用者,等等。

在大型程序中,幾十個函數調用鍊是常態:有時您甚至可以找到數百個函數的調用深度。現在您必須將錯誤代碼從最底層傳遞到最頂層。如果在某個地方某個函數不處理退出代碼,那麼錯誤將丟失。

這種方法的另一個缺點是,如果函數返回錯誤代碼,它們將無法再返回自己工作的結果。計算結果必須通過參考參數傳遞。這使得代碼更加繁瑣,並進一步增加了錯誤的數量。