首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

測試驅動開發實戰:重構篇——從冗餘代碼到分層架構

     編輯:關於.NET

回顧:TDD 紅-綠-重構循環

  1. 寫測試 → 紅燈(失敗)
  2. 寫代碼 → 綠燈(通過)
  3. 重構 → 保持綠燈優化結構

重構目的:消除重複、清晰結構、去除壞味道。有測試保護,重構無懼。

第一步:提取公共邏輯(DRY 原則)

重構前:SQL 操作高度重複

public int Add(string loginName) {
    int count = 0;
    using (var conn = new SqlConnection(connStr)) {
        conn.Open();
        var cmd = new SqlCommand("insert(loginName) value('" + loginName + "')", conn);
        count = cmd.ExecuteNonQuery();
        cmd.Dispose(); conn.Close();
    }
    return count;
}
public int Delete(string loginName) {
    // 除 SQL 字串外完全相同...
}

重構後:提取 ExecuteSql

private int ExecuteSql(string sql) {
    int count = 0;
    using (var conn = new SqlConnection(connStr)) {
        conn.Open();
        var cmd = new SqlCommand(sql, conn);
        count = cmd.ExecuteNonQuery();
        cmd.Dispose(); conn.Close();
    }
    return count;
}
public int Add(string loginName) => ExecuteSql("insert(loginName) value('" + loginName + "')");
public int Delete(string loginName) => ExecuteSql("delete from LoginUsers where loginName='" + loginName + "'");

代碼清晰度大幅提升。

何時重構?

代碼重複度高、層次混亂、出現「壞味道」(長方法、大類別、散彈式修改等)時皆可重構。測試是安全網。

第二步:依據設計原則分層(SOLID)

問題:登入方法混雜驗證與資料存取

違反單一職責原則(SRP)。拆分服務層與資料層。

服務層介面

public interface IEmployeeService {
    bool Login(string loginName, string password);
    bool ValidateLoginName(string loginName); // 驗證單獨抽離
}

服務層實現:依賴倒置(DIP)

public class EmployeeService : IEmployeeService {
    private readonly IEmployeeDataAccess _empDAO;
    public EmployeeService(IEmployeeDataAccess empDAO) => _empDAO = empDAO;

    public bool ValidateLoginName(string loginName) => !string.IsNullOrEmpty(loginName);

    public bool Login(string loginName, string password) {
        if (ValidateLoginName(loginName))
            return _empDAO.GetCount(loginName, password) > 0;
        return false;
    }
}

關鍵:依賴介面 IEmployeeDataAccess 而非具體實現,解耦服務層與資料層。

資料層介面

public interface IEmployeeDataAccess {
    int GetCount(string loginName, string password);
}

資料層實現(略)

public class EmployeeAccess : IEmployeeDataAccess {
    public int GetCount(string loginName, string password) => throw new NotImplementedException();
}

測試代碼同步更新:使用 Moq 模擬資料層

[TestFixture]
public class EmployeeServiceTest {
    private IEmployeeService _empService;
    [TestFixtureSetUp]
    public void Init() {
        var mockDao = new Mock<IEmployeeDataAccess>();
        mockDao.Setup(d => d.GetCount("admin", "pwd")).Returns(1);
        _empService = new EmployeeService(mockDao.Object);
    }
    [Test] public void LoginTest() => Assert.IsTrue(_empService.Login("admin", "pwd"));
    [Test] public void ValidateNullLoginName() => Assert.IsFalse(_empService.ValidateLoginName(null));
    [Test] public void ValidateEmptyLoginName() => Assert.IsFalse(_empService.ValidateLoginName(""));
}

Moq 優勢:資料層未完成時,即可模擬資料對服務層獨立測試,實現真正的分層並行開發。

總結

重構不僅是代碼整理,更是架構演進:模式為變化而生。若專案交付後無變化,模式確屬過度設計。但在真實世界,變化是常態——TDD + 重構 + 設計原則,讓我們從容應對。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved