「首席架構師看敏捷數據」資料庫重構:適應業務快速變化
- 2019 年 10 月 4 日
- 筆記
您在A Vision中了解到敏捷數據方法,敏捷方法(如極限編程(XP)和紀律敏捷交付(DAD))採用迭代和增量方法進行軟體開發。XP和DSDM項目的應用程式開發人員通常放棄大型設計(BDUF)方法,轉而採用緊急方法,系統設計在整個項目生命周期中不斷發展。在敏捷開發項目中,在應用程式準備好發布之前,通常不知道最終設計。對於許多有經驗的IT專業人員來說,這是一種非常不同的工作方
這意味著,預先創建(幾乎)完整的邏輯和物理數據模型集的傳統方法不會起作用。傳統方法的主要優點是它使資料庫管理員(DBA)的工作變得更加容易 – 數據模式很早就實現了,而這正是人們使用的。然而,有幾個缺點。首先,它要求設計人員儘早完成,迫使您在項目早期確定大多數要求,從而迫使您的項目團隊採用連續的方法進行開發。其次,它不容易支援變化。隨著項目的進展,您的項目利益相關者了解他們的需求將會發展,從而激勵他們發展自己的需求。在您的項目中,業務環境也會發生變化,再次激勵您的利益相關者發展他們的需求。簡而言之,傳統的工作方式在敏捷環境中不能很好地工作。如果敏捷DBA將繼續工作並支援遵循敏捷方法的項目團隊,那麼他們需要找到支援迭代和增量工作的技術。我的經驗是,一種關鍵技術是資料庫重構。
目錄
- 重構
- 資料庫重構
- 為什麼資料庫重構?
- 保留語義
- 什麼資料庫重構不是
- 為什麼資料庫重構很難
- 如何重構資料庫
- 第1步:從您的開發沙箱開始
- 第2步:在集成沙箱中實施
- 第3步:安裝到生產中
- 在您的組織內採用資料庫重構
- 資料庫重構最佳實踐
- 現實世界中的資料庫重構
- 資料庫重構目錄(發布為另一頁)
1.重構
Martin Fowler(1999)描述了一種稱為重構的編程技術,這是一種重構程式碼的規範方法。基本思想是您對程式碼進行少量更改以改進設計,使其更易於理解和修改。重構使您可以隨著時間的推移緩慢地發展程式碼,採用迭代和增量方法進行編程。Martin的重構網站www.refactoring.com是一個很好的在線資源。
重構的一個關鍵方面是它保留了程式碼的行為語義,至少從黑盒的角度來看。例如,有一個名為Rename Method的非常簡單的重構,可能是從getPersons()到getPeople()。雖然表面上的這種更改看起來很簡單,但您需要做的不僅僅是進行單一更改,還必須在所有應用程式程式碼中更改此操作的每次調用以調用新名稱。一旦你做了這些改變,你可以說你已經真正重構了你的程式碼,因為它仍然可以像以前一樣再次運行。
重要的是要了解在重構時不添加功能。當您重構改進現有程式碼時,在添加功能時,您將添加新程式碼。是的,您可能需要重構現有程式碼才能添加新功能。是的,稍後您可能會發現需要重構剛剛添加的新程式碼。要點是重構和添加新功能是兩個不同但互補的任務。
2.資料庫重構
在2002年2月的軟體開發期間,我描述了一種我稱之為數據重構的技術。本文描述了我的初步經驗,應該更恰當地稱之為事後資料庫重構。因此新名稱。從這一點開始,我將使用術語程式碼重構來引用Fowler所描述的傳統重構,以區別於資料庫重構。
讓我們從一些定義開始。資料庫重構是對資料庫模式的簡單更改,可以改進其設計,同時保留其行為和資訊語義。為了便於討論,資料庫模式包括結構方面(如表和視圖定義)以及功能方面(如存儲過程和觸發器)。有趣的是,資料庫重構在概念上比程式碼重構更難。程式碼重構只需要維護行為語義,而資料庫重構也必須維護資訊語義。
有一個名為Split Column的資料庫重構,它是A Database of Database Refactorings中描述的眾多資料庫之一,您可以用兩個或多個其他列替換單個表列。例如,您正在處理資料庫中的Person表,並發現FirstDate列用於兩個不同的目的 – 當該人是客戶時,此列存儲他們的出生日期,當該人員是僱員時,它存儲他們的僱用日期。您的應用程式現在需要支援既可以成為客戶又可以成為員工的人,這樣您就會遇到問題。在實現此新要求之前,您需要通過將BirthDate列替換為BirthDate和HireDate列來修復資料庫模式。要維護資料庫模式的行為語義,您需要更新訪問FirstDate列的所有源程式碼,以便現在使用這兩個新列。要維護資訊語義,您需要編寫一個遍歷表的遷移腳本,確定類型,然後將現有日期複製到相應的列中。雖然這聽起來很簡單,有時也是如此,但我的經驗是,在考慮文化問題時,資料庫重構在實踐中是非常困難的(稍後將詳細介紹)。
2.1為什麼要重構資料庫?
您應該對資料庫重構感興趣的原因有兩個:
- 安全地修復現有的舊資料庫。底線是遺留資料庫不會自行修復,從技術角度來看,資料庫重構是一種安全,簡單的方法,可以隨著時間的推移改善數據和資料庫的品質。多年來,我對數據品質的各種調查一直表明,組織遭受數據品質問題,但在許多情況下,沒有一個現實的戰略來解決這些問題。
- 支援進化發展。現代軟體開發過程,如DAD,XP和Scrum,都以漸進的方式工作。數據專業人員需要採用包括這一技術在內的技術,使他們能夠以這種方式工作。
- 調整資料庫。部分調優工作可能包括模式的(反)規範化。
2.2保留語義
資訊語義是指從該資訊的用戶的角度來看資料庫內的資訊的含義。保留資訊語義意味著當您更改存儲在列中的數據的值時,該資訊的客戶端不應受到改進的影響。類似地,關於行為語義,目標是使黑盒功能保持相同 – 必須重新設計與資料庫模式的已更改方面一起使用的任何源程式碼,以實現與以前相同的功能。
2.3什麼資料庫重構不是什麼
對模式進行小規模轉換以擴展它,例如添加新列或表,不是資料庫重構,因為更改擴展了您的設計。同時應用於資料庫模式的大量小更改(例如重命名十列)不會被視為資料庫重構,因為這不是一個小的更改。資料庫重構是對資料庫模式的微小更改,可以在保留行為和資訊語義的同時改進其設計。而已。我毫不懷疑你可以對你的模式進行那些更改,你甚至可以遵循類似的過程,但它們不是資料庫重構。
3.為什麼資料庫重構很難
耦合。正如您在關係資料庫101中所了解到的那樣,耦合度是兩個項目之間依賴程度的度量 – 兩個事物之間的耦合程度越高,一個變化需要另一個變化的可能性就越大。在進行資料庫重構時,耦合是「萬惡之源」,資料庫模式與重構更加困難的事情就越多。不幸的是,您在關係資料庫101中了解到關係資料庫模式可能與各種各樣的事物耦合:
- 您的應用程式源程式碼
- 其他應用程式源程式碼
- 數據載入源程式碼
- 數據提取源程式碼
- 持久性框架/層
- 您的資料庫架構(通過模型或腳本捕獲)
- 數據遷移腳本
- 測試程式碼
- 模型和/或文檔
圖1描述了資料庫重構的最佳情況 – 只有您的應用程式程式碼與資料庫模式相關聯。圖2描繪了資料庫重構工作的最壞情況,其中各種各樣的軟體系統與您的資料庫模式耦合,這種情況在現有生產資料庫中很常見。
圖1.最佳情況。


