有一次業務在系統裡找某個東部縣市的飯店報價,怎麼篩都篩不到,只好回客人「這個地區目前沒有報價,晚點統一回覆」。後來同事回頭查才發現,那家飯店的報價其實好端端躺在系統裡,只是地區欄位被程式自動分類成另一個看起來完全不同的選項——業務在篩選器裡根本不會想到要去點開那個陌生的選項名稱找。
這個坑後來追出來,是歸檔資料夾分兩層:外層九個大地區,裡面再分細一點的縣市,程式一開始寫的時候,地區欄位直接取資料夾名稱,結果取到了裡面那一層。原本九個地區,在系統裡悄悄裂成十四個,而且完全不會報錯——資料都在、程式沒當、網頁正常顯示,只是篩選器裡多出幾個沒人看得懂的選項,同事篩不到的飯店,看起來就像「系統裡沒有」。
昨天講的是報價單怎麼被讀成資料。今天講的是讀完之後怎麼存——聽起來是最無聊的一段,卻是我改版次數最多的地方,剛才那個分類錯誤就是其中一個代價最高的教訓。
飯店的業務窗口很常重寄同一份報價單:改個檔名再寄一次、換一個信箱再寄一次、或是同一份東西被不同同事各自存進不同的地區資料夾。如果系統只認檔名,這三種情況都會被當成新資料,網頁上就會長出三筆一模一樣的價格,業務點開一看,自己都搞不清楚該信哪一筆。
所以判斷「這份我是不是已經處理過了」用的是三把鑰匙:雲端硬碟給這個檔案的識別碼、檔名、還有檔案內容本身算出來的雜湊值。三把鑰匙裡只要內容雜湊對得上,不管檔名怎麼改、被重傳幾次,系統都認得出這是同一份東西,直接略過不重複入庫。
最後那把才是關鍵。前兩把擋得住重複上傳,擋不住改名重傳;內容雜湊是直接對檔案本身的位元組算出來的指紋,哪怕檔名、信箱、存放資料夾全部不一樣,只要檔案內容一字不差,雜湊值就會完全相同。
資料的存法我選了最單純的一種:一份報價單就是一個獨立的資料檔,新的不會覆蓋舊的。
這樣做有一個很實際的好處——同一家飯店同時有好幾份不同期間、不同商品的報價是常態,入境團跟國旅的價格不一樣、團體跟散客的價格也不一樣。如果設計成「一家飯店一筆資料」,這些東西就得互相擠,遲早會出現新資料蓋掉舊資料的情況。分開存之後,它們可以並存,查詢的時候再依條件篩。
開頭那個地區裂成十四個的坑,修正方式是一律取上層資料夾,並且把地區寫成不可自創的固定九項——程式讀到資料夾名稱之後,要先對照這份固定清單,對不上的話直接攔下來進人工複核,不會自己生出一個新選項。
飯店名稱跟適用對象這兩個欄位也一樣要沿用既有的寫法。原因相同:這三個欄位會直接變成網頁上的篩選器選項,只要有人寫法不一致,篩選器就會多長出一個沒人看得懂的選項,而且跟地區那個坑一樣,不會有任何錯誤訊息提醒你哪裡出了問題。
不是每一個丟進資料夾的檔案都該入庫。實際跑下來被排除的有:根本不是報價單的檔案、重複的版本、早就過期的舊報價、還有檔案太大處理不了的。這些不是默默跳過,而是記到一份排除清單裡,註明為什麼被排除,隨時可以回頭查。
這跟前面講過的原則是同一件事:安靜地略過,看起來像沒事,其實是把問題埋起來。
資料怎麼存這件事,比辨識準不準更影響最後好不好用。認重複要靠內容本身而不是檔名、同一家供應商的不同商品要能並存、分類欄位一定要是固定選項不能讓人自由發揮——這三件事沒做好,後面查詢頁做得再漂亮,同事還是會覺得「這個系統怪怪的」,更糟的是像開頭那次一樣,業務會把明明存在的報價,親口回客人說沒有。