除錯的意義


上週五工作到一半,家裡的門鈴響起,開門後是衛生局的人員通報說社區附近出現登革熱案例,需要整棟樓進行消毒,正當我想著那我就不要出門就好,結果想不到對方說連屋內都要消毒時,我一整個傻眼,家裡這麼多吃的穿的睡的,全部都要暴露在殺蟲劑下,一想到頭就暈。

第一時間先上網查一下這是不是新型態的詐騙手法,才知道原來對臺南人來說這已是司空見慣的作業流程,還查到「養生膠帶」這個神器,它可以把大型傢俱鋪上一層塑膠袋作為防護,於是當晚趕快去水電行買了兩捲,想說隔天早上再蓋就好。

到了隔天一早九點,大樓就傳來噴藥機的巨大聲響,衛生局人員敲每戶的門,說要開始進行消毒了,那時候我們才剛吃完早餐,一整個被殺個措手不及,只好趕快把養生膠帶鋪上,但因為太趕,很多傢俱都沒有鋪到,就這樣半推半就的被請出家裡。

坐進電梯前看到消毒人員拿著在戶外消毒水溝的大型噴藥機直接在家裡面狂噴,不知為何有種荒謬感,好像我家是喪屍病毒外洩的實驗室必須徹底消毒一番,然後跟著鄰居們一起被迫撤離家園,似乎也拉近了鄰居之間的距離(?)

就這樣在外面待了半小時後回到家中準備進行清掃,一進門就被殺蟲劑的味道嗆到一直咳,只能把所有門窗打開用電風扇狂吹,然後依序拆下養生膠帶並把每個傢俱都用酒精擦擦過一遍,地板因為還有殘留所以很濕滑,必須要先用靜電拖拖過一輪。

第一輪收拾殘局就花了一個多小時,接下來開始每週的例行打掃,掃完後開始洗衣服跟床單,前前後後花了三個小時才恢復世界和平,打掃過程中就只有撿到一隻小小強,好像在跟我證明說消毒是有用的。

在實體世界消完了毒,數位世界的蟲依舊每天出現,真希望也有台噴藥機可以一次幫我搞定 Debug 啊~

除錯的意義

在忙完了 WordCamp 之後,我調整了自己的工作節奏,從原先做二休一,改成做五休二,把之前累積的工作放在早上集中力最高的三小時來處理,然後上午做完後就下班了,下午看是要繼續弄產品,還是去跑個步動一下。

這樣的節奏在第一週運作的很順利,看到專案每天都有進展對客戶也有所交代,但到了第二週開始有些狀況,下午的時間常收到客戶的緊急回報,因為這些問題會影響到客戶當晚的作業流程,因此我會放棄下午的行程優排除客戶的問題。

檢查後才發現是第一週開發的功能所影響的,這些新功能開發完成時雖然我都有進行測試,並且確認可以正常運作後才交付,但這週遇到的問題是我完全沒想到的情境,我沒有預料到做了 A 功能竟然會造成 B 功能的錯誤,於是只能當客戶在實際使用時才發現問題。

這樣的狀況持續了幾天,結果變成一整天都在處理專案,上午開發下午除錯,就讓我反省為什麼會有這些臭蟲的發生?難道這些蟲是無法避免的嗎?就算無法避免有沒有更好的通知機制能讓我第一時間就知道?

因此我想藉由這篇文章來分析一下這週遇到的問題,並且提出可能的解決之道。情境是這樣:

因為 wp_postmeta 資料表已經儲存百萬筆的資料,在載入文章編輯頁的時候速度變得很慢,原先的欄位是用 ACF Repeater 開的,這些資料每天都會有數百筆的增長,因此我跟客戶提議把這些資料拉出來,新開一個自訂資料表來存放以及查詢,並且用 WP_List_Table 來彙整所有資料,不用點進各別文章查看。

我將本週遇到的問題類型分為以下三種:

ㄧ、原本應該發生的行為沒有觸發

重構前有一個功能是可以在前台寫入這個資料,然後在寫入後會觸發第三方的 API 做事情,結果重構後觸發 API 的行為沒有發生。觀察我自己的重構方式是在加入新的寫入方式後,把原先舊有的程式碼全部註解掉,結果我以為註解掉的部分就只有寫入資料的功能,想不到觸發 API 的程式碼也被我一併刪了。

