[模板] Template 一定要加個 Clone 才對味

[模板] Template 一定要加個 Clone 才對味

今天的一隻蟲是這麼開始的 ...

某使用者反應他每次收到的e-Mail內容是錯的,

根據維護者的介紹知道它的架構大致上是:

主程式是去引用EmailGenerator物件, 然後將ValueObject填入該物件的 Generate() 操作去產生e-Mail內容,

但是主程式每次都會創建EmailGenerator 及 ValueObject 實體, 在封裝下, 不可能有什麼程式可以去改動到ValueObject 內的值, 才是.

 

再向下一層追去, 出現一個叫TemplateCache的類別, 小弟我的警報器突然響起,

後來查證Log, 果然是在這裡出了問題 ...

 

原作者是希望付予Template去讀取樣板檔案, 外部程式只需要將值填入PutValue(), 然後呼叫Generator(), 將值填入樣板中, 輸出eMail結果.

Main

但如果每次都去創建一個Template, 就會面臨不斷在IO 讀取檔案的效能問題,

所以加入了TemplateCache , 並實作了Singleton Pattern, 讓Template 可以Reuse.

Main

為了讓送Email可以共用, 又產生了EmailGenerator類別, 讓BuObject可以創建它, 並填入ValueObject就可以完成送eMail的任務了.

Main

 

原作者到此收工了, 悲劇從此展開 ...

------------------------------------------------------

 

思考一下, 問題在那裡呢 ?

 

 

------------------------------------------------------

這裡有一個很大的問題,

那就是Template是一個全域的物件, 而且還要求被填值, 並產生資料內容.

當Multi Thread時, 一堆執行緒湧入設值, 最後建出來的eMail一定慘不忍賭.

 

暫時先跳一個tone, 如果在工廠裡, 我們做了一個模板, 可以選擇:

1. 把它填入各式IC, 然後裝機, 等這個機弄完, 再把模板拿出來, 填入另一堆IC, 然後再裝機.

2. 用模板, 做出一堆空板, 再各別填入IC, 再裝機.

 

原作者就是用了1 , 這是不對的喔 !! 在硬體上沒人這麼玩吧, 但軟體卻很可能發生這種情形.

另外因為他用了EmailGenerator包裝後, 當BuObject在引用時, 雖然每次都用新的創建實體物件, 其實Template還是只有一個喔~

這讓維護者捉了很久的蟲都摸不出頭緒來... 好加在大叔之前也是有害過人的(煙), 才能這時候派上用場,

話說回來, Cache物件一定要受過MultiThread Test Case洗鍊過才能出廠喔!  不然上線有你受的.

 

 

解法:

關鍵在於:原作者搞錯要做樣板的是File, 而非Template物件本身.

一、快速解

(1) 為Template類別實作Clone將File的內容Cache住.

(2) 修改TemplateCache.getInstance() 取物件, 回傳Clone物件

 

二、慢速解

(1) 移除Template原責任操作, 就單純為File的包裝工, 新增一個方法取得樣板的內容.

(2) 由EmailGenerator Facade功能仍在, 將原本Template物件的工作攬下來做, 並修改為私有的操作.

Main

 

其它解, 就交給大家自由發揮了.

ps. 本篇是無碼, 實在很想睡了...