專案動機
自己平時有記帳的習慣,可以幫助釐清每個月的花費狀況。有用過幾款記帳APP,其中喜歡 CMoney 這款記帳軟體,可以替每一筆收支作細部分類,也可以按月或類別進行搜尋,還有豐富的圖示供選擇。目前正在學習網頁全端開發,便想嘗試實作網頁版的記帳專案。
專案技術
- 開發環境: Node.js + Express.js
- 為了讓網頁能在電腦上運行,選擇了 Node.js 環境架設網頁服務
- 選擇用 Express.js, 一個基於 Node.js 的 Web 應用框架,包含大量中介層 (Middleware) API,幫助快速開發伺服器端網頁服務 - 網頁前端: HTML+Handlebars+Bootstrap+CSS
- 使用 Bootstrap 來快速構建出前端元素與排版樣式,再搭配 CSS 去做細部修改
- 使用 Handlebars 模板,將後端資料嵌套到 HTML 文本中 - 網頁後端: MongoDB + Mongoose+JavaScript
- 由於是嘗試開發,因此使用非關聯式資料庫,可以讓更改資料表的成本降低
- 使用 MongoDB 的 ODM (Object Data Modeling) ,可以更方便的在 JS 物件資料,與 MongoDB 之間轉換 - 使用者相關: Passport.js+bcryptjs+Express-Session
- 使用第三方套件 passport.js 實作出使用者驗證中介層,包含本地端登入 (passport-local)與臉書登入(passport-facebook)
- 使用 bcryptjs 將使用者密碼進行加密動作,再存到資料庫中
- 採用 cookie-based 紀錄使用者憑證,確認用戶狀態
專案開發過程
開發過程中,覺得目前較能掌握的地方是非同步的寫法,這也是花最多時間的部分。此專案在非同步的部分大概寫過了三種,一開始還不太熟悉,最早的寫法,是規劃好執行流程後,依照順序寫入對應的 callback function 中,但常常會寫成 callback hell,對於程式閱讀與除錯上都不太友善;再來是使用 Promise + then 的寫法,雖然在程式閱讀上與除錯上有改善,但是沒辦法像同步寫法一樣這麼直觀,而且在程式邏輯改動的時候會比較麻煩;最後認真學好 async/await 語法糖後,只要確認好使用的函式回傳型態是 Promise,就可以很輕易的以同步寫法,撰寫非同步程式邏輯,不論在程式閱讀上、改動上或除錯上,都有很有幫助,在熟悉寫法後,在面對非同步就比較沒那麼困難了。
專案開發困難
開發過程中,遇過在路由設計上的困難。在還不熟中介層設計前,由於想要加入資料驗證與錯誤顯示,選擇多加了一些額外的路由進行驗證或錯誤頁面渲染,後來就造成在修改功能的時候,陷在除錯海中。當時便去網路上查詢別人是怎麼樣設計好路由功能,當時查到有人的路由不單單只有 (req, res) 的 callback function ,前面又多加了幾個函式,便又去深入研究一下,後來就寫了幾個前處理的中介層,讓自己的路由可以簡單化、易讀一點。
印象深刻的學習
這個專案的實作過程學了不少東西,在開發出第一版時有寫了一篇心得文,記錄下設計思考的改變歷程,而專案的第二版多了使用者驗證、錯誤訊息的顯示、還有非同步寫法優化,覺得最印象深刻的是非同步技術搭配資料庫的應用,在學會 async/await 後,改寫Mongoose非同步部分遇到一些問題,去查找文件才知道 Mongoose API 並非完全都是回傳 Promise,有的是回傳 Query。
得知這件事後,就再去尋找解決方案,從網路上與官方文件上,了解到 Mongoose 若在會回傳 Query API 上加上 exec(),便會回傳 Promise,而本來會回傳 Promise 的 API,並不支援 exec。再回去優化非同步程式後,也同時開啟 Mongoose 官方文件,確認好 API 的回傳型態後,再決定要不要加上 exec()。
未來學習方向
這次也寫到一個功能,是要同時考慮月份與類別,篩選出符合的資料,這次很單純的從資料庫撈出資料,再用陣列比對的方式篩選,但後來思考到若資料庫中資料非常多的狀況下,也許透過資料庫查詢方法,撈出特定資料較為適當。有看到 Mongoose 似乎有 Aggregate 可以提供這種功能,只是需要再花點時間研究實作細節,就放在優化清單上了!