Claptrap 生命週期(Claptrap Lifetime Scope)
Claptrap 生命週期按照筆者的看法分為兩大類進行闡述:運行時生命週期和設計時生命週期。
運行時生命週期
運行時生命週期是指 Claptrap 系統在運行過程中各個物件在記憶體中的生命周期行為。例如:在 Web 系統中,每個 Web 請求通常都會被分配為一個生命週期,而 Claptrap 系統也存在類似的生命週期設計。這些生命周期對於開發者進行元件擴展或者業務開發都具有一定的影響。Claptrap 框架的運行時生命周期分為:進程級(Process)、Claptrap 級和事件處理器級(Event Handler)。
進程級。被設計為進程級上生命週期的對象,屬於常規意義上的單例物件。每個正在運行的 Claptrap 進程都具有自己的單例物件。典型地,例如在 Claptrap 框架中,為了提高向持久層寫入事件的速度,每個持久層目標都會對應一個批量處理器(Batch Event Saver)。它們在整個進程的生命週期中只有一個實例,分別與對應的持久層一一對應,這樣才能將事件進行合併寫入持久層,從而提升寫入性能。一般來說,被設計為進程級生命週期的對象具備以下一個或多個特點:
- 只需要在整個進程生命週期中運行一次的邏輯或代碼。通常可以藉助 Lazy 以及單例的方式實現。
- 整個進程生命週期中只需要單個物件。例如 Claptrap Design Store、Claptrap Options 等等。
- 整個進程生命週期中只能有單個物件。例如 Orleans Client。
Claptrap 級。Claptrap 級生命週期的物件會隨著 Claptrap 的啟動而創建,隨 Claptrap 的失活而釋放。這些物件通常來說與一個 Claptrap Identity 有很強的關聯關係。例如,與該 Claptrap Identity 關聯的 Claptrap Design、Event Saver、Event Loader、State Saver 和 State Loader 等等。
事件處理器級(Event Handler)。事件處理器級生命週期對象隨著事件處理器創建而創建,隨事件處理器釋放而釋放。與 Web 對應來說,這一級別的生命週期和 Web 請求生命週期類似。典型的,統一資料庫事務的工作單元(Unit of Work)就屬於這一級別。
設計時生命週期
設計時生命週期,是指 Claptrap 對應的業務物件的生命週期。這與程式是否運行無關,甚至與是否使用程式都無關。舉個具體的例子,常規電商系統中的訂單。一個訂單的活動業務時間限界一般不會超過三到六個月。當超過這個時間限界后,訂單的數據就已經不能修改。此處就這個「三到六個月」的時間限界稱為訂單的設計時生命週期。在 Claptrap 系統中,如果一個對象已經超過了其設計時生命週期,就表現為「業務上再也不需要啟動這個 Claptrap」。。由此可以得到以下推論:
- 該 Claptrap 已經存儲的事件失去了意義,刪除這些事件可以騰出可用空間。
- 該 Claptrap 對應的業務代碼不再需要維護,可以選擇被移除引用或者移除代碼。
所以,如果 Claptrap 的設計時生命週期越短,就更有利於減少資源的佔用和代碼維護成本,反之,則增加了存儲成本和維護難度。故而,在設計 Claptrap 系統時,傾向於使用更短的設計時生命週期。而這個名詞,也直接反應了其實完全由"設計"來決定。 接下來,我們列舉一些常用的設計時生命周期劃分法。
業務邊界劃分法
這是最為常見的劃分法。基於領域建模的要求對業務物件進行劃分。並且這些業務物件通常有固定的生命週期。就如前文的「訂單」就是常見的按照業務邊界劃分生命週期的例子。在使用該方法進行劃分時,只需要注意 Claptrap 滿足「大於等於最小競爭資源範圍」的基礎要求就可以了。開發者可以通過「火車售票系統」的樣例來體驗這種劃分法。
條件邊界劃分法
一般來說,基於業務邊界劃分法已經能夠劃分出合理的生命週期。但是,如果只是按照業務邊界劃分,可能會出現設計時生命週期為永久的物件。假如這些對象又擁有非常密集的事件操作。那麼隨著生成的事件量將異常多。為此,我們引入人為控制的方式來縮短設計時生命週期。這種劃分是基於特定的條件劃分的。因此稱為條件邊界劃分法。而在此之中最為經典的就是採用「時間限界」 來劃分。
此處我們藉由"快速入門"例子中的購物車對象來說明一下這種劃分法。首先,購物車是和使用者相關的物件,只要使用者一直存在於這個系統中,那麼就有可能被啟動,也就是說,它的設計時生命週期是"永久"的。因此就無法刪除相關的事件,必須永久保存這些事件來確保購物車數據的正確性。但,假如我們對於購物車在一年前所產生的的事件已經不再關心。我們就可以手動的按照年份對單個用戶的購物車進行劃分。同時,我們可以在相鄰兩個年份的購物車進行"狀態拷貝"。這樣就延續前一年的狀態數據,從而使用戶的購物車在設計時生命週期上產生更短,而且這樣也不影響業務。我們可以藉助中國的一個經典傳說故事《愚公移山》來理解這種基於時間的設計時生命周期劃分法。故事中,愚公是凡人,雖然不能長生不老(較短的設計時生命週期),但愚公的精神(較長的設計時生命週期)卻可以隨著子孫後代而延續,因而可以完成移山的偉業。當每代"愚公"進行換代時,就發生了上文中提到的"狀態拷貝"(精神延續)。從而用較短的設計時生命周期,實現了較長的甚至永久的設計時生命週期的要求。
《愚公移山》 太行、王屋兩座山,方圓七百里,高七八千丈,本來在冀州南邊,黃河北岸的北邊。 北山下面有個名叫愚公的人,年紀快到 90 歲了,在山的正對面居住。他苦於山區北部的阻塞,出來進去都要繞道,就召集全家人商量說:"我跟你們盡力挖平險峻的大山,使道路一直通到豫州南部,到達漢水南岸,好嗎?" 大家紛紛表示贊同。他的妻子提出疑問說:「憑你的力氣,連魁父這座小山都不能削平,能把太行、王屋怎麼樣呢?再說,往哪兒擱挖下來的土和石頭? "眾人說:"把它扔到渤海的邊上,隱土的北邊。" 於是愚公率領兒孫中能挑擔子的三個人上了山,鑿石頭,挖土,用箕石頭運到渤海邊上。鄰居京城氏的寡婦有個孤兒,剛七八歲,蹦蹦跳跳地去説明他。冬夏換季,才能往返一次。 河曲的智叟譏笑愚公,阻止他幹這件事,說:"你簡直太愚蠢了!就憑你殘餘的歲月、剩下的力氣連山上的一棵草都動不了,又能把泥土石頭怎麼樣呢? "北山愚公長歎說:"你的思想真頑固,頑固得沒法開竅,連孤兒寡婦都比不上。即使我死了,還有兒子在呀;兒子又生孫子,孫子又生兒子;兒子又有兒子,兒子又有孫子;子子孫孫無窮無盡,可是山卻不會增高加大,還怕挖不平嗎? "河曲智叟無話可答。 握著蛇的山神聽說了這件事,怕他沒完沒了地挖下去,向天帝報告了。天帝被愚公的誠心感動,命令大力神誇娥氏的兩個兒子背走了那兩座山,一座放在朔方的東部,一座放在雍州的南部。從這時開始,冀州的南部直到漢水南岸,再也沒有高山阻隔了。