成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

【譯】怎樣避免開發(fā)時的深坑

KitorinZero / 2858人閱讀

摘要:但是,在實際開發(fā)時仍然障礙重重。我就曾經(jīng)接受了一個開發(fā)任務(wù),就是做一個像劊子手一樣的游戲,但是當我看完需求中所有的規(guī)則時,才意識到要做的應該是邪惡的劊子手這是一個深坑。邊界問題僅在極端最大或最小值參數(shù)的情況下發(fā)生的問題或狀況。

翻譯:瘋狂的技術(shù)宅
作者:Valinda Chan
英文標題:10 Steps to Solving a Programming Problem
英文鏈接:https://codeburst.io/10-steps...
本文首發(fā)微信公眾號:充實的腦洞

我總是聽到剛?cè)胄胁痪玫某绦騿T這樣說:知道自己要實現(xiàn)什么功能,同時處理邏輯和基本語法也都明白,但是就不知道該怎么寫代碼。如果把別人的的代碼給你看,或者有人給你你一些指導,或許你能明白其中的思路。但是,在實際開發(fā)時仍然障礙重重。即使語法或邏輯都明白,也很難自己的想法轉(zhuǎn)化為代碼。在本文中我將會告訴大家我自己是怎么做的,還有一些解決典型問題的方法,希望能夠?qū)Υ蠹矣兴鶐椭?/strong>

1. 把給你的需求反復閱讀三遍以上(或者直到看吐了為止)

