[經驗] 大量客製化需求應對與考量
以 Web Application Service 的角度出發
從我進入軟體業後,就投身在雲端網路服務的開發中,例如物聯網分析、點餐系統等,都是基於某個主幹進行延伸,標榜的只要客戶申辦帳號後就可以享受一系列的功能。
而這些專案都出產自規模不大的公司,因此不約而同的都面臨到相同的處境 — 推廣不易,意味著需要有業務去尋找客戶使用這個服務,隨之而來的就是大量的客製化需求。
本文想探討的就是如何不讓專案被客製化需求淹沒,變成一團維護狗屎,臭的讓工程師們避之唯恐不及。
工程師,這個直接寫死
通常小公司的 PM 都身兼數個專案,很難針對某個專案在開發初期進行通盤考量,在 RD 時程壓力與 PM 捉模不定下,針對業務端帶回來的需求通常直接以寫死作為解決方案,這種高利貸技術債在專案初期既快速又有成效,在你的專案不確定能不能存活的情況下,動輒要求規劃一兩週的開發時程,不如直接寫死。
根據過往經驗,這個專案如果活下來了,該專案的最初開發者要不中離、要嘛離職,他比誰都還清楚這個程式碼已經臭不可聞,維護難如登天。
除非這個 RD 是百年難得一見的全能開發者,不只有高超的技術,還有得道高僧的通靈能力。
然而真正頭痛的都是這類專案,所以我並不會討論太多架構規劃問題,因為既有軟體實在很難走回頭路,更不可能打掉重練了。
當客製化需求端到眼前的第一步
AWS 的每個新服務的第一個使用者通常來自家業務或合作夥伴,這使每個需求都有清晰的痛點和有許多可以談的空間,雖然這會使得這類服務會有些特定產業的形狀,但終究會盡可能符合使用者的使用情境,不過雅馬遜錢多屌大,你對常使用的服務有某些意見也不能拿他怎樣。
而我想說的是需求內化的可能,如果這個客製化需求可以融入整體系統中,那就太好了,有人願意幫 PM 分擔一些規劃的想法豈不美滋滋。
只需要問客戶能不能有一些妥協空間就好了…
通常沒有。
軟體之所以軟,就是天性沒有最佳解,所以我也沒有什麼最佳解決方案,接下來只是一些經驗的分享。
圓環與叉路
我曾經為了左轉繞了一圈這樣的路,圖如下:
這條路線像極了在強硬客戶的淫威下,我們遇到什麼補什麼的狀況,導致未來就算是一點新的需求就必須繞過重重難關,建立一條令人難以置信的路線,不只是工程師要繞著開發、使用者也要繞著使用才行。
其實要解決這個狀況,只要採用圓環設計就可行了:
可惜的是,失敗的都市規劃是回不了頭的,但軟體可不好說。
必須持續重構
不斷讓專案跟上世界的新進度是某些工程師的宿命,所以持續重構就算沒處於必要環境中,也是必須做的,否則 JQuery 運作的完全沒問題啊。
不過事實上我們根本沒時間也沒那個心臟去重構。
// TODO :: 下輩子再來處理這邊的效能問題
但在大量客製化需求的專案,重構必須是開發的一環,如果 PM 希望你能提供開發時間給他,記得把重構時間加進去,灌水灌越滿越好,例如試著逐步支援 TypeScript ,這能讓遍佈地雷的程式碼更安全一點。
這裡分享一個時程規劃的技巧:直覺預估時間 * 2
醜話說前頭,提出任何風險
有時候必須說一些廢話甚至是列出一系列很扯的狀況(根據墨菲定律,大多都會發生),不論是面對 PM 還是業務,如果還能有個 Email 備份那就更完美了。
你所提出的警告可以轉達到客戶那邊是再好不過,這能讓客戶知道要承擔某些後果,防止持續加碼的狀況發生。
但通常是講給業務聽的,有些需求是為了搶下這張單自己加油添醋說服客戶的,有時候嘴砲一下隔天就跟你說不用了。
使用者故事是很重要的一環
能閃則閃還是沒能躲過,那就請要求方提出使用者故事吧,畢竟會遇到這類狀況的你,團隊裡通常沒有 SA 幫你規劃的舒舒服服,從架構到所有可能性都得由你自己扛起。
而不可思議的是你永遠都是最後才知道的那個,因此可以得知資訊像尬進碎紙機一樣破碎,這也是通常需要工程師要會通靈才能開發的主因,明明只是個碼農卻好像身處在 CIA 一樣神秘。
所以必須不斷地追問為什麼要這麼做,最好把所有底線都摸得清清楚楚,釐清對方是不是也搞清楚自己在幹嘛,但這樣會顯得你很雞掰,但別忘了,你可是正在試著阻止專案變成一團狗屎,能有這種情操的人實在不多了。
完善自動化測試
陷入加班與時程的噩夢還是舒舒服服過日子,決定在於是否願意建立自動化測試,而這點在大量客製化需求的程式中更是體現的徹底。
針對核心功能的頻繁變動,更動到客製化需求的程式碼是無法避免的,但問題來了,在 end-to-end 測試中,我們無法完整跑過客製化需求的情境,因為理論上那些特殊狀況是不會存在開發環境中的。
在初期寫死階段,我們可能會從指定商家id做條件,這讓我們在後續的開發中難以得知是否在其他異動中影響了其功能,也阻礙了擴展性。
先假如我們有一個標準流程,就是點擊加入商品時回到商品目錄,而有客戶A希望轉移到購物車列表中,程式如下:
這段程式碼是程式初期以寫死的模式進行的,也代表著在客戶A沒有存在的情形下,永遠無法被測試覆蓋到。
從 ERP 中獲取經驗 — Rule
Rule 指的是一種特定的行為,可以把這種行為綁定在不同的 Role (角色),例如刪除資料庫的權限可以加入在 Admin 這個 Role 身上。
為了能讓自動化測試可在測試環境中運行,我們為購買物品轉跳至購物車這個行為定義一個 ”BuyItemToCart” 的 Rule :
這樣規劃我們就再也不需要在乎現在的客戶是誰了,只要試著Mock這些規則就能開始運行測試。
搭配文件與 Key-Value Table
盡可能別把客製化需求加入主要的 DB 中,而是試著建立一組專門複寫或擴展全部為可選的 Table 中,因為客製化需求的變動非常少。
Key-Value Table 是首選,首先是結構簡單、高彈性,其次不需要為了某個客戶瑣碎的需求去擴展資料庫,而得去麻煩 DB 管理人員,可謂兩全其美。
但客製化需求在開發的過程中 Rule 會有大量相應情境的名詞,因此如果缺乏管控的話,很容易出現上線後服務停擺卻找不到原因的事件,也會有業務人員無所適從的狀況發生。
因此先不管 PM 與 SA 到底在幹嘛,我建議開發人員協助建立一份 Rule 的關係文件。
使用本地文件控管
主要是針對介面操作處理,由於需要進行部屬才會更新,且非工程單位不容易調適,所以本地文件需要謹慎操作才行。
我的建議是盡可能的不要在文件中出現必填選項,才不會使的結構不斷擴充時使文件過於肥大,造成維護人員的惡夢。
本地文件控管通常在前端發生,如果後端也是這樣控管,那太瘋狂了,這也代表著這個類型基本上只針對極度特別且變動極少的狀況進行處理。
彈性很重要
這裡指的彈性是指對客戶來說操作越困難越好。通常越有彈性的系統,操作起來就越複雜,但系統結構也就越簡單,要打掉或是被狗幹時改得也快。沒有辦法內化的需求基本上是不需要考量使用者體驗的,在主幹優先的原則下,客製化需求要的只求解決而不是追求完美。
走向瑞士刀就是走向毀滅
曾經有一個專案為了應付所有可能,串了一堆不該在目標操作對象中看到的API ,因此不得不加入許多操作迥異的權限設定。
為了接下所有可能的客戶,只好注入了大量與主系統無關的功能,迎合各種產業,直到專注的解決目標與優化消失殆盡,逐漸喪失特色的系統很容易被大型軟體公司給取代。
所以就算你的架構再怎麼允許彈性,如果管理層沒有辦法阻止瑞士刀的結局,那終究會是累得半死的一場空。