多人協作 simple twitter 專案心得

多人協作 simple twitter 專案,是 Alpha Camp 學期三的最後一份作業。我們這組的分工是前端兩個人,後端兩個人,我負責後端。

專案成果

Demo

程式碼


我負責的任務

  • 建立 model,和建立 model 之間的關聯

  • 加入 JWT 驗證機制

  • 路由:
    • /api/admin
    • /api/followship
    • /api/chat
    • /api/user 底下的七條路由:
      /current、/top、/:id、/:id/followings、/:id/tweets、/:id/replied_tweets、/:id/likes
  • 將專案部署到 heroku

  • 撰寫 api 文件和 README

  • 在我所知的範圍內,盡量實現「不要相信前端來的資料,後端一定要再驗一次」的精神

  • 實作伺服器端的公開即時聊天功能、在資料庫保存公開聊天的歷史訊息


溝通

事前準備

如果我沒記錯的話,組員都是從 Alpha Camp 課程一路學上來的,已經減少許多溝通成本;但因為在最後一學期,前端和後端的課程是分開的,我比較顧慮和前端的溝通落差,因此在進行多人協作前,用 1.5 倍速看了一些前端課程中,關於 Vue 框架的教學影片。這讓我日後,能夠在前端進度稍微落後時,也有能力分攤一些串接 api 的工作;前端串接 api 遇到問題時,我可以在本地同時開啟後端伺服器和前端 Vue 專案,重現問題,找出原因所在。

第一次專案會議前,我把測試檔案中要求的資料庫路由規格整理出來。

工具

除了 Alpha Camp 幫我們設立的 basecamp 討論專區,第一次專案會議中,正職是產品經理的前端組員 TC,帶頭破冰,並協助定調了管理專案進度的方式:使用 Trello 切卡片,以及每天早上進行簡短的進度報告、問題回報。

學到的經驗

專案過程中,最讓我印象深刻的地方,是因為「前後端對伺服器的認知不一樣」而產生的坑。來龍去脈如下:

為了避免開發即時聊天功能時,意外把架好的 twitter api 伺服器 A 弄壞,我另外部署了一個「twitter api + 即時聊天」功能的伺服器 B,兩個伺服器各自擁有自己的資料庫。

因為沒有試探過前端願意讓我把事情問清楚到什麼程度,所以,以下只是我單方面的推測:前端以為 twitter 功能只有 A 伺服器才有,即時聊天功能只有 B 伺服器有,於是 twitter 功能是串 A 伺服器,即時聊天功能是串 B 伺服器。但我一直一廂情願地認為,前端串接的都是 B 伺服器。這引發了下列問題:

  • 攜帶 A 伺服器發的 token,對B伺服器請求資源,導致無法通過使用者認證。
    因為當時一直沒找到原因所在,只好放棄已經實作出的「在即時聊天功能中,用 token 辨認連線的使用者是誰」的機制。改成使用者連線後,主動告知伺服器自己的 id,讓伺服器能辨認出使用者(我猜,用這種方式的話,冒用身份的風險比較高)。

  • twitter 功能的使用者頭像,和即時聊天的使用者頭像不一樣

經過這次教訓,以後我會更有意識地留意前後端的資訊分享,避免認知差異;遇到奇怪的狀況時可以多問一點、多想一下,或許可以提早發現認知差異,省下許多開發時間。

關於「前端回報 api 錯誤」,在一次事件中我也學到,解讀前端回報的訊息時,不要只停留在文字表面。來龍去脈如下:

在專案中,使用者可以追隨其他使用者。有個畫面會列出,某個使用者正在追隨的人有哪些(以下簡稱「正在跟隨名單」),並根據 api 中 isFollowed 的值是 true 或 false(意思是,當前使用者是否有跟隨這位使用者),決定要顯示「取消跟隨」或「跟隨」的按鈕。

有一次前端回報問題:正在跟隨名單中,應該全都是顯示「取消跟隨」按鈕,但卻出現了一些「跟隨」按鈕。花了一點時間,我仍沒有把產生問題的原因想清楚,為了盡快解決前端回報的問題,就急就章修改程式碼,把 isFollowed 的值一律設定成 true。

後來再仔細想想,終於找到原因:因為當初是用 user 1 的帳號去瀏覽 user 4 的正在跟隨名單,所以出現了 user 1 沒有跟隨的人是正常的。(自己瀏覽自己的正在跟隨名單,此時出現沒有跟隨的人,才會是不正常的)。所以,我根本是把正確的程式碼改成錯誤的程式碼。

經過這次教訓,我學到不要照字面意義,把前端回報的問題照單全收。要找到真正的原因,才能對症下藥,而不會把功能改成錯的。


使用沒學過的技術

開發即時聊天功能時,使用 socket.io 套件。

在規格指定的功能以外,意外發現套件的潛力

  • 隱身:
    因為規格中指定,要在公開聊天室,顯示「目前已上線的使用者」,所以實作時,一旦辨認出上線的人是哪個使用者,就會把使用者加入「已上線者的陣列」裡,若伺服器監聽到使用者斷線,就將使用者從陣列中移除。在查資料過程中,發現有些人不是採用「伺服器監聽使用者斷線」,而是使用「使用者離線前發通知給伺服器」的方式,提醒伺服器將使用者從陣列中移除。

    這啟發了我,使用者可以主動通知伺服器「我想要顯示為離線」,請伺服器將自己從陣列中移除,完成隱身效果。

  • 已讀:
    閱讀文件時,發現有個 Acknowledgements 功能,官網是這樣介紹的:

    Events are great, but in some cases you may want a more classic request-response API. In Socket.IO, this feature is named acknowledgements.

    You can add a callback as the last argument of the emit(), and this callback will be called once the other side acknowledges the event

    雖然沒有實際實驗過,但似乎可以用來實作訊息是否已讀的功能

自從開始在 Alpha Camp 學習寫程式,我原本以為,我對程式的興趣主要在於「了解背後的原理」,對於套件或框架等等工具的看法,則是「可以加速開發,是件好事,但另一方面,卻把我跟原理之間的距離拉得更開了」。但經過這次「發現套件的潛力」後,我有點感覺到,如果對產業有準確地認識,對於使用者的需求有敏銳度,那麼,發揮創意,適當地組合現有的工具,做出很有意思的功能,以滿足大家的需要,是一件多麽有趣的事情。於是比較不會用「把我跟原理之間的距離拉得更開了」的負面視角看待工具了。


需要再加強的地方

  • 更有效率地從資料庫撈資料
  • 前端課程中教了許多「拯救後端伺服器效能」的技巧。我覺得身為後端,應該也要留意「減少前端效能負擔」的技巧
  • 應該能再提升完成功能的速度

感謝

謝謝一起完成專案的組員:前端的 caspar 和 TC,以及後端的 Max。有些事情是需要和人一起合作時,才能體會到的。

Comments

Popular posts from this blog

shop_platform - 建立多對多關聯:Association Object

git 指令

[LeetCode] #78. Subsets