iT邦幫忙

2026 iThome 鐵人賽

DAY 20
0
IT Operation

AI 輔助開發下,測試如何保住品質防線系列 第 20 篇

Day 20:接進 CI 前先跑一次,才發現它從一開始就是紅燈

  • 分享至 

  • xImage
  •  

前言:一個從沒被呼叫過的 composer script

composer.json 裡有一個叫 check-style 的 script,執行 phpcs 檢查 PSR2 風格規範。CI 設定裡完全沒有呼叫過它。今天實際跑一次,看看為什麼——這可能不是單純被忘記,而是一旦接進去馬上就會炸。

今日目標

  • 確認 check-style 這個 composer script 從未被 CI 呼叫過
  • 實際跑一次,核對真正會冒出來的錯誤數量跟內容
  • 理解「命名慣例規則」跟「跟外部系統對齊的欄位命名」之間的衝突
  • 想清楚:這種衝突該怎麼解,而不是誰對誰錯

composer.json 裡定義了,但沒人呼叫的兩個 script

"scripts": {
    "test": "phpunit",
    "check-style": "phpcs -p --standard=PSR2 src/",
    "fix-style": "phpcbf -p --standard=PSR2 src/"
}

.github/workflows/tests.yml 只有一個步驟叫 Execute tests,內容是 vendor/bin/phpunit --testdox --no-coverage。從第一次寫這個 workflow 到現在,check-style 沒有出現在任何一個 CI 步驟裡。

實際跑一次:8 個錯誤,全部集中在同一個檔案

在暫存複本上跑 composer check-style:

FILE: src/Traits/HasCVSOrBARCODEFields.php
--------------------------------------------------------------------------------
FOUND 8 ERRORS AFFECTING 8 LINES
--------------------------------------------------------------------------------
  44 | ERROR | Method name "HasCVSOrBARCODEFields::setDesc_1" is not in camel caps format
  52 | ERROR | Method name "HasCVSOrBARCODEFields::getDesc_1" is not in camel caps format
  65 | ERROR | Method name "HasCVSOrBARCODEFields::setDesc_2" is not in camel caps format
  73 | ERROR | Method name "HasCVSOrBARCODEFields::getDesc_2" is not in camel caps format
  86 | ERROR | Method name "HasCVSOrBARCODEFields::setDesc_3" is not in camel caps format
  94 | ERROR | Method name "HasCVSOrBARCODEFields::getDesc_3" is not in camel caps format
 107 | ERROR | Method name "HasCVSOrBARCODEFields::setDesc_4" is not in camel caps format
 115 | ERROR | Method name "HasCVSOrBARCODEFields::getDesc_4" is not in camel caps format

8 個錯誤,一次都沒有分散在別的檔案,全部出在同一個 Trait 的 8 個方法上。

命名衝突的根源:跟著綠界的欄位名走,還是跟著 PSR2 走

HasCVSOrBARCODEFields 裡的 setDesc_1、getDesc_1……這幾個方法名稱,之所以帶底線,是因為它們對應綠界官方 API 要求的欄位名稱就叫 Desc_1、Desc_2、Desc_3、Desc_4。這個套件的命名慣例是「setter/getter 方法名稱直接對應要送給廠商 API 的欄位名稱」——這個慣例本身在其他地方運作得很好(例如 setMerchantTradeNo() 對應 MerchantTradeNo 欄位,完全符合 camelCase),只有這四組欄位剛好在原始欄位名稱裡就帶了底線,直接照搬過來的方法名稱就違反了 PSR2 的 camelCase 要求。

這不是「這個套件命名沒統一」的隨機失誤,是兩套規則(跟隨外部 API 的欄位命名 vs 遵守程式語言的風格規範)在剛好交會的地方,必然會撞在一起。

❌ vs ✅:兩種解法各自的取捨

❌ 保留跟外部 API 一致的命名,違反 PSR2
public function setDesc_1($value) { /* ... */ }
✅ 改成 camelCase,符合 PSR2,但跟綠界文件的欄位名稱不再一一對應
public function setDesc1($value) { /* ... */ }

正例解決了風格檢查的問題,但代價是當開發者對照綠界官方文件(欄位名稱寫的是 Desc_1)跟這個套件的方法名稱(setDesc1)時,多了一層需要自己心算轉換的落差。這正是為什麼這種違規到現在還留著的一個合理推測:維護者可能認為「跟外部文件保持字面一致」比「符合 PSR2 命名規範」更重要——這是一個真實存在的取捨,不是誰忘記修的疏失,但這只是觀察到現象後的推測,不是套件維護紀錄裡明講的理由。

為什麼這個 script 至今沒被接進 CI

一個合理的推測:如果現在把 composer check-style 接進 CI,這 8 個既有的違規會讓 CI 從第一次跑起就是紅燈。要嘛得先修掉這 8 個違規(並承擔上面講的取捨),要嘛得在 phpcs 設定裡加規則例外(排除這幾個方法),兩者都需要一次額外的決定跟投入,而不是像加一行 CI 步驟那麼簡單。一個「事後才想接進去」的品質工具,往往需要先處理完既有的違規才敢真的接上——這個成本本身,可能就是它一直被擱置的原因。

今日思考題

你的專案裡有沒有類似「定義了但沒接進 CI」的檢查工具?如果現在把它接上,你猜會先冒出幾個既有的違規?

今日重點回顧

  • check-style(phpcs PSR2)定義在 composer.json,但從未被 CI 呼叫過
  • 實測發現 8 個真實違規,全部集中在對應綠界欄位命名 Desc_1~Desc_4 的 4 組方法
  • 違規根源是「跟隨外部 API 命名」跟「遵守語言風格規範」兩套規則交會處的必然衝突,不是隨機疏失
  • 一個檢查工具事後才想接進 CI,往往需要先處理完既有違規才敢接上,這個成本可能正是它被擱置的原因

明日預告

明天討論一個更直接的問題:如果請 AI 幫忙寫程式碼,要怎麼避免它不小心用了目前 CI 矩陣(最舊到 PHP 7.1)不支援的新語法?


上一篇
Day 19:第一次跑 PHPStan,抓到一個打字打錯的烏龍
下一篇
Day 21:請 AI 幫忙寫程式碼,怎麼確保它沒用 CI 矩陣不支援的語法?
系列文
AI 輔助開發下,測試如何保住品質防線 共 23 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言