- 軟件再工程:優化現有軟件系統的方法與最佳實踐
- (美)Bradley Irby
- 920字
- 2020-11-04 16:44:57
1.3 理解耦合
耦合指的是兩段代碼之間的關聯性。兩個類可以是緊耦合也可以是松耦合,這是由兩個類之間信息的互通程度決定的。兩個類之間的緊密信息越多,它們的耦合度越高。那么“緊密信息”意味著什么?參見代碼清單1.6展示的例子。
代碼清單1.6 緊耦合類的例子
/// <summary> /// This class will retrieve a string from the database and /// display it on the screen. /// </summary> public class ShowDatabaseInfo { /// <summary> /// Main driver method /// </summary> public void GetAndShowData(int recordId) { ADODB.Recordset data = GetData(); DisplayForm frm = GetForm(); ShowDataInForm(frm, data); } /// <summary> /// Open an ADO connection to Microsoft SQL Server, /// get the data, and return it. /// </summary> public ADODB.Recordset GetData() { var connection = new ADODB.Connection(); connection.ConnectionString = "my connection string"; connection.Open(); var rs = new ADODB.Recordset(); //The following query is specific to Microsoft SQL Server //it will not execute properly on Oracle. rs.Open("Microsoft SQL Specific Query", connection); rs.ActiveConnection = null; return rs; } /// <summary> /// Get the proper form to use for our display /// </summary> private DisplayForm GetForm() { return new DisplayForm(); } /// <summary> /// Show the information to the user in the given form. /// </summary> public void ShowDataInForm(DisplayForm frm, ADODB.Recordset data) { frm.UserInfo = data; frm.Show(); } } /// <summary> /// Form that displays the information to the user. /// </summary> public class DisplayForm : Form { private readonly Label _userFirstNameLbl; private readonly Label _userLastNameLbl; private ADODB.Recordset _userInfo; /// <summary> /// Constructor that creates the data display form. /// </summary> public DisplayForm() { _userFirstNameLbl = new Label(); Controls.Add(_userFirstNameLbl); _userLastNameLbl = new Label(); Controls.Add(_userLastNameLbl); } /// <summary> /// Property to assign the data to the proper labels. /// </summary> public ADODB.Recordset UserInfo { get { return _userInfo; } set { _userInfo = value; _userFirstNameLbl.Text = _userInfo.Fields[0].ToString(); _userLastNameLbl.Text = _userInfo.Fields[0].ToString(); } } }
在這個例子中,ShowDatabaseInfo類與很多方面存在著緊耦合的關系。首先,我們來檢驗它同DisplayForm的緊耦合關系。直接在代碼中創建一些東西會導致緊耦合,因為這會產生對那個特定類的依賴性。如代碼清單1.7所示,假設代碼清單聲明另外一個顯示窗體叫做DisplayFormDescendant。
代碼清單1.7 DisplayForm Descendant
public class DisplayFormDescendant : DisplayForm { //empty class }
DisplayFormDescendant沒有增加任何東西到DisplayForm。它表現得和DisplayForm一模一樣,而且理論上它是一次完美的替換。然而,再看下ShowDatabaseInfo類,如果GetForm方法試著創建并返回DisplayFormDescendant而不是DisplayForm,那么整個解決方案就不能成功生成。要完成這次替換,我們不得不把所有出現DisplayForm的地方都替換為DisplayFormDescendant。這就是所謂的對DisplayForm的依賴性,同時這使得代碼很脆弱。
在例1.7中,另外一個緊耦合的例子是數據訪問技術Active數據對象(Active Data Object,ADO)。如果引入另一種數據訪問技術(比如EntityFramework),而且想使用該項技術,但由于對ADO關聯類各種各樣的依賴,我們不得不重構整個應用程序。這種與ADO的緊耦合使得應用程序很脆弱,因為任何對某處進行修改的嘗試都會導致其他地方不相關的改變。
在本例中,一種比較弱的依賴關系體現在對Microsoft SQL Server的依賴性上。因為我們的數據查詢含有特定于Microsoft SQL Server的細節,所以不能移植到Oracle上。如果應用程序需要支持Microsoft和Oracle兩種數據庫,那么我們不得不維護兩個完全獨立的代碼段。這是脆弱的代碼。
在后續篇章中,你將學習如何將這種緊耦合、脆弱的代碼轉變為比較容易維護和更新的代碼。接口是完成這種轉變的關鍵部分。