今天要來寫我在這個會計逾期報表的專案中踩過的坑。
這個是我花最多時間的一個。
流程的前幾步要把 Excel 轉成試算表才能讀,某一天開始,這一步一直失敗,錯誤訊息只寫著「內部錯誤」。
我改了程式、換了寫法、加了重試,全部沒用。
後來我隨手做了一件事, 自己開瀏覽器,手動把那個 Excel 打開。 一樣失敗。
那一刻我才知道,問題根本不在我的程式裡,是平台對「Excel 轉試算表」這件事有每日的額度上限,而我那幾天每一輪測試都會轉三個檔,密集重測之後,額度就被我自己燒光了。
這件事有兩個收穫。
第一,重試救不了這種失敗。 我加的重試機制是等兩秒、四秒、八秒再試,那是為了應付「暫時性的網路問題」而設計的,但額度用完不是暫時性的問題,它是一道硬牆,等幾秒沒有意義,只能等隔天重置。
第二,最快的除錯方法,有時候是離開程式。 如果我早一點手動去開那個檔案,可以省下好幾個小時,因為那個動作可以一口氣排除掉「我的程式」這整個層級。
審核通過之後,系統會抓到錯的報表。 原本是靠「找資料夾裡最新的那一份」來定位,但測試期間資料夾裡有可能因為我修改的關係,修改的那份不一定就是最新的,但依照編輯日期去抓就會抓錯,後來改成產出報表的當下就把檔案的識別碼存起來,之後直接用那個編號去拿。
同一支程式可能被重複執行。 如果兩個觸發同時發生,就會跑出兩份報表,或是寫到一半互相蓋掉,後來加了鎖,同一時間只允許一份在跑。會發現這個問題是會計在協助我測試的時候,他們的習慣是會連續按按鈕,導致我程式重複執行,我覺得這個問題我應該要能提早避免。
有一段時間我很困惑,報表上有一欄「物流人員」,我怎麼找都找不到程式是在哪裡把它填進去的。
我翻了整支程式,沒有任何一行在處理那一欄。
最後發現,那一欄本來就在會計傳過來的檔案裡。 程式在複製主表的時候原封不動地把它一起帶過來了。而且它在報表上是隱藏的,那個隱藏也不是我設的,是他們自己那份檔案本來就那樣。
這件事本身不嚴重,但它提醒了我一件事。
來源檔不會只帶資料進來,它會把自己的樣子一起帶進來。 欄位、格式、哪幾欄被藏起來,這些都是別人當初為了別的用途做的決定,然後一路跟著資料跑到我的產出裡。
我應該要請會計直接把餵編輯過的資料給我,才不會有找不到資訊的問題出現,也才不會有資料處理環節我不知道的問題。
九月的某一次執行之後,一口氣冒出三個問題。
有一類客戶是貨到收款,他們的催款信原本是統一寄到一個固定的信箱,而不是寄給負責那筆單子的業務。
這條規則從第一版就在,跑了四個多月。
九月的時候會計提出調整,這類單子應該直接寄給該筆的收款業務員,因為業務本人才知道自己手上有這張單要追。
這不是錯誤,程式完全照著規則跑,而那條規則當初也是他們定的。
但有趣的是, 我發現他們會忘記自己當初訂過的規則。
所以當他們看到某一封信寄到那個固定信箱,第一個反應是「這個好像寄錯了」,而不是「對,這就是我們當初說的」,要等我回頭去翻,才會確認那確實是照著約定跑的。
這件事我想了很久。
一是,規則一旦寫進程式,記得那條規則的就變成程式,不是當初訂它的人。 手動的時代,規則活在做事的人腦袋裡,用久了自然會調整、會有例外、會隨著情況修正;自動化之後,規則被固定下來了,而人還是繼續往前走。
而且改一次的成本也不一樣了。手動的時候想改寄給誰,當下決定就好;現在改寄給誰,等於要改程式。規則沒有比較不容易變,只是變一次的成本變高了。
二是,這樣會出現一種很奇怪的落差,系統跑得完全正確,但沒有人記得它為什麼要那樣跑。
所以我後來對「文件要寫給誰看」的想法變了。
我現在寫的專案文件,有很大一部分其實是給 AI 看的,讓它接手的時候知道脈絡。但這件事提醒我,文件的第一個讀者應該是人,是幾個月後的需求方、是下一個接手的同事,也是已經忘記自己訂過什麼規則的我自己。
同一次還有四位新接手的業助沒有收到信。
原因是這樣:會計先前有提出要調整這一塊,讓這些單子改由業助負責,但在我把程式改好之前,他們就先自己動手,在報表上把收款業務員改成了那幾位業助的名字。
問題是那幾位的信箱還沒有被加進名單裡,系統照著改好的名字去找信箱,找不到,就記了一行紀錄然後跳過。
他們沒有做錯任何事,他們只是在做一件很自然的事,也就是在系統跟上之前,先用手把事情做對。
而我那時候才意識到,一個需求從「他們提出」到「我改好上線」中間是有時間差的,而在那段時間裡,他們不會停下來等。
所以我後來多做兩件事。一是提出需求的當下就告訴他們大概什麼時候會改好,讓他們知道這段期間還要不要自己動手;二是講清楚這個改動會牽動到哪些環節,因為他們手動改的那一欄,後面還接著別的東西,而那些東西他們不一定知道。
最後一件是總表沒有寄出去。
原因是前面有一個步驟沒有執行成功,所以後面的步驟就全部停住了。
這件事最諷刺的地方在於,那正是我自己設計的行為。
我在前面寫過,這套系統的原則是缺一就停,寧可全部停住,也不要帶著錯誤往前跑。這次它確實照做了。
但停住之後發生了什麼事?什麼都沒有發生。沒有人收到總表,也沒有人知道為什麼沒收到,大家只是覺得「今天好像還沒寄來」。
所以問題不是停得對不對,是停了之後沒有人知道它停了。
後來我把這一段拆開,就算催款信那邊出了問題,總表還是照寄,然後我也覺得我應該再加一個回報機制。
「一起停」聽起來很安全,但它的前提是有人會發現停了。
第二件事我看了很久。
會計在系統產出報表之後,手動改了上面的資料,而系統不知道有人改過。
這跟我在人資考核那邊踩的坑是同一個形狀。那次是主管交出職能之後又回頭修改,系統拍完快照就往下走,不會回頭確認。這次是報表產出之後有人改了業務員,系統拿著新的名字去找舊的名單。
兩個不同的專案、不同的部門、不同的資料,同一種問題。
那時候我的結論是「系統是線性的,它不回頭檢查」,人不會照著系統的節奏做事。 系統以為拍完快照這份資料就定了,但對使用者來說,那只是一份可以繼續改的表。他們沒有做錯任何事,是我把「產出」當成了「結束」。
還有一個問題一直留著。
人員異動、物流商換了、資料夾搬家,這些都要手動去改程式裡的設定。我有把這些集中放在檔案最前面,改一個地方就好,但它終究還是一個需要人去維護的點。
而且維護它的人只有我。
如果哪天我不在了,沒有人知道這支程式是怎麼運作的,或者要花很多時間才看得懂。對一套每個月都要跑、而且會直接寄信給業務的系統來說,這件事其實很不穩健。
而這還不是最嚴重的。 這套東西不只是知識綁在一個人身上,連它實際執行的位置,也綁在某一個人的帳號底下,這也是我之後想把這個流程網頁化的原因。