團隊開發一個 Ruby on Rails 專案時,寫程式的風格很難統一,不管是從其他技術搬家過來的老手,或是剛學習程式語言的新手,必定和其他團隊成員有習慣不同的地方。適時使用像 Rubocop 這樣的程式評量工具,不只帶新人變得容易,也讓團隊的程式風格更趨於統一。
Rails 的設計風格是「傳統比設定更重要」( conventions over configurations ),因此長久下來, Ruby 及 Rails 社群逐漸歸納出一套邏輯,希望在所有開發者都能養成默契,在加入開發各種專案時不會難以接軌。這套邏輯是由 Bozhidar Batsov 首先制定,稱作” Ruby Style Guide “及 ” Rails Style Guide “。其中包含許多我們不陌生的寫法,例如 Ruby 1.9 推出的新 Hash 寫法,將 {: foo => “ bar ” } 精簡為 { foo : “ bar ” },諸如此類的規定,不只讓入門新手有很詳細的參考,資深的開發者也可以依照這套邏輯來統一整體團隊的風格。
不過,要花時間檢查所有人的程式有沒有符合這些規定,實在有點浪費時間,身為一個 Ruby 開發者,實在沒理由不用現成的工具來完成這件事。這類協助檢查程式風格並點出問題的工具稱為「程式評量」( code metrics ),包括 Rubocop 、 Rails best practices 、 Flog 等,從不同角度來提供我們不同的數據。目前開源工具中最普遍使用的就是 Rubocop 。
Rubocop簡介
Rubocop 同樣也是由 Batsov 這位神人開發者所撰寫,只要一個指令,他就會告訴我們哪邊的 code 有問題。他完全依照 Ruby Style Guide 和 Rails Style Guide 內的風格來檢查,因此只要把這兩篇文章讀透了,每當產生錯誤,基本上也不致於到無法理解的地步。
最簡單的使用方法就是在開始新 Rails 專案或其他 Ruby 專案時,依據說明在根目錄下新增 .rubocop.yml 檔案,並將所有需要及剃除的檔案列出,接著就像是回家作業一樣,每次寫完一段程式就執行 rubocop 指令(或是搭配編輯器的整合功能),看是否有需要修改的地方。當然,他內建有數百個檢查項目,剛開始使用一定非常不習慣,例如強迫每個method要保持在10行之內、每個 class 要保持在100行以內,這些對許多開發者來說都非常頭痛。但只要耐著性子,每一次的修改都會越來越熟練,到最後你會發現那些標準的風格寫法已經內化,寫出來的程式都具有一定的品質。
如何用於既有專案
當然,一般的團隊在草創時期根本不可能將時間運用在如此奢侈的檢視工具上。大部分開始使用 rubocop 的專案都是已經行之有年,發現團隊間的程式風格難以統一,不得已才必須開始使用的工具,除了推行困難之外,要在短時間內解決所有問題難如登天,通常中型專案檢查出來的問題都會超過 1000 個以上,不安排個兩三個月,根本無法修復。
因此,依筆者的經驗,最好是在專案根目錄的 .rubocop.yml 當中先將全部的檢查項目關閉,確認無誤後再逐一解開,藉由一個一個項目的修復,團隊也比較容易培養默契。筆者在自己的 GitHub 上有整理一份設定檔 ,有興趣的朋友歡迎將這份檔案複製到專案根目錄中,逐一將項目的 false 改為 true ,並參考 style guide 的連結,確認了解自己在修改哪些項目。
這樣一來,團隊可以優先處理最容易有 bug 的問題,例如在專案當中寫了 binding.pry 這樣的中斷功能,卻沒有在推送時拿掉,這樣讓其他團隊成員接手開發時發現伺服器會在莫名的地方暫停。
整合服務
Rubocop 執行非常方便,而在團隊管理上也有非常方便的整合工具。例如為了確保團隊每個成員都有乖乖使用這個工具,就可以利用像 Code Climate 這樣的持續整合( continuous integration )工具,讓每位成員在將程式推送到Git伺服器(例如 GitHub )上時,可以設定自動檢查是否有風格問題,只要不符合就會跳出警告,讓所有漏洞無所遁形。基本上只要連續出現數個錯誤,大概就可以判斷這個成員根本偷懶沒執行這個工具了!
另一個很方便的服務是 HoundCI ,同樣將程式推送到 Git 伺服器時,會自動檢查,更神的是會自動送出 pull request ,用以自動修正錯誤,這些整合服務都能在專案管理上加快速度,並且維持程式品質的良好。
小結
在專案中要統一風格並非易事,而自己身為開發者要能遵循這些原則也要花上一段時間。但隨著專案的逐漸擴大以及團隊成員的增加,使用這樣的自動化工具來增加管理效率,才是像 Matz 所說” work hard to be lazy “的精神,只要先把原則建立起來,後續要管理就方便多了!共勉之!
Photo Credit:Bozhidar Batsov