除了上篇所說的做法與心態上出奇制勝外。
我們再導入一些實質的SOP工具,幫助我們更有效率的達陣得分。而真正要看見這些工具展現的地方,就要來到終極戰場: Debugging
不會debug的前端工程師,同樣是不qualified的工程師。
工程師常開玩笑說R&D就是repeat和debug,若工作會一直repeat自己就要檢討,是不是有些事情要讓robot去做? 而不是自己就是那個robot,沒有robot就寫一個robot。至於debug就是資深工程師真正展現身手的時候了。
一個bug搞死(不只)一個年輕工程師,這是很常發生的事情。
我年輕的時候也是會有遇到一個禮拜還沒有解出一個bug的窘境。若你沒有過因為想解決一個bug,搞到看見凌晨四點的天空的話,那你離資深工程師只會越來越遠。
工欲善其事,必先利其器
自從Chrome瀏覽器於2008年底開放下載後,其好用的開發者工具,造福許多陷在bug海中的網頁開發者們。那是
Console、Sources、Elements、NetWork這幾個最常用。其他還有Audit(Lighthouse)、Performance、Application等。
其中Sources區塊是前端工程師很好拿來debug的工具。基本的不說,它可以在網站執行階段,觀看callstack,知道上一層是哪個function的call的,也可以更改執行階段的變數值,動態塞入工程師想測試的資料。
還有Preserve log / Disable cache/ 模擬slow 3G等功能。
網路上很多chrome dev tools功能的介紹文章,本篇不是介紹功能,請自行搜尋google。
公司沒有資深人員可以review code? 就算有資深的人他也沒有時間? 那找外面的人跟你討論總可以吧? 找個你可信任的前同事或同學跟你一起討論程式碼。不用整個專案給對方看,而是拿出那一段程式碼討論即可。
像我們團隊每週會固定例會做code review,團隊中所有人都會參加(code review meeting)。review時我們會依照我們之前訂定的撰寫規範來討論。
若等不及每週的code review meeting,也可以在每天早上站會提出問題,尋求其他團隊成員pair review或pair programming。
至於使用的工具有很多,當然最快就是打開vs code,reviewer走過去對方位置直接看直接討論,或者commit到git後使用diff工具,或者pull request / merge request到要release的分支,由資深人員直接在git上review後accept或reject。
review的過程不是為了給資深同仁或者主管看說,「你看,我有做事情...」,並不是這樣。
而是藉由review的過程中,激發出更多想法與討論,自己或者對方才有可能朝向更優秀的資深工程師邁進。
應觀眾要求一定要放入眾所皆知的google教我們的code review。
Jest是笑話的意思,logo是一張鬼牌滿有意思的。但測試絕對不是笑話,而是抓出鬼牌。
一個簡單的Modal測試如下,檢測該Modal有無成功渲染出來。
describe('測試 <Modal /> 組件', () => {
it('測試 Modal 是否正常顯示', () => {
const msg = '購物車是空的'
const { container, queryByText } = render(<Modal content={msg} title="提示" />)
expect(queryByText(msg)).toBeInTheDocument()
expect(container).toMatchSnapshot()
})
})
為什麼培養寫單元測試的習慣最難,因為當大家還沒有感受到unit test的好處時,其實是很難在時程每次都很趕的狀況下,確實執行單元測試。
因次目前團隊透過之前所說的在每週例會刷leetcode的時候,強迫團隊成員先想單元測試,再寫leetcode的答案。也就是測試先行(TDD)的概念。
唯有透過這種方式,團隊成員才會發現原來先想測試,對之後開始寫leetcode答案會想得比較仔細!?漸漸的團隊成員就會自動自發地,在專案中先寫測試再寫程式。
然後最後是與後端的API測試,之前討論要先寫API文檔,寫好之後若是後端還沒有完成所有API功能,前端可利用Mock Server先做一個傳假資料的後端Server。使用json-server非常容易做到。
首先安裝json-servernpm install -g json-server
創建一個db.json,寫入跟後端定好的每個API該回傳的值。如下購物車step2/step3範例。
{
"checkout": {
"isSuccess": true,
"orderId": 16899801,
"message": "Successfully Checkout!"
},
"complete": {
"order": {
"id": 5834454,
"time": "1570177320.33638"
},
"payment": {
"amount": 1400,
"bank": "永豐銀行",
"account": "20191022019102"
}
}
}
最後把json-server run起來就ok了。json-server ./db.json
然後用postman去打localhost 3000 port就可以拿到資料。
除了這些幫助debug的工具外。另外還有各種debugging後解決的奇淫技巧,再此展現。
真實在專案中發生的狀況是,原本埋追蹤碼用的中繼頁,我們使用document.ready,造成追蹤碼api的js還沒載入成功時,就已經執行document.ready內的傳送追蹤碼內容,而造成錯誤。
所以改用$(window).load。$(window).load會等「DOM 建立好」並「載入所有檔案後」才執行,避免追蹤碼尚未載入完成而遺漏數據。但若追蹤碼回應時間過久,我們依然設定最長等待 2 秒後強制跳轉下一步。
function redirectToStep2() {
location.replace('/Checkout');
}
window.onload = function () {
redirectToStep2()
}
setTimeout(redirectToStep2, 2000)
try {
Promise.all([PromiseTracking1, PromiseTracking2]).then(result => {
// All Finished
locationHref(link)
})
} catch (error) {
// Throw error
locationHref(link)
throw new Error('Tracking Code Error:', error)
} finally {
// Timeout
setTimeout(() => {
locationHref(link)
}, sendTrackingCodeTimeOut)
}
let cate = [ ...state.cate]
if (state.indexArray && state.indexArray.length > 1) {
for (let i = 0; i < state.indexArray.length - 1; i++) {
const ai = parseInt(state.indexArray[i])
cate = [...cate[ai].cate]
}
}
const lastIndex = state.indexArray[state.indexArray.length - 1]
cate[index].cate = json.categoryResult.cate
this.setState({
cate
})
因為每一次點擊tree的子分類才去要下面的資料json.categoryResult.cate,所以透過搜尋樹去拿到展開的最下面一個節點,並將從api拿到的分類資料合併進去,然後重新render。
其他像埋ga tracking code, seo, service worker, browser cache機制, 離線瀏覽, 爬蟲等。都是邁向資深前端工程師,必須知道的。
前端技能都突破後,我們就來看後端如何深入。