準備工作的簡短回顧(一)
在拿到程式碼的時候,我們並不是立刻把程式碼砍掉重練,而是先做一連串的準備工作:
- Day 14 重構的第一步--讓程式可以動
- Day 15 來試著升級 PHP 吧
- Day 16 導入 Composer
- Day 17 整合 Laravel
- Day 18 導入 Database Migration
- Day 19 整合 CI
- Day 20, Day 21 導入驗收測試
每個階段其實都有一些重構的影子在裡面,我們一起來看看。
先讓程式可以跑
開發重要的任務之一是做功能測試。因為程式執行的結果要正確,才能產生預期的價值。
而我們拿到一份既有程式碼(legacy code)後,首要任務應該是要了解如何執行,才能進一步做功能測試。
設定檔的壞味道
這個階段是為了確認既有程式碼是可以運行的,以及確認修改程式前的行為。因此這天應該只能建構環境,不能修改程式。
但相信大家會發現,這天其實是有修改程式碼(config.php
)的:
define('DB_HOST', 'mysql'); |
或許有人會認為這是設定檔,但事實上,這個檔案會被 index.php
與 admin.php
引用,因此只要 config.php
有任何問題,都有可能造成系統錯誤。
最好的方法,就是不要改它。資料庫是環境的依賴,因此從環境變數來取得對應的設定,會是更好的設計:
define('DB_HOST', getenv('DB_HOST')); |
Laravel 則可以使用 env
或 config
函式,來取得 .env
或 config 目錄下的設定值了:
// 使用 env |
升級 PHP
升級 PHP 最主要的目的是為了要使用 Laravel 框架的測試套件。以 Laravel 5.5 來說,它最低需求是 PHP 7,所以目標才會放在升級 PHP 7 上。
除此之外,最重要的目的是為了 Built-in web server。
雖然它的行為與 Apache 有些許的不同,但大部分的功能都是一樣的。有了它,將可以減少許多建置測試環境的問題,讓時間都盡可能花在改善設計。
使用 Composer 自動載入
Composer 除了提供了第三方套件管理功能之外,也提供了自動載入機制。
必須要能在 Laravel 裡正常載入既有程式碼,才能使用 Laravel 當做 proxy。Composer 可以實作自動載入,讓 Laravel 可以正常載入。
實作自動載入後,同時也安裝 PHPUnit 做簡單測試,以確認 Composer 的自動載入是有效的:
/** |
事實上,只要單元測試有確定 Composer 自動載入正常的話,載入 class 的方法就可以移除了:
require_once CLASS_PATH . 'Smarty/Smarty.class.php'; |
移除之後,載入方法調整就不影響原始碼了,這也能讓原始碼能更專注在處理商業邏輯上,如同單一職責原則所想達成的目的一樣--只有商業邏輯調整才會改變原始碼。
我們現在也可以試著修改看看,只要測試的結果是正確的,代表我們的修改是不影響正常行為的。
- 新增 Autoload 檔案:
class/Smarty/Smarty.class.php
- 重新載入 Autoload
composer dump-autoload
- 移除
config.php
index.php
admin.php
裡相關的引用
完成後再跑測試:
$ php vendor/bin/phpunit |
一切正常就代表我們的修正是正確的了!
整合 Laravel
使用 Laravel 的 Route 接上舊程式:
Route::get('/admin', function () { |
這能讓舊程式運行在 Composer 與 Laravel 的平台之上,後面如果需要在既有程式碼裡,使用 Composer 套件或是 Laravel 時,就可以大方的使用了:
// 使用 Carbon |
尤其如果改使用 Laravel Container 後,就能開始使用 Mock 來替換物件,讓撰寫驗收測試的難度降低。
Database Migration
程式碼要版控,資料庫的 Schema 也要版控,資料庫版控工具都通稱為 Database Migration。
使用 Database Migration 的好處在,資料的遷移可以由程式進行。在遷移過程,如果有需要運算或是轉換的行為,程式的處理會遠比人為處理來的可靠很多。
Schema 通常會被認為是基礎設施(infrastructure),如果 Schema 可以介由程式建立的話,這正是一種基礎設施即程式碼(Infrastructure as Code)的概念。最明顯的好處是:只要有完整原始碼,不管是剛來的新同事,或是遠在雲端的 Travis CI,任何地方都能做測試。
整合 CI
CI 會在程式碼改變的時候,建置(build)原始碼。它除了會檢查程式碼之外,也能提供許多資訊讓開發人員提早發現與解決問題。
重構有可能會改變設計,如果沒有處理好,就有可能把原始碼整個搞壞。
整合 CI 正是為了發現並解決這些問題。
驗收測試
對一個產品而言,做驗收測試就像是在模擬使用者操作產品。
驗收測試能確保使用者操作產品是符合預期的,這在重構時,是個非常重要的任務。修改程式該如何確定程式沒改壞?尤其是越底層的程式,如 DB 連線,就越難確認。如果有驗收測試的話,執行一下就可以確認了。
上面調整自動載入的時候,也是依賴驗收測試來確保產品沒有被改壞的。
今天相關的程式碼可以參考 GitHub PR。
現在基本測試都有了,明天就能開始對程式敲敲打打了!
參考資料
- Infrastructure as Code - 維基百科
- 先求有,再求好? - CI 從入門到入坑
- 有了 CI Server,然後呢? - CI 從入門到入坑