每日最新頭條.有趣資訊

谷歌軟體工程師分享編程經驗:有效的流程很關鍵

選自blog.usejournal

者:Steve Merritt

參與:Panda

編寫程序時,正確合適的工作流程能夠確保高效地完成工作目標。近日,谷歌軟體工程師 Steve Merritt 在部落格上分享了自己的工作流程,機器之心進行了編譯介紹,希望能為讀者的編程之路帶來一些幫助和啟發。

我將在這篇文章中帶你了解我從頭至尾解決編程問題的策略。我既在谷歌的日常工作中使用這一策略,也在和各種水準的編程人員(訓練營、大學生和實習生等)合作時使用它(幫助他們學習和成長)。應用這一結構化的流程能盡可能地縮減令人沮喪的調試過程,在更少的時間裡得到更清晰更正確的代碼。

一步步介紹

我將使用一個示例練習題來進行說明。

問題:「給定兩個字元串 sourceString 和 searchString,返回 searchString 出現在 sourceString 中的第一個索引。如果 searchString 未在 sourceString 中出現,則返回 -1。」

第一步:畫出來

直接從寫代碼開始實際上是一個荒謬又懶惰的思路。在寫一篇文章之前,你首先會搞清楚你的假設和證據,以確保你的論證是合理的。如果你不這樣做,後面當你發現你寫的內容整體無法合適地組合起來時,你又要重新開始,這會浪費很多時間。寫代碼也是這樣,甚至可能更糟,就像把洗發水揉進眼睛裡那麽糟。

通常而言,一個問題的解決方案並不是淺顯直觀的,即使可能乍看起來很簡單。在紙上琢磨一下能讓你找到解決方案並驗證該方案在一些不同場景中的效果。所有這些工作都應在寫下任何一行代碼之前完成。

所以先不要寫代碼。甚至不要去想代碼。後面你會有足夠的時間去添加分號和括號。現在你只需要搞清楚你作為一台人體計算機,會如何解決這個問題。

畫圖。使用箭頭。在小方框裡填寫數字。只要能讓你可視化這個問題,就去做吧。你的目標是解決問題,你能用紙張和鉛筆盡情發揮,而不受限於鍵盤。

首先找一些簡單的輸入。比如,假設你的函數是「取一個字元串」:「abc」。搞清楚正確的結果是什麽。然後去想「如何」解決這個問題以及所涉及到的步驟。

我們假設我們的字元串有以下值:

我的想法就會像下面這樣展開:

好吧,我看到 sourceString 包含 searchString。但我是怎麽看出來的?嗯,我首先從 sourceString 的開頭開始閱讀,檢查每 3 個字元構成的片段是否與詞「yes」匹配,直到結束。比如,我看了 abc、bcd、cdy 等組合。當我看到索引 4 時,我找到了 yes,所以我確定找到了匹配並且是從索引 4 開始。

當我們寫下我們的算法時,我們需要確保我們表達了一切並能夠處理所有可能的情況。當我們確實能找到匹配時,返回正確答案當然很好,但我們也需要在沒有匹配時也能返回正確答案。

我們再以另一對字元串為例:

這裡,我們同樣首先從 sourceString 的開頭開始閱讀,檢查每 3 個字元構成的片段是否與詞「yes」匹配,直到結束。當我們看到索引 4 時,找到了「yef」,差點就匹配了,但卻並沒有完全匹配,因為第三個字元不同。所以我們繼續檢查,直到字元串末尾,最後確定其中沒有匹配,因此返回 -1。

我們已經確定了解決這個問題的一系列步驟(在編程領域,我們稱之為「算法」),我們也已經嘗試了一些不同場景,每一次都得到了正確的結果。現在,我們已經很相信我們的算法有效了,現在是時候形式化這個算法了,這就是下一個步驟。

第二步:寫成國語

我們想想在第一步確定的算法,然後用平實易懂的語言把它寫出來。這能使這些步驟顯得具體,讓我們在寫代碼時能夠回顧參考。

從字元串開頭開始檢查

檢查每 3 個字元構成的片段(具體字元數量視 searchString 而定)

如果其中有任何片段等於 searchString,就返回當前索引

如果直到該字元串結束也沒找到任何匹配,就返回 -1

看起來不錯喲!

第三步:寫偽代碼

偽代碼並不是真正的代碼,但卻模仿了代碼的結構。下面是我為上面的算法寫的偽代碼:

我還可以讓偽代碼更接近代碼一點,比如這樣寫:

偽代碼與代碼的接近程度完全由你決定,隨著時間的推移,你會發現最適合自己的風格!

第四步:將你能做到的部分翻譯成代碼

注:對於更簡單的問題,這個步驟可以與上一步一起完成。

這是整個流程中我們第一次必須考慮句法、函數參數和語言規則。你也許沒法寫出所有一切,但沒有關係,把你知道的部分寫出來!

注意,我在這段代碼中留了一些空白。這是故意的!我不確定 JavaScript 中切分字元串的句法是什麽,所以我要在下一步查一下。

第五步:不要猜測

我看到代碼新人常會犯一個錯誤:在互聯網上找一些寫著「可能有效」的東西,然後不加測試地將其插入到自己的程序中。你的程序中你不理解的片段越多,你就越不可能最後得到正確的解決方案。

每增加一個你不確定的東西,你的程序可能出錯的方式都會翻一倍。對某事不確定?沒有問題——如果你的代碼無效,那麽這裡可能就是問題所在。

附注:你的程序可能出錯的方式遵循梅森序列:a(n) = (2^n)?—?1

首先測試你的新代碼。在網上找東西是可以的,但你在將其插入你的程序之前應該在另一個單獨的小空間裡測試一下它,以確保其工作方式和你所想的一樣。

在前一步中,我並不確定在 JavaScript 中該如何選擇一個字元串的特定部分。所以我谷歌了一下:

https://www.google.com/search?q=how+to+select+part+of+a+string+in+javascript

第一個結果來自 w3schools,有點舊了,但通常比較可靠。

https://www.w3schools.com/jsref/jsref_substr.asp

基於這個結果,我猜想我應該使用

來提取 sourceString 中的各部分。但這只是一個假設,僅此而已。所以,我首先創建了一個小例子來測試其行為。

現在,我已經確定這個函數的效果了。所以當我將其插入到我的程序中時,我知道如果我的程序沒有效果,那麽原因不會是我加入的這段新代碼。

有了這樣的保證,我就可以完成程序的最後一部分了。

總結

如果你讀到了這裡,我現在只想說:試試這種策略。回到你上周因為受挫而擱置一旁的編程問題。我保證你能立馬看到效果。祝你好運,編程快樂!

本文為機器之心編譯,轉載請聯繫本公眾號獲得授權。

------------------------------------------------

獲得更多的PTT最新消息
按讚加入粉絲團