如您所見,在資料庫重構方面,耦合是一個嚴重的問題。為簡單起見,在本文的其餘部分中,術語「應用程式」將指代與資料庫耦合的所有外部系統,資料庫,應用程式,程式,測試套件。
4.如何重構資料庫
在我描述重構資料庫的步驟之前,我需要解決一個關鍵問題 – 圖1所示的簡單情況是否意味著你會做出與圖2中高度耦合的情況不同的事情?是的,不是。基本過程本身保持不變,儘管隨著資料庫耦合的增加,實現單個資料庫重構的難度也會大大增加。如果您發現自己處於簡單的情況,那麼您將不需要執行下面描述的過渡期工作,您可以簡單地並行重構資料庫模式和應用程式程式碼並同時部署它們。發現自己處於更複雜局面的人沒有這種奢侈品。
本節的編寫假設您的技術和文化環境是有組織的,以支援資料庫重構。雖然這聽起來像是一個很大的假設,但是,我會描述你需要做些什麼才能達到這些環境實際到位的程度。少一點是不合適的。
我喜歡將資料庫重構視為一個三步過程:
- 從您的開發沙箱開始
- 在集成沙箱中實現
- 安裝到生產中
4.1第1步:在您的開發沙箱中開始
您的開發沙箱是一個技術環境,您的軟體(包括應用程式程式碼和資料庫模式)是開發和單元測試的。重構資料庫模式的需求通常由嘗試實現新需求或正在修復缺陷的應用程式開發人員識別。例如,開發人員可能需要擴展其應用程式以接受除美國地址之外的加拿大郵寄地址。主要區別在於加拿大地址有郵政編碼,如R2D 2C3而不是郵政編碼,如90210-1234。不幸的是,SurfaceAddress表的ZipCode列是數字的,因此目前不支援加拿大郵政編碼。應用程式開發人員描述了對其項目中的一個Agile DBA所需的更改以及資料庫重構工作的開始。
如圖3所示,Agile DBA和應用程式開發人員通常會通過以下部分或全部步驟來實現重構:
- 驗證是否需要重構資料庫
- 選擇最合適的資料庫重構
- 棄用原始架構
- 寫單元測試
- 修改資料庫架構
- 遷移源數據
- 更新外部訪問程式
- 更新數據遷移腳本
- 運行回歸測試
- 宣布重構
- 版本控制你的工作
圖3.資料庫重構的過程。