如果不能理解給你的需求,也就沒有辦法實現(xiàn)它。 實際的需求和你認為的需求有很大的區(qū)別。假設(shè)有一個需求,當你閱讀前幾行時非常容易,但是接下來你就會假設(shè)其余部分與你曾經(jīng)看到過的東西類似。比如你要做一個像“劊子手”一樣的游戲,一定要通讀它所有的規(guī)則,即便你曾經(jīng)玩過這個游戲。我就曾經(jīng)接受了一個開發(fā)任務(wù),就是做一個像“劊子手”一樣的游戲,但是當我看完需求中所有的規(guī)則時,才意識到要做的應該是“邪惡的劊子手”(這是一個深坑?。?。

有時我會試著向一個朋友解釋某個需求,看她對我解釋的理解是否和我的需求一致。如果你不想在開發(fā)了一半的時候才發(fā)現(xiàn)自己誤解了這個需求,那么在開始的時候多花點時間是值得的。你對問題越了解,就越容易解決它。

假設(shè)我們要創(chuàng)建一個簡單的函數(shù)selectEvenNumbers,這個函數(shù)的參數(shù)一個存放整數(shù)的數(shù)組,返回值evenNumbers 是一個只存在偶數(shù)的數(shù)組。如果沒有偶數(shù),那么久返回一個空數(shù)組。

function selectEvenNumbers() {
  // your code here
}

以下是我思考的問題:

計算機怎樣去判斷是不是偶數(shù)? 檢查該數(shù)是否能被2整除

我傳給這個函數(shù)的參數(shù)是什么? 一個數(shù)組

數(shù)組中保存的內(nèi)容是什么? 一個或多個整數(shù)

數(shù)組中元素的數(shù)據(jù)類型是什么? 整數(shù)

這個函數(shù)的目的是什么?之行結(jié)束后要返回什么? 目標是得到所有偶數(shù),并把它們保存到數(shù)組中返回。如果沒有偶數(shù),就返回一個空數(shù)組。

2.至少使用三組模擬數(shù)據(jù)進行手動模擬

找一張草稿紙,人工解決這個問題。至少考慮三組模擬數(shù)據(jù),注意要考慮到極端情況和邊界問題。

極端情況:在正常操作參數(shù)范圍之外產(chǎn)生的問題或情況。或者是多個變量或條件都在其指定范圍內(nèi),但是都同時處于極端的水平的情況。
邊界問題:僅在極端(最大或最小值)參數(shù)的情況下發(fā)生的問題或狀況。

舉個例子,下面是一些要使用的樣本數(shù)據(jù)集:

[1]
[1, 2]
[1, 2, 3, 4, 5, 6]
[-200.25]
[-800.1, 2000, 3.1, -1000.25, 42, 600]

在剛開始的時候,很容易忽略這些步驟。

因為你的大腦對于偶數(shù)的概念十分清楚,所以只要看到一組數(shù)據(jù),就可以從中找到2,4,6這樣的數(shù)字,幾乎意識不到自己的大腦是怎么思考的??梢試L試更多的數(shù)據(jù),它會改變你大腦通過觀察來解決問題的習慣。這有利于幫你實現(xiàn)真正有效的算法。

我們來看第一個數(shù)組:[1]

查看數(shù)組 [1] 中唯一的元素

判斷是否為偶數(shù):嗯,并不是

確定這個數(shù)組中沒有其他的元素了

確定在這個數(shù)組中沒有偶數(shù)

返回一個空數(shù)組

接下來看第二個數(shù)組:[1, 2]

先看數(shù)組[1, 2]中的第一個元素

數(shù)字是1

判斷是否為偶數(shù):不是

看數(shù)組中的下一個元素

數(shù)字是2

判斷是否為偶數(shù):是的

創(chuàng)建一個數(shù)組evenNumbers ,并把數(shù)字2添加到其中

確定數(shù)組中沒有其他元素了

返回的數(shù)組evennumbers[ 2 ]

再多看幾遍。請注意處理[1]的步驟和[ 1, 2 ]略有不同。這就是為什么我要嘗試多種不同的組合。在這些數(shù)據(jù)中,有的只存在一個元素;有些是浮點數(shù),而不是整數(shù);有些是一個元素中有多個數(shù)字,有些是負數(shù)。

3.簡化并優(yōu)化你的步驟

尋找模式,找到概括問題的方法,看看能不能減少無用或重復的步驟。

創(chuàng)建一個函數(shù)selectEvenNumbers

創(chuàng)建一個保存數(shù)據(jù)的空數(shù)組evenNumbers

檢查數(shù)組[1, 2]中的每個元素

找到第一個元素

判斷它是否可以被2整除。如果是,就加到evennumbers

找到下一個元素

重復步驟4

重復步驟5和步驟4,一直到數(shù)組中沒有任何其他元素

返回數(shù)組evenNumbers ,不管它是不是空數(shù)組

這個方法可能會讓你想起數(shù)學歸納法:

證明當 n = 1, n = 2, ... 的情況下成立

假設(shè)當 n = k 時成立

證明當 n = k + 1 時成立

4. 寫出偽代碼


偽代碼

我們已經(jīng)有了處理步驟,接下來就要編寫出偽代碼了,偽代碼可以轉(zhuǎn)換成真實的代碼,這有助于定義代碼的結(jié)構(gòu),并使編碼變得更加容易。您可以在紙上寫偽代碼,也可以在代碼編輯器中用注釋的形式來寫。如果你在電腦上做會分心,我建議你用紙和筆來完成。

通常偽代碼并沒有什么特定的規(guī)則,不過有的時候我可能會使用自己熟悉的某種語言的語法。所以不要被語法所糾纏。把精力放在邏輯和步驟上。

對于我們所面對的問題,可以有很多不同的方法。 例如,您可以使用filter,但是為了盡可能簡單地說明前面的例子,我們現(xiàn)在將使用一個基本的for循環(huán)(但是當我們重構(gòu)代碼時,將會使用filter )。

下面是一個偽代碼的例子,它有比較多的語言描述:

function selectEvenNumbers
create an array evenNumbers and set that equal to an empty array
for each element in that array
  see if that element is even
    if element is even (if there is a remainder when divided by 2)
      add to that to the array evenNumbers
return evenNumbers

下面這段偽代碼比較簡潔:

function selectEvenNumbers
evenNumbers = []
for i = 0 to i = length of evenNumbers
  if (element % 2 === 0) 
    add to that to the array evenNumbers
return evenNumbers

只要你能把它逐行地寫出來,并且理解每一行的邏輯,用哪種方式并不重要。

最后還要回顧一下,確保自己沒有走偏。

5. 把偽代碼翻譯成真正的代碼并進行調(diào)試

當偽代碼被準備好之后,就可以把每一行偽代碼用自己正在使用的語言實現(xiàn)了。在這個例子中我們將使用JavaScript。

如果你把偽代碼寫在了紙上,那么就把它作為注釋輸入到自己的代碼編輯器中,之后再替換為代碼中的每一行。

然后我調(diào)用這個函數(shù),并給它一些我們之前使用過的樣本數(shù)據(jù)集。可以用它們來檢查代碼執(zhí)行的結(jié)果是否和預期一致。還可以編寫測試用例來檢查實際的輸出是否符合預期。

selectEvenNumbers([1])
selectEvenNumbers([1, 2])
selectEvenNumbers([1, 2, 3, 4, 5, 6])
selectEvenNumbers([-200.25])
selectEvenNumbers([-800.1, 2000, 3.1, -1000.25, 42, 600])

我通常在每個變量或者每一行后面都使用console.log()。這將會幫助我檢查變量值和代碼是否符合預期。通過這種方法,可以很容易的發(fā)現(xiàn)代碼中的問題。下面的例子是我在運行時會檢查哪東西。在我所有的代碼中都會這樣做。

function selectEvenNumbers(arrayofNumbers) {
  let evenNumbers = []
  console.log(evenNumbers) // I remove this after checking output
  console.log(arrayofNumbers) // I remove this after checking output
}

最后使每一行偽代碼都有對應的真實代碼。//后面是偽代碼,其它部分是用JavaScript實現(xiàn)的真實代碼。

// function selectEvenNumbers
function selectEvenNumbers(arrayofNumbers) {
  // evenNumbers = []
  let evenNumbers = []
  // for i = 0 to i = length of evenNumbers
  for (var i = 0; i < arrayofNumbers.length; i++) {
    // if (element % 2 === 0) 
    if (arrayofNumbers[i] % 2 === 0) {
      // add to that to the array evenNumbers
      evenNumbers.push(arrayofNumbers[i])
    }
  }
  // return evenNumbers
  return evenNumbers
}

為了避免混淆,我去掉了偽代碼。

function selectEvenNumbers(arrayofNumbers) {
  let evenNumbers = []
  for (var i = 0; i < arrayofNumbers.length; i++) {
    if (arrayofNumbers[i] % 2 === 0) {
      evenNumbers.push(arrayofNumbers[i])
    }
  }
  return evenNumbers
}

有時候,初級開發(fā)人員會被語法所困擾,導致難以繼續(xù)前進。記?。赫Z法會隨著時間的推移而逐漸熟練起來。在編碼的時候因為語法問題去翻參考材料并不丟人。

6. 簡化并優(yōu)化你的代碼

你可能已經(jīng)注意到,簡化和優(yōu)化是經(jīng)常性的話題。

“簡單性是可靠性的先決條件?!?br>——荷蘭計算機科學家Edsger W. Dijkstra,計算科學研究領(lǐng)域的先驅(qū)

在這個例子中,優(yōu)化的方法之一就是通過使用filter 返回一個新數(shù)組來過濾原來數(shù)組中的項。這樣我們就不用再去定義另外一個變量evenNumbers,因為filter 將返回一個新的數(shù)組,其中包含與過濾器匹配的元素并復制一個新的數(shù)組。 這樣就不會改變原來的數(shù)組。我們也不用使用for循環(huán)來進行遍歷。過濾器將會遍歷每個項,如果在數(shù)組中的元素符合條件就返回true,否則就返回false將其忽略。

function selectEvenNumbers(arrayofNumbers) {
  let evenNumbers = arrayofNumbers.filter(n => n % 2 === 0)
  return evenNumbers
}

簡化和優(yōu)化代碼可能需要迭代多次,以確定進一步簡化和優(yōu)化代碼的方法。

這里有一些需要牢記的問題:

簡化和優(yōu)化的目標是什么?目標會被你的團隊風格或個人喜好所左右。是盡可能地壓縮代碼還是使代碼更易閱讀? 如果是后者,你可能會用多帶帶的代碼行來定義變量或計算某些變量,而不是試圖在一行中做這些事。

怎樣做才能使代碼容易閱讀?

還有沒有多余的步驟可以去掉?

有沒有變量或函數(shù)始終沒有被用到過?

是不是存在重復的步驟?看能不能在另外一個函數(shù)中定義它們。

有沒有更好的處理邊界問題的辦法?

編寫程序的本意是為了供人閱讀,只是順便讓計算機能夠執(zhí)行它。
——“計算機程序的結(jié)構(gòu)與解釋”作者Gerald Jay Sussman和Hal Abelson

7.調(diào)試

這一步應該貫穿始終。在調(diào)試的過程中,您會很容易發(fā)現(xiàn)邏輯上的錯誤或漏洞。要充分利用集成開發(fā)環(huán)境(IDE)和調(diào)試器。當我遇到bug時,會逐行跟蹤代碼,來檢查是否存在不符合預期地方。以下是我使用的一些技巧:

實用控制臺可以查看錯誤信息,有時候它會告訴我需要檢查哪一行,這就給了我一個大概的思路:從哪里開始。盡管有時候問題并不在提示給出的那一行。

注釋掉某些代碼塊或者行,并輸出調(diào)試信息,來檢查剩余的代碼是否能正常運行??梢愿鶕?jù)實際情況對代碼進行注釋。

