[TOC]
## Code review #1 by Angela
### Q16
* 可以把題目設定的數字都寫得更彈性,讓程式可以額外設定
```javascript
// 例如我目前就把偏移量宣告一個變數,所以在跑messageOfQ16的時候就可以先調整shift的值
const shift = 3;
console.log(messageOfQ16(answer, shift));
// 所以,也可以把5個字母的5設定出來
```
* readline使用reject的情境可以是:如果使用者超過某個時間沒有輸入的話就會reject
## Code review #2 by Eva
### Q17
* 可以思考完全符合業主的需求就好,還是做點彈性
* 但17題目標還是先把需求做出來就好
* 我目前的寫法是以候選人的角度,可以和以選票的角度去寫的方法比較優缺點
* 比較票數的function可以寫在另一個class裡
* 但我不會寫orz
```javascript
class Candidates {
constructor({ candidatesScores }) {
this.candidatesScores = candidatesScores || [0, 0, 0, 0];
}
get sameHighestSCoreCandidates() {
const rawScores = [
new Candidate(1).score,
new Candidate(2).score,
new Candidate(3).score,
new Candidate(4).score,
];
return rawScores.sort().filter();
}
}
```
* 命名不要怕字數很多很長,寫清楚比較重要!!
* 找出最大值可以用Math.max
```javascript
// 原本用排序來找最大值
const sortedCandidates = candidates.toSorted((candidate1, candidate2) => {
return candidate2.score - candidate1.score;
});
//使用Math.max
const scoresOfCandidates = candidates.map((candidate) => candidate.score);
const maxScore = Math.max(...scoresOfCandidates);
```
## Code review #final by Chris
### Q17
* Q17預設要練習的是什麼?
* 練習實作演算法,照別人的邏輯把code寫出來
* 資料整理也要寫成code,不然怎麼知道人工有沒有key錯
```javascript
// 我原本的寫法是一個一個把資料key進去
const candidate1 = new Candidate(1);
candidate1.setVotes("firstOrderVotes", 51);
candidate1.setVotes("fourthOrderVotes", 5, 23, 21);
const candidate2 = new Candidate(2);
candidate2.setVotes("firstOrderVotes", 23);
candidate2.setVotes("secondOrderVotes", 5);
candidate2.setVotes("thirdOrderVotes", 51, 21);
const candidate3 = new Candidate(3);
candidate3.setVotes("firstOrderVotes", 5);
candidate3.setVotes("secondOrderVotes", 51, 23, 21);
const candidate4 = new Candidate(4);
candidate4.setVotes("firstOrderVotes", 21);
candidate4.setVotes("thirdOrderVotes", 5, 23);
candidate4.setVotes("fourthOrderVotes", 51);
---
// 應該要能直接從表格中整理資料
// | # | 51票 | 5票 | 23票 | 21票 |
// | 第一順位 | 1 | 3 | 2 | 4 |
// | 第二順位 | 3 | 2 | 3 | 3 |
// | 第三順位 | 2 | 4 | 4 | 2 |
// | 第四順位 | 4 | 1 | 1 | 1 |
// 假設資料以csv傳入
const data = `51,5,23,21
1,3,2,4
3,2,3,3
2,4,4,2
4,1,1,1`;
function processData(allText) {
var allTextLines = allText.split("\n");
var headers = allTextLines[0].split(",");
const lines = allTextLines.map((strLine, index) => {
const arrLine = strLine.split(",");
const result = new Map(); // 做成Map物件是為了要迭代
headers.forEach((header, headerIndex) => {
result.set(header, arrLine[headerIndex]);
});
return result;
});
return lines.slice(1);
}
console.log(processData(data));
// [
// Map(4) { '51' => '1', '5' => '3', '23' => '2', '21' => '4' },
// Map(4) { '51' => '3', '5' => '2', '23' => '3', '21' => '3' },
// Map(4) { '51' => '2', '5' => '4', '23' => '4', '21' => '2' },
// Map(4) { '51' => '4', '5' => '1', '23' => '1', '21' => '1' }
// ]
```
> Map物件[MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/forEach)
* 盡量不要用寫死的名稱來表示有順序的東西
* 把這些order改成array,用index來代表order
```javascript
// 原本寫的
this.firstOrderVotes = [23];
this.secondOrderVotes = [5];
this.thirdOrderVotes = [51, 21];
this.fourthOrderVotes = [0];
// 改成
votes = [
[23],
[5],
[51, 21],
[0]
]
```
* 直接用整份資料的角度去寫
```javascript
// 橫列為一陣列
const votes = [51, 5, 23, 21];
const orders = [
[1, 3, 2, 4],
[3, 2, 3, 3],
[2, 4, 4, 2],
[4, 1, 1, 1],
];
// 直排為一陣列
// [總票數, 順位1, 順位2, 順位3, 順位4]
// 順位剛好等同於index
const votingCompositions = [
[51, 1, 3, 2, 4],
[5, 3, 2, 4, 1],
[23, 2, 3, 4, 1],
[21, 4, 3, 2, 1],
]
```
### 其他補充
#### 軟體工程的本質性及附屬性 from 人月神話
> 軟體的本質相當抽象,由許多概念組合而成,但無論有多少種呈現方式,其基本構造都是不變的,可區分為本質性及附屬性
* 本質性問題:不可消滅的複雜度
* 例如我最後一定要印出一行字,那`console.log`就是不可消滅的程式碼
* 附屬性問題:怎麼去解決本質性問題。我們要學習的是控制附屬性問題的厚度適當,小但足以形容問題。
* 厚度不要太小:例如要適當的命名,讓問題得以被理解
* 厚度不要太大:用了一堆花俏的技術來解決簡單的問題,殺雞焉用牛刀🔪
#### 了解JavaScript的3大方向:new, this, 繼承
* 先去了解new這個運算子在做什麼,試著實作看看
> [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new#description)
#### OOP
* 三大要素:封裝、繼承、動態連結
* Date這個物件可以幫助理解OOP的封裝,以及get, set的運作
* 永遠無法得知Date裡面到底存了什麼,只能用各種method去取得格式化後的值