4.1.1驗證是否需要資料庫重構
敏捷DBA所做的第一件事是他們將嘗試確定資料庫重構是否需要發生以及是否是正確的重構。敏捷DBA所做的第二件事是在內部評估實際需要變更的可能性。這通常是基於Agile DBA之前與應用程式開發人員的經驗的「直接調用」。Agile DBA接下來要做的就是評估重構的整體影響。在圖1的瘦腿情況下,這是相當簡單的,因為敏捷DBA應該了解應用程式如何耦合到資料庫的這一部分。如果不是這種情況,他們需要與應用程式開發人員合作。在圖2的複雜情況下,Agile DBA需要了解組織內的整體技術基礎架構以及其他應用程式如何與資料庫耦合。這是他們需要通過與企業架構師,企業管理員,應用程式開發人員甚至其他敏捷DBA合作來建立的知識。當敏捷DBA不確定其影響時,他們要麼需要決定當時做出決定並且有他們的直覺,或者決定建議應用程式開發人員在他們與合適的人交談時等待。這項工作的目標是確保您嘗試進行無法完成的資料庫重構 – 如果您需要更新,測試和重新部署其他20個應用程式以進行此重構,那麼你可能繼續下去是不可行的。
4.1.2選擇最合適的資料庫重構
敏捷DBA需要的一項重要技能是理解您通常有多種選擇來在資料庫中實現新的數據結構和新邏輯。
4.1.3編寫單元測試
與程式碼重構一樣,資料庫重構由於存在全面的測試套件而啟用 – 您知道如果您可以輕鬆驗證資料庫在更改後仍然有效,則可以安全地更改資料庫模式。這是我的建議:
您的主要目標是確保測試存在。
您應該嘗試在應用程式級別或資料庫級別執行一次每個測試,但不能同時執行兩者。
一些單元測試將在應用程式級別,一些在資料庫級別,這沒關係。
尋求最低的共同點 – 如果資料庫被多個應用程式訪問,那麼任何與數據相關的測試都應該出現在您的資料庫測試套件中,這有助於確保它們經過一次測試。
如果您有選擇,請在具有最佳測試工具的級別(通常在應用程式級別)實施測試。測試工具在工具文章中討論。
文章資料庫回歸測試詳細描述了資料庫測試。
4.1.4棄用原始架構
Pramod Sadalage和Peter Schuh(2002)推廣的一種有效技術是棄用期,儘管過渡期是一個更好的術語,對於你正在改變的模式的原始部分。他們發現您不能簡單地立即對資料庫模式進行更改,而是需要並行處理舊模式和新模式一段時間,以便為其他應用程式團隊提供重構和重新部署系統的時間。圖4顯示了當我們將替換列資料庫重構應用於ZipCode時,這個想法是如何工作的(這個例子是在2003年創建的,因此在2007年是一個刪除日期 – 稍後將詳細介紹)。請注意過渡期間原始模式和模式之間的更改。PostCode已添加為列,正如您所期望的那樣。ZipCode列已被標記為已棄用 – 您知道這一點,因為已使用UML命名變數為其分配了刪除日期。還引入了一個觸發器來保持兩列中包含的值同步,假設新的應用程式程式碼將與PostCode一起使用,但不應期望ZipCode保持最新,並且舊的應用程式程式碼尚未重構為使用新架構將不知道如何使PostCode保持最新。此觸發器是資料庫腳手架程式碼的示例,是保持資料庫「粘合在一起」所需的簡單和通用程式碼。此程式碼已分配與ZipCode相同的刪除日期。
圖4.重構Address表。

