-
Notifications
You must be signed in to change notification settings - Fork 62
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
423 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
# 常見重點整理 | ||
|
||
因為有些事情在計畫裡面提過很多遍了,不想每一次都重新再講一遍,因此拿這篇來當重點整理,講一些很重要的地方,提醒大家一下。有些可能之前忘了提到,或者是改作業的時候沒有特別挑出來,總之請以這篇為準。 | ||
|
||
## 什麼是不好的 code? | ||
|
||
不好 code 的定義因人而異,但有很多工程師都有一個特點,那就是都有著「程式碼潔癖」。 | ||
|
||
這也是我第一份實習時我老闆很強調的一件事,在寫程式碼的時候你必須要細心,必須要對自己寫出的 code 負責,至少要讓你的 code 「看起來」是好的。 | ||
|
||
那到底怎樣才是好的? | ||
|
||
這答案有可能出乎你意料,因為聽起來搞不好比你想像中的簡單,可是你卻發現自己多數時候都沒有做到。 | ||
|
||
兩點答案給大家: | ||
|
||
1. 符合命名慣例以及命名一致性 | ||
2. 合理的變數名稱 | ||
|
||
先介紹三種常見的命名慣例以及它的專有名詞: | ||
|
||
### 駝峰式命名(Camel case) | ||
|
||
人如其名,駝峰就是會一高一低的,所以比如說你有一個 handle add post 的 function,就會叫做 `handleAddPost`,單字之間不空格,而是直接連起來,但是連起來的第一個字要大寫。 | ||
|
||
駝峰又有分兩種,分別是小駝峰(lower camel case)跟大駝峰(upper camel case)。 | ||
|
||
第一種很簡單,就是開頭是小寫,也就是我們上面說的 `handleAddPost`。 | ||
|
||
第二種就只是開頭變成大寫而已,變成:`HandleAddPost`,而第二種大駝峰也被叫做 Pascal Case。 | ||
|
||
### 蛇型命名(Snake case) | ||
|
||
其實蛇就是底線的意思啦,因此同樣以 handle add post 這個 function 來講,會取叫 `handle_add_post`,利用底線來連接單字,然後全部都小寫。 | ||
|
||
### 烤肉串命名(Kebab case) | ||
|
||
Kebab 是烤肉串的意思,那哪一個符號看起來很像那根棍子呢?就是 `-`,所以看起來會像是 `handle-add-post` 這樣,這個就叫做 kebab case。 | ||
|
||
講完了這三種常見的命名慣例以及名詞之後,就可以來看看不同地方的命名慣例是用哪一種。沒錯,不同程式語言或是不同環境,使用的命名慣例會不一樣,所以大家需要一點時間熟悉一下。 | ||
|
||
雖然這是命名慣例,不是強制的,但基本上因為所有人都是這樣遵從這套慣例在開發,如果沒有照慣例的話,就會比較難跟其他人合作,你寫的 code 就會變成所謂的「不好的 code」。 | ||
|
||
### JavaScript | ||
|
||
在 JS 裡面,大家習慣的是 lower camel case,也就是 `handleAddPost` 這一種。大家仔細想一下那些 WebAPI 或是內建的 function 就知道了,例如說: | ||
|
||
1. setTimeout | ||
2. requestAnimationFrame | ||
3. getElementById | ||
|
||
這些都是用 lower camel case 在命名的。當然不止 function,變數也會這樣子命名。 | ||
|
||
所以除非有特殊理由,不然你不應該在 JS 裡面寫出: | ||
|
||
1. set_timeout | ||
2. SetTimeout | ||
3. Set_timeout | ||
|
||
這幾種的命名方法 | ||
|
||
不過第二個那個開頭大寫的駝峰式,有些人可能會有印象看過,例如說: | ||
|
||
1. XMLHttpRequest | ||
2. Number | ||
3. Set | ||
|
||
為什麼這些可以開頭大寫呢?因為這些東西基本上都可以算是一個「class」,就是物件導向那個 class。在物件導向裡面,class 的命名慣例就是大寫開頭。 | ||
|
||
所以 JS 基本上都是小寫駝峰式,但有其他好理由的話,可以用大寫駝峰式。或者是之後大家會學到的 React,component 也都會用大寫開頭的駝峰式來命名。 | ||
|
||
最後還有一種,那就是常數,通常都是不會變的東西,但定義其實也沒那麼嚴謹,這種的就會是 snake case + 全大寫。 | ||
|
||
例如說圓周率 PI,就會是 `Math.PI`,例如說第八週的作業裡面有 client id,你就可以定義成:`const CLIENT_ID = 'xxxx'`,因為這在這整個程式裡面是不會變的值,不過這點之前沒有特別提是因為就算你取做 `const clientId = 'xxx'` 我也覺得 OK,這邊倒是還好。 | ||
|
||
但除此之外,請一律使用小寫駝峰式。 | ||
|
||
* isDelete(O) | ||
* is_delete(X) | ||
* is_delete(X) | ||
* IsDelete(X) | ||
|
||
是否刪除就是`isDelete`,不是`is_delete`也不是`is_Delete`,更不是`IsDelete`。 | ||
|
||
### 資料庫 table 與欄位 | ||
|
||
資料庫走的是 snake case 為主,然後 table 名稱的慣例是複數,所以使用者資料會叫做 `users`。 | ||
|
||
* users(O) | ||
* Users(X) | ||
* user(X) | ||
|
||
欄位名稱的話就是 snake case,例如說建立時間,會是這樣: | ||
|
||
* created_at(O) | ||
* createdAt(X) | ||
* CreatedAt(X) | ||
* Created_At(X) | ||
* created-at(X) | ||
|
||
使用者的大頭貼可能會是這樣: | ||
|
||
* user_avatar(O) | ||
* userAvatar(X) | ||
* UserAvatar(X) | ||
|
||
Week17 講到 ORM 之後,通常只會關注 ORM 裡面我們的 model 的 naming,例如說我們用 JS,所以程式裡面就會是 createdAt,然後資料庫長怎樣就交給 ORM 處理,因此有可能跟上面講的會不一樣。 | ||
|
||
### Url | ||
|
||
網址的話其實慣例沒那麼嚴格,比較常見的兩種我都有看過,例如說: | ||
|
||
1. handle_add_post | ||
2. handle-add-post | ||
|
||
不過我自己比較喜歡的是第二種 kebab case,然後這邊順便幫大家補充一個小知識,像是那種部落格或英文網站,通常都會有一個單一文章的網址,例如說我的 medium 文章: | ||
|
||
https://hulitw.medium.com/lidemy-mentor-program-4th-updates-c344302c8a2d | ||
|
||
後面那一段 `lidemy-mentor-program-4th-updates-c344302c8a2d`,這個有個專有名詞叫做 slug | ||
|
||
你用 `slug webpage` 去找可以找到滿多資料,這個通常會與 SEO 有關。 | ||
|
||
以上差不多就是幾個課程中有碰到的地方的 naming convention,這邊還沒提到變數命名是否恰當,光是變數名稱的慣例就已經先死一堆人了。 | ||
|
||
這種命名慣例如果不一致,例如說 JS 變數硬要叫做 IsDelete,然後其他地方都符合 camelCase 的話,就好像你在一篇文章裡面在再不分,對文字(對程式碼)比較敏感的人,就會直接覺得這一段程式碼寫得很爛,因為連在再都分不清楚。 | ||
|
||
這種細節才是最應該注意,然後影響也會比你想像中的大的地方。 | ||
|
||
## 變數命名 | ||
|
||
先給大家一個大原則,如果你不知道某個東西是否可以縮寫或簡稱,你就全部寫下去就沒事了,例如說 `lottery` 不要簡寫成 `lotto`,`controller`不要簡寫成 `ctler` 之類的,寫全稱頂多就是變數名稱長一點,但如果寫簡稱然後並不是一種慣例的話,那一樣就會被認定為是不好的 code。 | ||
|
||
舉例來說,event handler 傳進來的參數 event,常見的簡寫就是 evt 或是 e,這些都還可以接受,但像是 target 就沒有簡稱為 tar 或是 tgt 這種用法,所以不能簡稱。因此這些其實是很憑經驗的,經驗不足的時候就乖乖寫好寫滿就好,不要自作聰明。 | ||
|
||
然後 function 基本上都會搭配動詞開頭,像是第八週裡面的 `getGames` 或是 `getStreams` 之類的,就是去拿什麼東西,然後像 `setName` 或是 `setTitle`,一看也知道是要去設定一些什麼,get 跟 set 是兩種最常見的動詞。 | ||
|
||
如果你不知道哪些動詞很常用,請參考我之前提供過的所有範例程式碼,已經出現過很多範例了。然後通常很少有 function 不包含動詞,因為意義不明,不知道這個 function 到底要做些什麼。 | ||
|
||
## 程式碼排版 | ||
|
||
以後你去面試的時候,有可能面試官會先去你的 GitHub 看你的程式碼,所以沒有人會管在你的電腦上看起來怎樣,大家只會去看在 GitHub 上面顯示長怎樣。 | ||
|
||
所以請把自己編輯器的排版調整好,我都是統一設成只用 space 不用空格,然後一次空兩格之類的,在 GitHub 上顯示沒有出問題過。 | ||
|
||
## 資訊安全 | ||
|
||
請永遠記住一件事情,在考慮資訊安全的時候,你要假設一件事情,那就是: | ||
|
||
> 程式碼都是公開的 | ||
這是什麼意思? | ||
|
||
例如說部落格後台管理的功能,有些人可能會寫一個 `handle_delete_post.php` 來處理刪除文章,然後裡面就是接收一個 id,把文章刪除掉,沒有做任何的驗證。 | ||
|
||
為什麼沒有做驗證?因為這一頁照理來說只有管理員看得到,所以應該沒差吧? | ||
|
||
這時候如果你想到我上面說的原則,「程式碼都是公開的」,你就知道這個檔案,這個 url 是會被發現的,一旦被發現之後,任何人都可以刪除文章。所以這是不對的,正解是做好權限管理,檢查 session 裡面是不是有登入,沒登入就把使用者導去其他地方。 | ||
|
||
儘管程式碼被別人看光,他也沒辦法破解這機制,因為他沒有登入,所以就不會被設定 session,裡面就不會有東西。 | ||
|
||
這點很重要,超級重要,權限管理是很多人會忘記的地方。當你在做 CRUD 的時候,或是在看別人程式碼的時候,一定要有的一個想法是:「這段 code 會不會可以讓其他人執行?」,只要你有把這個想法記住,就可以少寫很多漏洞出來。 | ||
|
||
再來第二點是: | ||
|
||
> 不要存著僥倖心態 | ||
這點之前我自己在示範的時候其實沒有做得很好,例如說留言板我只對 nickname 跟 content 做跳脫,沒有對 id 或是建立時間做跳脫。但其實呢,這是應該要做的,你應該把任何要輸出資料的地方都編碼過後再輸出,才能確保不會有問題。 | ||
|
||
Week17 以後我們用的 template engine 就是這樣,永遠都預設把你要輸出的東西做編碼以後才輸出,而不是直接輸出,就可以避免掉很多的 XSS 攻擊。 | ||
|
||
所以無論你是要輸出 id 還是你確認輸出的只會是數字,都可以 escape 以後再輸出,比較保險一點。 | ||
|
||
### 前端檢查 vs 後端檢查 | ||
|
||
承上,請大家再記住一件事情,那就是: | ||
|
||
> 前端做資料檢查,只是為了增進使用者體驗,後端做資料檢查才是真的檢查 | ||
原理很簡單,假設你註冊的時候前端會檢查使用者名稱是不是 > 8 個字,沒有的話就會跳錯誤出來,所以使用者還沒發 request 就可以知道有錯。 | ||
|
||
但如果你後端沒做檢查,我一樣可以繞過瀏覽器去打這個 endpoint,我自己帶資料去打就好,根本不需要過瀏覽器,那就根本不會執行到你寫的 JS 驗證邏輯,所以那些邏輯完全沒有任何效力,只是增進使用者體驗,只要後端沒檢查,我資料就一定寫得進去。 | ||
|
||
這點也很重要,大家一定要記住。所以後端驗證一定要做,前端可做可不做。 | ||
|
||
其他相關概念請參考 Week11 的參考範例,裡面也有講到很多資訊安全相關的概念。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.