舊版寫入資料的方法有將近四十行程式碼,觸發第三方 API 僅有六行,因此一整遍看過去會以為這四十六行就是只有處理寫入資料,而忽略了觸發 API 也在裡面。想到幾個可以改善的地方是:

  1. 把寫入資料的程式碼包裝成方法或函式,這樣在視覺上就會是一個獨立的事件而非一連串的行為
  2. 增加明顯的程式碼註解,帶有開頭跟結尾,並且把空行的間距加大,讓自己可以很明顯的看出處理同一功能的區塊開頭與結尾
  3. 增加返回的型別提示,確實定義每個任務執行完後要回傳的是什麼資料型態,以這個例子來說,寫完資料觸發 API,要回傳的應該是 WP_HTTP_Response 物件,如果我有指定的話,在測試重構後的方法我就可以即時知道回傳東西有誤,進而發現到我漏了觸發 API 的行為

事實上我有時候都會懶得把一連串的程式封裝成方法或函式,因為每多一個函式就要多寫程式碼,像是函式的命名、帶入參數的定義、返回資料類型、註解說明,尤其是要找問題的時候必須在多個函式之間切換很麻煩,但為了程式碼的維護性,還是要逼自己養成這個習慣才行。

還好在我改用 PhpStorm 之後裡面有一個很貼心的重構功能,可以把選取的程式碼直接變成函式:

點下之後就會在同一個檔案的最下方加入新的方法,他還會自動所需要的參數帶入,並且寫好參數的註解,算是省下不少手動輸入的時間,另外在查看函式的部分,只要把游標停留在函式上,按住 cmd + 滑鼠點擊,就會自動跳到定義該函式的區塊或檔案以方便查看。

有了這兩個實用的功能應該不能再用麻煩當藉口了,乖乖的把程式碼封裝起來吧!

二、重構不完整

新功能有一個方法是檢查特定的 user id 是否有在新建立的資料表中,藉此取代原本判斷 user id 是否存在於 Post Repeater 欄位中的邏輯,這部分我已經有獨立一個方法來做判斷,因此我是直接替換這個方法裡面的判斷邏輯。

結果想不到除了這個方法以外,還有一支散落於某處的函式也是在處理一樣的功能,結果我只改了方法沒改到函式因此發生問題,這讓我學到在重構方法前,記得先用全站搜尋功能來尋找原始的 user id 判斷邏輯有寫在哪寫地方,然後列出所有的方法與函式。

更好的做法是要將這些重複的地方整合為一個方法,就能避免改了 A 忘了 B,趁著這次除錯就可以順手把這件事做起來,如果時間趕可以先寫個註記,萬一之後又要調整就不會漏了它。

三、預期外的 save_post 勾點

新增資料的部分我是用 ACF 設定頁來處理,這樣就可以省下開一堆欄位的時間,然後當儲存後抓欄位值寫入資料,一般儲存文章的勾點是 save_post,而 ACF 的是 acf/save_post,問題出在我為了要判斷當下儲存的頁面是 ACF 設定頁,因此用了 get_current_screen() 來取得目前所在頁面,當頁面 ID 等於我的設定頁 ID 時才會執行資料寫入。

因為這個勾點的名稱我預期是只有在儲存 ACF 設定頁面才會觸發,為了精簡程式碼我把 get_current_srceen() 的判斷拔掉了,想說應該不需要這層判斷,但沒想到一般文章在儲存時也會觸發到,這導致寫入資料表時少了必要欄位而噴錯,造成客戶沒有辦法在後台更新文章。

於是還是乖乖的把判斷加回去,但第二個問題來了,因為我有用另外一個 ACF 設定頁以表單的方式放在前台供客戶使用,在前台因為沒有 get_current_srceen() 這個方法,因此設定頁 ID 的判斷會出錯,要先用 function_exists() 來判斷函式是否存在,才能繼續做設定頁 ID 的判斷。

第一個問題我想到的解決辦法就是用任何勾點前先去爬一下原始碼,看他們會在哪裡被觸發,使用 PhpStorm 並且有設定 WordPress 為專案環境的話,在每個勾點前面都可以看到一個小 h 的圖示,點擊後就會直接前往勾點定義的來源:

第二個問題的解法是在使用 WordPress 內建的函式時,要先意識到該函式是否有前後台的區別,如果懶得想最快的解法就是用之前一律做 function_exists 判斷就不會錯了,然後當回傳 false 時直接返回終止程式執行。

-

回想我的除錯過程都是客戶貼重大錯誤的截圖給我,然後我再進主機或是網站後台去查看錯誤日誌,然後從裡面尋找程式出錯的地方,我就在想不知道有沒有更快速的方法可以得知問題在哪,爬了一下找到這個解:https://www.businessbloomer.com/woocommerce-email-fatal-error/