關於圖4的一個有趣的事情是將Country列添加到Address。等一下,目錄中沒有添加列資料庫重構。我們發現了一種新型的資料庫重構嗎?不。資料庫重構是對資料庫模式的小改動,它們改進了他們的設計,而不僅僅是改變設計。添加新列是對模式的轉換,但不是對它的設計改進。雖然這顯然是一個非常小的細微差別我相信它是一個重要的。
要了解如何實現資料庫重構的程式碼,請閱讀重命名列資料庫重構。
圖5描繪了資料庫重構的生命周期。首先在項目範圍內實現它,如果成功,最終將其部署到生產環境中。在過渡期間,原始模式和新模式都存在,具有足夠的腳手架程式碼以確保正確支援任何更新。在過渡期間,一些應用程式將與PostCode和其他具有ZipCode的應用程式一起使用,但不能同時使用。無論它們使用哪個列,應用程式都應該正常運行。棄用期限到期後,將刪除原始架構和任何腳手架程式碼,並重新測試資料庫。在這個時間點,假設所有應用程式都使用PostCode。
圖5.資料庫重構的生命周期。

在圖5的頂部,我們將來自Disciplined Agile(DA)的3C模式應用於生命周期。這是一個三步模式:
坐標。實施重構,與組織級別的適當人員(可能是您的數據管理組)協調,以確保它進入整個變更流程。
合作。整個組織中的團隊共同努力改變與資料庫相關的任何變化(參見圖2)。
得出結論。刪除原始模式和腳手架程式碼,有效地完成重構。
4.1.5修改資料庫模式
應用程式開發人員和Agile DBA一起在開發沙箱中進行更改。策略是簡單地開始每個重構,首先通過在開發沙箱中執行重構,您實際上將自己置於圖1中描述的情況中。
為此,您需要更新兩個日誌(假設您沒有自動執行此操作的資料庫重構工具):
- 資料庫更改日誌。這是在整個項目過程中應用它們的順序實現所有資料庫模式更改的源程式碼。在實施資料庫重構時,只包括此日誌中的即時更改。在應用替換列資料庫重構時,我們將包括用於添加PostCode列的DDL和用於實現觸發器的數據定義語言(DDL),以在過渡期間維護PostCode和ZipCode列之間的值。
- 更新日誌。此日誌包含將在資料庫重構的過渡期之後運行的資料庫模式的未來更改的源程式碼。在我們的示例中,這將是刪除ZipCode列和我們引入的觸發器所需的源程式碼。
4.1.6遷移數據
許多重構要求您將舊版本的架構遷移或複製數據到新架構。您的數據遷移日誌包含數據操作語言(DML),用於在整個項目過程中重新格式化或清理源數據。在我們的示例中,這將包括任何用於提高ZipCode列中值的品質的程式碼。
4.1.7更新外部程式
訪問要重構的資料庫模式部分的程式必須更新才能使用新版本的資料庫模式。所有這些程式都必須重構,然後在過渡期到期之前部署到生產中,如圖5所示。
4.1.8運行回歸測試
一旦對應用程式程式碼和資料庫模式進行了更改,您就需要運行回歸測試套件。因為成功的測試會發現問題,所以在你做對之前需要重做工作。資料庫重構的一個重要優點是,如果您的測試確實打破了,那麼您可以很好地了解問題所在 – 在您剛剛更改的應用程式程式碼和資料庫架構中。您的更改越大,追蹤問題就越困難,因此您的開發工作就越慢,效率也就越低。你會發現,在小的漸進步驟中進行開發在實踐中非常有效。
4.1.9宣布您所做的更改
因為您的資料庫是一個共享資源,所以如果不是由多個應用程式團隊在應用程式開發團隊中共享它,那麼Agile DBA需要傳達已經發生的更改。如果您還沒有這樣做,則應更新資料庫的物理數據模型(PDM)。我個人傾向於在PDM工具(如ERWin)中對新模式進行建模,然後生成初始DDL,然後我將修改並包含在我的資料庫更改腳本中。
4.1.10版本控制你的工作
敏捷開發人員的一項關鍵技能是將所有工作都置於配置管理(CM)控制之下,通過將其檢入版本控制工具。在資料庫重構的情況下,這包括您創建的任何DDL,更改腳本,數據遷移腳本,測試數據,測試用例,測試數據生成程式碼,文檔和模型。這是您通常會修改的面嚮應用程式的工件的補充 – 對待面向資料庫的工件與處理其他開發工件的方式完全相同,您應該沒問題。
4.2第2步:在集成沙箱中實施
幾天過後,您將準備好在項目集成沙箱中實現資料庫重構。您需要等待的原因是為了讓您的隊友有時間重構自己的程式碼以使用新架構。
選擇通過使用持久性框架封裝對資料庫的訪問許可權的團隊將發現更容易對資料庫模式更改做出反應,因此可能會發現他們可以加強在開發沙箱和項目中實現資料庫重構之間的時間間隔集成沙箱。這是因為資料庫模式在元數據中表示,因此許多資料庫模式更改只需要更新元數據而不需要更新實際的源程式碼。
要部署到每個沙箱中,您需要構建應用程式並運行資料庫管理腳本(Autopatch等工具可以提供幫助)。下一步是重新運行回歸測試以確保您的系統仍然有效 – 如果不是,您將需要在開發環境中進行修復,重新部署和重新測試。項目集成沙箱中的目標是驗證團隊中每個人的工作在組合時的功能,而您在Test / QA沙箱中的目標是驗證您的系統是否適用於組織內的其他系統。
通訊是將資料庫重構部署到Test / QA沙箱中的關鍵部分,我現在使用複數,因為您通常會在此環境中同時引入多個資料庫更改(重構)。在更改資料庫模式之前,您需要與訪問資料庫的所有其他應用程式的所有者進行通訊並協商更改。您的企業管理員將參與此次談判,他們甚至可以促進工作,以確保滿足您組織的整體需求。幸運的是,您在開發沙箱中遵循的過程使資料庫重構的這一方面變得更加容易:
- Agile DBA只允許實際實現的資料庫重構 – 如果另一個應用程式團隊無法重新編寫程式碼來訪問新模式,那麼就無法進行更改。
- Agile DBA編寫的文檔,即使只是每個更改的簡要描述,也很重要,因為它提供了即將部署的更改的概述。
- 隨著資料庫重構的實施而更新的新版本物理數據模型(PDM)成為與其他團隊進行談判的焦點。敏捷建模(AM)會認為PDM是您的團隊與其他應用團隊之間的「合約模型」,他們可以指望這些模型是準確的,並且他們可以指望積极參与協商變更。
4.3第3步:安裝到生產中
安裝到生產環境是資料庫重構中最難的部分,特別是在圖2的複雜情況下。您通常不會自己部署資料庫重構,而是將它們部署為一個或多個系統的整體部署的一部分。當您有一個應用程式和一個要更新的資料庫時,部署是最簡單的,並且這種情況確實在實踐中發生,但實際上我們需要考慮您一次部署多個系統和多個數據源的情況。圖6概述了將重構部署到生產環境中的步驟。
圖6.部署資料庫重構的步驟。

