# +_q11~q17 code review # Chris q6~q10_code review 想看哪幾題: ## q12 #### if...else 目前這樣寫有點威脅感,如果(...)就這樣,不然就給你怎樣 ```javascript! if (rangeStart > 0 && rangeEnd > 0 && multipleLimit > 0) { const primeList = getPrimeListOfThisRange(rangeStart, rangeEnd); const multiplesList = getMultiplesList(primeList, multipleLimit); const allPrimeMultiples = getAllPrimeMultiples(primeList, multiplesList); return (`10~20 的質數有:${primeList}\n${showResult(primeList, allPrimeMultiples)}`) } else { throw new Error(`請輸入正數`); } ``` Chris 覺得比較好的寫法是: 區分正常和不正常部分,讓一看就知道正在處理哪個部分,所以通常會寫==如果是什麼條件,就拋錯誤==,正常情況就不會被包在 if...else 裏面,就是 early return 寫法 ```javascript! // 而且這邊可以很多條件(不用寫巢狀),而這段 if 就算消失也不會怎樣,正常 code 都不會動到,就少了威脅感 if (rangeStart <= 0 || rangeEnd <= 0 || multipleLimit <= 0) { throw new Error(`請輸入正數`); } const primeList = getPrimeListOfThisRange(rangeStart, rangeEnd); const multiplesList = getMultiplesList(primeList, multipleLimit); const allPrimeMultiples = getAllPrimeMultiples(primeList, multiplesList); return (`10~20 的質數有:${primeList}\n${showResult(primeList, allPrimeMultiples)}`) ``` ### getMultiplesList 命名 ```javascript! 命名遇到 number,要小心,number 對於問題的定義太模糊了 書上寫:遇到 number 去想它是 index 還是 total? 終究會有更貼近意義的命名,是級數的 number 嗎?還是什麼的 number,這些數字有關係嗎,一定有東西可以加進去 ``` ### fill 改寫(歐買尬) ```javascript! function generateNumberList(rangeStart, rangeEnd) { return Array(rangeEnd - rangeStart + 1).fill().map((_, index) => { return rangeStart + index; }); } // 改寫為 function generateNumberList(rangeStart, rangeEnd) { return Array(rangeEnd - rangeStart + 1).fill(rangeStart).map((init, index) => { return init + index; }); } ``` ```javascript! function generateNumberList(rangeStart, rangeEnd) { return Array(rangeEnd - rangeStart + 1).fill(rangeStart).map((init, index) => { return init + index; }); } export function getMultiplesList(primeList, multipleLimit) { return primeList.map((prime) => { const multipleCount = Math.floor(multipleLimit / prime); return generateNumberList(1, multipleCount) .map(multiple => multiple * prime); }) // [9, 7, 5, 5] // return Array(multipleCount).fill(0).map((_, numberIndex) => { // return (numberIndex + 1) // }); // [ [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ], // [ 1, 2, 3, 4, 5, 6, 7 ], // [ 1, 2, 3, 4, 5 ], // [ 1, 2, 3, 4, 5 ] // ] // }) } ``` ### 關於寫 code 的整理 ```javascript! 現在自己看自己的 code 就是覺得還 ok 吧,但被 Chirs 整理過後就變成大改造,可以繼續練習思考重構和閱讀性這件事情 QQ 像是有些東西是不是拿到就要馬上存起來做計算,或是要再跑下一次迴圈重新拿再做計算? 例如我 q12 先在一個 算倍數的 function 送 質數陣列和 100 的限制當參數,拿到 11 可以乘以 9 次 的 [1,2,3,4,5,6,7,8,9] 和其他的質數要乘以幾次 然後再做一個 function 放 這個倍數 function 和質數陣列進去算乘積 >> 啊我怎麼不在第一支 function 的時候就乘起來!就不用再用第二個 function 再跑一次迴圈了:) 尬電,不知道自己在想什麼,被一支 funciton 做一件事情蒙蔽了 最直接反應是效能,但如果沒有比較好讀,就會選擇分開寫 ``` ### q12.test ![image](https://hackmd.io/_uploads/Byxa5trj0.png) ```javascript! 測試不應該出現 console.log 原因是因為我 q12 這隻 function 是從 main 來的,讀到 main 的時候會全部跑一次,main 裡面就有 console.log ``` ### 測試是出貨檢驗報告 ```javascript! 當品管收到檢驗報告的時候,他們會進行相同手法的測試,做一樣的事情看是否可以得到相同結果。 我現在的測試 1/ 的說明文字只有說要列出倍數,但是沒有說倍數是什麼,所以出錯了可能也看不出來。 所以可以:把範圍縮小,然後列出來 會比較好,很快的可以明確清楚知道是要檢驗哪些會比較好。 ``` ![image](https://hackmd.io/_uploads/rJZ04qHjR.png) ### 有 throw new Error 記得寫 try...catch 不然要 throw 去哪啦!直接噴錯! ## q15 ### 為什麼會覺得拿 index 來操作不好 ```javascript! Chris:index 是在寫程式的,是工程師會想到的事情,有時候寫程式會讓一切看起來像在"操作現實世界事物的感覺"。 < 寫 code 描述現實事物,會比拿來堆砌流程好很多 > ``` ### 控制迴圈只有一個出口一個入口 ```javascript! function getTotalCargo(equipmentList, carWeightLimit) { const sport = Array(3).fill(0); let currentWeight = 0; while(currentWeight < carWeightLimit) { const currentItemIndex = getRandomItemIndex(equipmentList); let randomItemWeight = equipmentList[currenItemIndex].weight; if (currentWeight + randomItemWeight > carWeightLimit) { break; } currentWeight += randomItemWeight; sport[currentItemIndex] += 1; } return { sport, currenWeight }; } ``` 改寫為 ```javascript! function getTotalCargo(equipmentList, carWeightLimit) { const sport = Array(3).fill(0); let currentWeight = 0; let currentItemIndex = getRandomItemIndex(equipmentList); let randomItemWeight = equipmentList[currentItemIndex].weight; do { currentWeight += randomItemWeight; sport[currentItemIndex]++; currentItemIndex = getRandomItemIndex(equipmentList); randomItemWeight = equipmentList[currentItemIndex].weight; } while (currentWeight + randomItemWeight < carWeightLimit); return { sport, currentWeight }; } ``` ### 這樣是拿容器裏面的 code 來用 ```javascript! sport[currentItemIndex]++; // 不用選,直接是 sport 這個容器隨機骰到哪個 index 就會幫我選好 // 不然我原本寫這樣哈哈哈哈哈哈 if(index === 0) { 搬什麼 } if(index === 1) { 搬什麼 } if(index === 2) { 搬什麼 } ``` ### 如果要用 constructor ```javascript! 車也要做出來喔,磅秤要有一個 is okay? okay 再放上車,建構物件的時候會很囉唆,很多細小行為都可以去定義它,呼叫他的時候很愉快,寫一個車滿了嗎,還沒繼續放,就目前這樣算是做一半,想像一個場景,有工人在把這些東西搬上車,步驟是怎麼樣?就真的要想好那些步驟器材物件,加上貨物重量也要定義好,要有磅秤、重量登記版等等等,不物件的寫法就很像在空氣中!就在你心中算而已! ``` ## q17 ### == null 就是 === null || === undefined ### 真心建議先跑一個迴圈做檢查,確定沒問題再開始做事 ```javascript! votingInfo.forEach(info => { if(info.votes !== undefined && info.rank !== undefined){ info.rank.forEach((info.rank.forEach((candidate, index) => { totalScoresList[candidate - 1] += info.votes * scoreStandard[index]; }); } else { throw new Error(`請輸入完整投票資訊`); } return totalScoresList }); ``` 改為 ```javascript! votingInfo.forEach(info => { if (info.votes == null || info.rank == null) { throw new Error(`請輸入完整投票資訊`); } }); votingInfo.forEach((info) => { info.rank.forEach((candidate, index) => { totalScoresList[candidate] += info.votes * scoreStandard[index]; }); }) return totalScoresList ``` #### votingInfo 這個 info 就是在切版的時候用 contianer . box 一樣道理 ```javascript! const votingInfo = [ { votes: 51, rank: [1, 3, 2, 4] }, { votes: 5, rank: [3, 2, 4, 1] }, { votes: 23, rank: [2, 3, 4, 1] }, { votes: 21, rank: [4, 3, 2, 1] } ]; // 一定有一個更好的詞可以用 result 是結果 但是還沒算而已 ``` #### info 可以改成 item ```javascript! item 就會隱喻這個東西是一個 Array/List 你就會知道,哇這是一個陣列,可以 forEach 嗎來看看裡面有什麼東西 ``` ```javascript! votingInfo.forEach(info => { if (info.votes == null || info.rank == null) { throw new Error(`請輸入完整投票資訊`); } }); ``` #### 變工程師,思想上會有些模糊地帶需要釐清,學會精準用字 #### index 巧妙之處 ```javascript! export function getCandidateScoresList(votingInfo) { let totalScoresList = [0, 0, 0, 0]; const scoreStandard = [4, 3, 2, 1]; votingInfo.forEach(info => { if (info.votes == null || info.rank == null) { throw new Error(`請輸入完整投票資訊`); } }); votingInfo.forEach(info => { info.rank.forEach((candidate, index) => { totalScoresList[candidate - 1] += info.votes * scoreStandard[index]; ----> 這邊的 [candidate - 1] 可能會有點難讀 }); }) return totalScoresList } ``` ```javascript! export function getCandidateScoresList(votingInfo) { let totalScoresList = [0, 0, 0, 0, 0]; ----> 改這樣 const scoreStandard = [4, 3, 2, 1]; votingInfo.forEach(info => { if (info.votes == null || info.rank == null) { throw new Error(`請輸入完整投票資訊`); } }); votingInfo.forEach(info => { info.rank.forEach((candidate, index) => { totalScoresList[candidate] += info.votes * scoreStandard[index]; ----> 這邊就真的是候選人1234了 }); }) return totalScoresList } ``` ![image](https://hackmd.io/_uploads/ByG5yCrs0.png) ```javascript! export function q17(votingInfo) { const totalScoresList = getCandidateScoresList(votingInfo); return totalScoresList.map((score, scoreIndex) => { if (scoreIndex === 0) return ''; ---> 回傳就會變成五個元素,再把第一個元素 Bang 掉,下方 return 就會 1234 return `候選人${scoreIndex} 得 ${score} 分`; }).join('\n'); } ``` ### ```javascript! const votingInfo = [ { votes: 51, rank: [1, 3, 2, 4] }, { votes: 5, rank: [3, 2, 4, 1] }, { votes: 23, rank: [2, 3, 4, 1] }, { votes: 21, rank: [4, 3, 2, 1] } ]; // Chris 會想用成這樣來做事,這樣後面的東西直接可以用比較合乎邏輯的 index 來做事 const votingInfo = [ [51, 1, 3, 2, 4], [5, 3, 2, 4, 1], [23, 2, 3, 4, 1], [21, 4, 3, 2, 1] ]; ```