研究後才知道原來 PHP 有 register_shutdown_function 函式,而 WooCommerce 就是利用這個函式來來做錯誤日誌的紀錄,並且在裡面放 woocommerce_shutdown_error 的勾點,就能實現當 500 Error 時收到通知,而不用從伺服器底層處理。

我期許自己在除錯的時候不是只要把眼前的問題解決就好,而是有餘裕去反思為何這個問題會發生,並且在除完錯的當下重構程式碼來避免再次出現,甚至可以改進工作流程來減少緊急狀況的發生,為了努力實現只上半天班,一定要將重大錯誤發生的頻率降低才行啊~

WordPress 開發日常

Read more from WordPress 開發日常

如果有一個平台,可以協助你: 完整紀錄開發產品的過程,從想法、手稿到實際動工 紀錄產品開發中遇到的困難、解決方法與成長經驗 查看產品從模糊概念,逐步轉化為 MVP、再到 PMF 的歷程 透過時間軸、行事曆與圖表,檢視每月的開發狀況 如果你對這樣的紀錄方式感興趣,那你一定會想試試看 aiker(艾可)。 有別於一般搶奪你注意力的社群平台,aiker 的設計初衷就是幫助你專注目標。只要每天順手更新開發狀況或心得,就能在產品履歷頁看到你努力的成果: 你可以在這裡實際瀏覽 aiker 的開發歷程,感受若將自己的專案以這種方式呈現,會是什麼樣子:https://aiker.app/products/288a712d-d942-4d3f-a50d-f3741895bb21 不要你的注意力,只要你的恆毅力! 為了鼓勵你更新開發動態,一進入首頁就會看到貼文介面。發文當下可同時設定分類與關聯產品,方便日後回顧;想要瀏覽產品開發歷程的人,也能透過你設計的分類快速搜尋。 此外,貼文還提供許多寫作輔助功能: 輸入 @ai:請求 AI 搶頭香發第一則留言,你也可以回覆 AI 留言,進一步與它討論。AI...

多巴胺(Dopamine)是一種神經傳遞物質,負責傳遞興奮和愉悅感。能引起渴望、興奮和希望等情緒,激勵人們追求目標。 上週日感冒了,很久沒有這麼嚴重的大感冒,發燒加喉嚨、頭爆炸痛,連續幾個晚上都沒什麼睡,白天完全沒有體力上工,不是在睡覺就是在發呆放空,受不了最後還是看了醫生吃了藥,每天等著症狀好轉。 到了週三稍微有點精神可以看書,看完「流言終結者」主持人亞當的書「創客精神」後一整個被激勵,很想要來動手做些什麼,於是拿出筆記本把一些點子畫下來,我想到可以做一個平台來搜集大家使用 Vibe Coding 開發出來的作品: 由於還沒有體力坐在電腦前工作,我就想說用平板先來做個雛形看看,付費解鎖了 Claude,也試了 Replit、Firebase Studio 來玩看看,很快的就有網站原型,再從這個原型去發想更多的功能細節。 第一次的衝擊 隔天因為需要回一些工作的訊息就開了電腦,想説回完後就關機繼續休息,結果想說把昨天弄的原型用 Cursor 來重做一次,能夠直接自己修改程式碼還是比較安心,但我忽然靈光一閃,我不是想要讓自己投入到 Vibe Coding...

原本努力了一個半月的新產品眼看就要正式釋出了,但在請了幾位客戶幫忙測試後,毅然決然暫停開發,主因是新產品有一些致命且短期無法解決的問題,再加上收入模式不明確,繼續開發下去會把自己推入險境中。 反而是請客戶試用的過程中,收到不少新功能的建議,考量到要顧好既有客戶以及營收狀況,還是決定先以既有產品的擴充功能為主,把營收站穩後再來另開戰場。 工作佔比 五月份總工作時數為 66.98 小時,比四月增加了 1.34 小時。各類工作佔比如下: 行銷:14% 產品更新:38% 產品研發:48% 這個月從下半月開始,全面採用 Vibe Coding 模式開發,在離開電腦前下好指令,回來後再驗收成果,一開始覺得很爽快,有一種人不在電腦前還是有進度的錯覺,尤其是在寫新外掛的雛形時很快就能獲得一些成果。 但如果寫流程比較多的功能,在驗收時就會開始感受到混亂,像是引用錯參考資料或是沒有遵循設計模式,一個檔案超過 500 行是家常便飯,事後反而要花時間在釐清甚至重新整理它的寫法,這部分我覺得應該可以透過提示詞來慢慢跟它磨合,就像以前跟朋友一起合作開發一樣,需要把相關的事項溝通清楚。 行銷 內容行銷...