圖7描述了如何安排應用程式預定義部署窗口的部署,如綠色所示。部署窗口(通常稱為發布窗口)是允許將系統部署到生產中的特定時間點。您的操作人員很可能對應用程式團隊何時部署系統有嚴格的規定。圖7顯示了兩個項目團隊如何安排將更改(包括資料庫重構)部署到可用的部署窗口中。有時沒有什麼可以部署,有時一個團隊有變化,有時兩個團隊都有架構變化要部署。
圖7.將重構調度到部署窗口中。

您自然需要與在同一部署窗口中部署的任何其他團隊進行協調。這種協調將在您部署之前很久發生,坦率地說,您的預生產測試環境存在的主要原因是提供一個沙箱,您可以在其中解決多系統問題。無論將多少資料庫重構應用於您的生產資料庫,或者這些重構是由多少團隊開發的,它們都將首先在您的預生產測試環境中進行測試,然後再應用於生產。
5.在您的組織內採用資料庫重構
雖然採用有效的工具是實現資料庫重構的重要部分,但它只是冰山一角 – 資料庫重構需要在組織內進行重大的文化變革。由於資料庫重構是敏捷數據方法的一種支援技術,因此採用資料庫重構的許多文化問題與採用敏捷數據方法時面臨的問題相同。這些文化問題包括許多數據專業人員的一系列思維方式,對變革的抵制以及政治惰性。以下方法可以幫助您克服這些挑戰:
- 從簡單開始。在新應用程式訪問新資料庫的綠地環境中,資料庫重構最容易,下一個最簡單的情況是單個應用程式訪問舊資料庫時。這兩種情況都以圖1為代表。通過簡單的開始,您可以為自己提供一個可以學習基礎知識的環境,一旦您了解了基礎知識,您就可以更好地解決圖2所示的情況。
- 接受迭代和增量開發是常態。現代軟體開發方法採用迭代和增量方法進行軟體開發。儘管串列開發通常是許多數據專業人員的首選方法,但遺憾的是它並未反映應用程式開發人員當前的工作方式。是時候改變了。
- 接受沒有神奇的解決方案讓你擺脫現有的混亂局面。您的數據品質問題並沒有自行創建,也無法自行修復。人們創造了問題,人們需要解決問題。資料庫重構是您可以從數據技術債務中挖掘出來的最安全,最直接的策略。
- 採用100%資料庫回歸測試策略。要使資料庫重構工作,並且通常要使迭代和增量開發工作,您需要在回歸測試中有效。要在資料庫重構方面取得成功,您不僅需要對資料庫本身進行回歸測試,還需要對與資料庫耦合的任何應用程式進行回歸測試。這意味著您需要為每個應用程式提供回歸測試套件,這是您很可能沒有的。所以開始寫它們。
- 探索技術。首先在簡單的情況下嘗試資料庫重構,以學習技術並獲得一些經驗。然後開始重構更複雜的事情。所以,開始簡單吧。
資料庫重構在實踐中起作用,它不僅僅是另一種學術理論。對於絕大多數組織而言,這是一種新的「前沿」技術。
6.資料庫重構最佳實踐
Fowler(1999)提出了一系列程式碼重構的最佳實踐,我在下面重新構建了資料庫重構的實踐:
- 重構以簡化模式的添加。
- 確保測試套件到位。
- 邁出小步。
- 人民計劃。
- 不要過早發布數據模型。
- 對文件的需求反映了重構的必要性。
- 經常測試。
7.現實世界中的資料庫重構
資料庫重構支援資料庫模式演變的漸進方法,這是三個基本策略之一(您可以放棄,採取「大爆炸」方法,採取增量方法)。每種策略都有其獨特的優點和缺點。我懷疑許多組織,或許是因為一種連續的思維方式,要麼嘗試過大爆炸的方法,要麼已經太害怕了,現在已經放棄了。它不一定是這樣的。是的,您的組織可能需要花費大量精力來制定文化和技術來支援整個企業的資料庫重構,但從長遠來看,這可能比您的其他選擇更加可口。
請參閱資料庫重構目錄
無論您的策略如何,資料庫的演變都很難,當您的資料庫與其他事物高度耦合時,尤其如此。資料庫重構不是一個可以神奇地解決所有資料庫問題的靈丹妙藥。本文介紹了如何在簡單的瘦腿環境中成功實現資料庫重構。
原文:http://agiledata.org/essays/databaseRefactoring.html
本文:https://pub.intelligentx.net/agiledata-process-database-refactoring-strategies-improving-database-quality