天天看點

《測試驅動資料庫開發》—第2章2.3節資料庫的類

本節書摘來自異步社群《測試驅動資料庫開發》一書中的第2章2.3節資料庫的類,作者【美】max guernsey, iii,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。

2.3 資料庫的類

測試驅動資料庫開發

盡管事實上,大多數的時候,資料庫就是上面儲存那些不被使用的對象内容的“其他地方”,在資料庫開發中運用上述模式一點也不切合實際。與上述描述最接近的做法,應該是當每次想更新對象的行為時,就從舊資料庫中遷移資料到新建立的更新後的對象中。對于許多資料庫來說,上述做法可能仍然比許多人現在做的方式要快許多,但是因為還有另一種支援比這還要快的開發過程的做法,是以就将上述做法作為一個可選項而不再繼續讨論了。

2.3.1 兩條途徑:建立或改變

在許多系統中,建立某“類”資料庫執行個體有兩條途徑。一條途徑是針對從無到有地被建立的資料庫,這種情況經常發生在測試和開發的環境中;另一條途徑是針對反複更新的資料庫,這些更新是由于随着時間的推移,資料庫的設計以行為增量的形式不斷地演進而産生的,這種情況往往發生在生産環境中。

應用開發團隊的工作往往是上述情況的最好的說明。一個我曾參與工作的團隊擁有一個代表“資料庫”的腳本,該腳本通過一些如電子郵件或網絡共享檔案夾這樣的機制被共享,當一個開發人員搞亂了他的資料庫,他會把整個資料庫删除,然後運作這段腳本。當人們要設計一些有意義的變化時,他們會把這些變化寫入“腳本”中。有時候一個偷懶的開發人員可能通過一些gui,用他操作的一個資料庫執行個體為藍本,重新生成了這個“腳本”。

上述工作方式在開發團隊中是很正常的。然而,這些開發團隊編寫并據此進行測試的上述腳本,永遠不會在生産環境下使用。取而代之的是,他們會把新的資料庫設計送出給資料庫專家,資料庫專家再建立一個新的資料庫執行個體,并運作一個diff工具,來搞清楚新的資料庫設計與原來相比有什麼變更。當然,上述工具的輸出結果不會被全盤接受,而僅僅是用來指導資料庫專家編寫一個新的腳本,進而實作上面的資料庫設計的變更。資料庫專家會手工備份生産資料庫實作變更,并驗證一切能夠正常工作。

在我與上面這個團隊一同工作期間,使用上述工作方式進行了6次産品釋出, 隻有1次該方式實作了完美地工作。系統所有的使用者回家度周末這個後備方案,能夠保護我們免受真正的災難,幫助我們抵禦重大的系統服務中斷。但是,在周五夜裡熬到9點半或更晚才能釋出産品真的讓人抓狂。

問題的根源是,開發人員試圖像對待典型的面向對象程式設計的類一樣,即僅僅通過被建立和析構去對待資料庫的類。他們不操心資料庫被修改了的情況,因為那是其他人的工作。

然而,全世界每一個重要的資料庫都是被建立一次,然後被修改多次的。

2.3.2 難點:統一兩條途徑

正是由于資料庫世界中這種表裡不一的現象,使得定義資料庫的類變成了一項困難的工作。如何才能為某件事建構一個類,使得在一種情況下,該類被從頭開始建立;而在另一種情況下,該類可能在大量疊代周期裡被多次建構,且這些疊代周期之間又會間隔很長的時間?

上述“兩種途徑”的問題并不能真正得到解決。唯一合理的解決方案是完全消除這兩條途徑,這意味着程式員必須找到執行個體化資料庫的類的單條途徑,使得該途徑既能産生新的資料庫執行個體,又能更新資料庫的類的現有執行個體。

2.3.3 真實的資料庫的生長情況

找到上述途徑對讀者來說可能是具有挑戰性的,不然立刻就能看到解決方案。當難以找到一種解決方案時,看看資料庫世界真正發生了什麼是會有所幫助的。在這種情況下,研究一下真正的生産資料庫是如何建構和成長的對解決問題會很有幫助。

在所有諸如建立空的資料庫執行個體這樣乏味的事情結束後,第一件事情就是執行一系列ddl語句,将所有資料庫初始化時應具備的行為注入到資料庫中。通常情況下,上述事情可以通過執行與開發團隊使用的完全相同的sql腳本來完成。

最後,當作出要以某種方式更改資料庫的設計的決定後,開發人員會完成一些工作來确認更改,建構相關的功能和基礎架構,并確定一切都能夠組合在一起工作,然後生産資料庫會被實施一個變更,使資料庫的設計發生了由舊到新的改變。

過了一段時間,人們會重複上述過程來實施另一種轉變,使資料庫演進到下一個版本,如此這般循環往複。

一個清晰的模式正在形成:生産資料庫設計的變更通常從每一個釋出版本過渡到下一個版本,然後再到下一個,以此類推。這時,一個明顯的問題會映入腦海:我們有可能克服變更這個問題嗎?

答案是“不能”的。幾乎可以這樣認為,對于一個長期運轉的資料庫,其設計必将定期地發生變更。

2.3.4 将每個資料庫建構成生産資料庫會怎麼樣

是以,如果不能改變建構生産資料庫的方式,可以考慮下面的替代方案:用建構生産資料庫的方式來建構每個資料庫。這樣做會有什麼問題嗎?肯定有人會得出自己的答案,但是對于我們大多數人,對上述問題的回答是:“用建構生産資料庫完全相同的方式來建構每個資料庫真是非常有意義。”

規則很簡單,具體如下。

1.将一個空的初始化好的資料庫執行個體當做版本零。

2.為了獲得新的資料庫,建構腳本,使得資料庫的版本從零過渡到1。

3.為了更新資料庫,建構腳本,使得資料庫的版本從n過渡到n+1。

4.當建構資料庫時,從資料庫的目前版本直到期望的目标版本,依次運作所有相應的腳本。

是以,要建構一個新的版本為3的資料庫,可以執行版本1的腳本,接着執行版本2的腳本,再接着執行版本3的腳本。為了将資料庫從版本1更新到版本3,可以執行版本2的腳本,接着執行版本3的腳本。

2.3.5 所有資料庫都遵循完全相同的途徑

問題的關鍵是,隻要依次執行兩個版本之間的所有腳本,就能從任意版本過渡到下一版本。要想把資料庫從版本5過渡到版本7,除了按上述方式執行腳本,就不需要做額外的工作了。因為你已經知道如何從版本5過渡到版本6,并且知道如何從版本6過渡到版本7,是以你就能知道如何從版本5過渡到版本7。

隻要按上述方法來做,就向測試驅動資料庫開發的正确方向跨出了一大步。

本文僅用于學習和交流目的,不代表異步社群觀點。非商業轉載請注明作譯者、出處,并保留本文的原始連結。