C#遗留代码重构:从A到Z

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:为什么遗留代码需要重构?

\n\n

每个使用.NET平台的开发者迟早都会遇到遗留代码。这些是用旧版C#(例如.NET Framework 4.x)编写的程序,使用诸如ASP.NET Web Forms中的DataTable或数千行的单体类等过时模式。此类代码是技术债务的根源:难以维护,包含隐藏的错误,并阻碍新功能的引入。

\n\n

重构是在不改变代码外部行为的情况下改变其内部结构的过程。在本文中,我们将分解C#遗留代码重构的分步计划,从诊断到引入现代实践。您将学习如何使用.NET工具和经过验证的技术安全地改进旧项目。

\n\n

1. 诊断与准备:从何开始?

\n\n

在修改代码之前,有必要了解其当前状态。没有分析,您就有可能破坏功能。

\n\n

1.1. 评估技术债务

\n

使用Visual Studio内置或通过NuGet获取的代码分析器:

\n
    \n
  • Roslyn分析器 — 发现潜在错误和过时结构。
  • \n
  • SonarQube(或SonarCloud) — 评估代码质量、重复、复杂度。
  • \n
  • NDepend — 可视化类与模块之间的依赖关系。
  • \n
\n\n

1.2. 编写测试作为安全网

\n

没有测试的重构就像玩俄罗斯轮盘赌。遗留代码通常没有单元测试。从编写特征测试(characterization tests)开始,这些测试记录当前行为:

\n\n
// 旧方法的测试示例\n[Test]\npublic void CalculateDiscount_ShouldReturn10Percent_WhenOrderTotalIsGreaterThan100()\n{\n    // Arrange\n    var legacyClass = new OrderProcessor();\n    var order = new Order { Total = 150 };\n    \n    // Act\n    var result = legacyClass.CalculateDiscount(order);\n    \n    // Assert\n    Assert.AreEqual(15, result); // 150的10%\n}
\n\n

为关键路径创建测试。这将使您能够安全地进行重构,知道行为不会改变。

\n\n

1.3. 选择策略:“菜园策略”

\n

不要试图一次性重构整个项目。选择一个带来最多问题的模块或类(高复杂度、频繁错误)。迭代工作:小步骤,频繁提交。

\n\n

2. C#遗留代码重构的主要技术

\n\n

让我们考虑一些关键技巧,帮助将“意大利面条式代码”转变为清晰的架构。

\n\n

2.1. 摆脱上帝对象(大型类)

\n

遗留代码通常包含什么都做的类:操作数据库、验证数据、发送电子邮件。使用单一职责原则(SRP)。

\n\n

重构前:

\n
public class UserService\n{\n    public void RegisterUser(string name, string email)\n    {\n        // 验证\n        if (string.IsNullOrEmpty(name)) throw new Exception();\n        \n        // 数据库操作\n        using (var conn = new SqlConnection("..."))\n        {\n            conn.Execute("INSERT INTO Users ...");\n        }\n        \n        // 发送电子邮件\n        SmtpClient client = new SmtpClient();\n        client.Send(new MailMessage(...));\n    }\n}
\n\n

重构后:

\n
public class UserService\n{\n    private readonly IUserRepository _userRepository;\n    private readonly IEmailService _emailService;\n    private readonly IValidator<UserRegistration> _validator;\n\n    public UserService(IUserRepository repo, IEmailService email, IValidator<UserRegistration> validator)\n    {\n        _userRepository = repo;\n        _emailService = email;\n        _validator = validator;\n    }\n\n    public void RegisterUse                

博客

书籍推荐