除錯的意義


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

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

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

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

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

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

在實體世界消完了毒,數位世界的蟲依舊每天出現,真希望也有台噴藥機可以一次幫我搞定 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 開發日常

先講結論:錢燒完了、產品賣不動,明年要先接案子過活了XD 雖然產品都沒有成功,但卻累積了一些不錯的失敗,知道哪些路不能走,以及投入實戰 AI 開發後看見全新的風景與機會,這些經驗讓我對於創業不再只是停留在書本的知識,而是自己親身走過的一段路,同時也明白自己的不足,現在看到能夠在創業路上存活下來的人都打從內心敬佩萬分。 今年的收穫 今年靠賣外掛賺了 28 萬,平均一個月 23,000 元,而這全是單一外掛所達成的營收,很自然的就會想如果有第二支、第三支的話,照這節奏累積下去想要月入十萬不是夢,於是年初時便開始著手研發第二款產品。 由於第一款是做客戶訂單推播功能就有如此的成績,因此第二款延續這主軸,改以管理員為主的推播,並整合 AI 讓管理員可以用自然語言做訂單查詢,商業模式是打算先釋出免費的版本,再搭配不同的 AI 查詢項目來做收費:https://oberonlai.blog/dwp-site-assist/ 開發期間請了很多客戶幫我測試,很慶幸有先找他們,如果沒有他們幫我測試就推出絕對會是災難一場,主要發現的問題是打算拿來收費的 AI 查詢訂單功能不穩定,會因為...

很開心今年又有 WordCamp 可以參加,每次參加都很珍惜,每年都靠著志工們的無私付出,才能有這麼多精彩的活動可以參與。今年是第一次舉辦在高雄,高雄展覽館超大氣,整個會場超舒服,真希望新北也能有這麼棒的場地~ 今年我的攻略路線就是專心聽演講,以往都覺得在現場跟人聊天交流比較重要,演講的內容事後還可以去看 WordPress.tv 回顧,結果最後都沒去看XD,自己當過講者也知道,每次上台前要花好多時間準備、練習再練習才有辦法呈現一場演講,所以與其只是在哪邊喇賽,還不如好好享受每位講者精心準備的內容。 為了達成此目標,我六點起床,搭了 6:54 的高鐵直達高雄,再坐小黃 30 分鐘拼第一場演講,然後趁著每場中間的休息時間去贊助商攤位認識一下,午餐過後找不到咖啡可以喝,只能撐著睡意,努力聽到最後一場,最後為了趕高鐵放棄了閉幕抽獎,度過非常充實的一天。 為了更精準的吸收每場的內容,我聽的場次我都有用語音備忘錄錄下來,然後回到家再用 Gemini 整理出逐字稿與重點整理,這邊我把有聽的七個場次整理出來並補上自己的心得,分享給當天無法參與的朋友們。 高效率人才管理,讓 WordPress...

OrderChatz 全新推播功能公開封測中!現在加入 LINE 官方帳號 @dwpev 輸入「真買家」,就會收到外掛下載連結以及免費的封測序號,讓你親身體驗分眾行銷的強大威力! 在廣告成效越來越差的情況下,再行銷是所有電商業主的必修課題,尤其是如何篩選出正確的 LINE 好友進而投放正確的行銷資訊更是一門大學問,常使用 LINE 官方帳號進行再行銷的你可能會遇到以下問題: 人力成本與工作量爆表:人工逐筆查訂單、比對商品並貼標,遇到一位好友多張訂單就會產生大量重複作業,整體工時與人事成本快速攀升。 標籤維護難度高、錯誤率大:退款、追加購買或不同客服的命名習慣會讓標籤狀態不一致,導致分眾邏輯失準、名單品質下降。 推播額度與行銷成本浪費:把訊息傳給不相關或已流失的好友會降低開信/點擊率,浪費 LINE 發送額度與廣告預算,讓 ROI 看不清楚。 時效性不足、錯失最佳接觸時機:人工貼標與核查耗時,導致無法在限時促銷或新品上市的黃金時段快速觸達目標客群。 測量與優化受限:錯誤或雜亂的分眾會讓 A/B 測試與成效分析失真,行銷團隊難以找出真正有效的訊息與受眾組合。...