使用不同的測試數(shù)據(jù),看看代碼是否仍然可以工作。以此來檢查是否存在我沒有想到的情況。

如果想要嘗試另外一種完全不同的方法,可以保存不同版本的文件。我可不想在恢復原來代碼的時候后悔莫及!

最有效的調(diào)試工具是仔細的思考,再加上輸出清晰的調(diào)試信息。
——普林斯頓大學計算機科學教授Brian W. Kernighan

8.添加有效的注釋

很有可能在一個月之后你會忘記自己的代碼都是什么意思,使用你代碼的其他人可能也不知道。這就是為什么要添加有效的注釋的原因:為了讓你在回頭看這些代碼時節(jié)省時間。

不要這樣去注釋:

// 這是一個數(shù)組,并且遍歷它

// 這是一個變量

我試著做一些簡要、高級的注釋,在出問題的時候可以幫我搞明白這段代碼到底是起到什么作用。尤其是在處理更復雜的問題時非常有用。它有助于理解某個特定功能在做什么以及為什么這樣做。通過使用清晰的變量名、函數(shù)名和注釋,你(和其他人)應該能夠理解:

這段代碼是做什么用的?

它是怎樣工作的?

9.通過代碼評審獲得反饋

從你的團隊成員、教授和其他開發(fā)者那里得到反饋。檢查堆棧是否會溢出??磩e人如何解決這個問題并從中吸取教訓。有時解決問題的方法有好幾種。把它們都找出來,這樣你進步會很快。

別在意你寫出良好風格的代碼會花費多少時間,因為一旦你寫出了糟糕的代碼,那將會更慢。
——Bob Martin,軟件工程師,敏捷宣言的合著者之一

10.實踐,不停的實踐

哪怕是經(jīng)驗再豐富的開發(fā)人員也總是在不停的實踐與學習。如果你得到了有用的建議,那么就要去照著做。重復做相同或類似的事情,不停的鞭策自己。隨著一個又一個的問題的解決,最終你會成長起來。在每一次成功之后,一定要對問題進行回顧。記住,編程和任何事一樣,會隨時間的推移變得更加簡單、更加自然而然。

歡迎掃描二維碼關(guān)注微信公眾號:充實的腦洞,第一時間推送我翻譯的國外最新技術(shù)文章。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/87282.html

相關(guān)文章

  • 2017-08-15 前端日報

    摘要:前端日報精選變量聲明與賦值值傳遞淺拷貝與深拷貝詳解淺談自適應學習比你想象的要簡單常見排序算法之實現(xiàn)世界萬物誕生記中文深入理解筆記與異步編程譯不可變和中的知乎專欄譯怎樣避免開發(fā)時的深坑瘋狂的技術(shù)宅在翻譯網(wǎng)格布局掘金詳解改變模糊度亮 2017-08-15 前端日報 精選 ES6 變量聲明與賦值:值傳遞、淺拷貝與深拷貝詳解淺談web自適應學習 React.js 比你想象的要簡單常見排序算法之...

    xinhaip 評論0 收藏0
  • 怎樣處理 Safari 移動端對圖片資源的限制

    摘要:可能部分限制已經(jīng)不再適用。當移動端的瀏覽器加載了到的圖片數(shù)據(jù)后,就會停止加載其他圖片,甚至瀏覽器還會崩潰。大多數(shù)網(wǎng)站都不會受到這條限制的影響,因為保持頁面合理的大小通常是一種很聰明的做法。替換掉屬性后,舊的圖片數(shù)據(jù)最終得到了釋放。 原文作者:Thijs van der Vossen 本文翻譯自《How to work around the Mobile Safari image res...

    Astrian 評論0 收藏0
  • 】你可能不需要派生狀態(tài)

    摘要:所有派生狀態(tài)導致的問題無異于兩種無條件的根據(jù)來更新無論和是否匹配來更新。派生狀態(tài)最常見的錯誤就是將這兩者混和在一起。因此通常被用于性能優(yōu)化而不是來判斷派生狀態(tài)的正確性。我們可以使用派生狀態(tài)來存儲過濾列表這種方式避免了重新計算。 原文鏈接:https://reactjs.org/blog/2018... 翻譯這篇文章的起因是因為在一次需求迭代中錯誤的使用了getDerivedState...

    dinfer 評論0 收藏0
  • 】this 是什么?JavaScript 對象的內(nèi)部工作原理

    摘要:關(guān)鍵字會實例化一個新的對象實例,并在執(zhí)行構(gòu)造函數(shù)時將指向該實例。原文鏈接譯是什么對象的內(nèi)部工作原理 原文鏈接:What is this? The Inner Workings of JavaScript Objects (需要梯子) 原文作者:Eric Elliott 譯文永久鏈接:【譯】什么是 this?JavaScript 對象的內(nèi)部工作原理 譯者:士心 翻譯目的:函數(shù)動...

    Hwg 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<