引言:为什么遗留代码需要重构?
\n\n每个使用.NET平台的开发者迟早都会遇到遗留代码。这些是用旧版C#(例如.NET Framework 4.x)编写的程序,使用诸如ASP.NET Web Forms中的DataTable或数千行的单体类等过时模式。此类代码是技术债务的根源:难以维护,包含隐藏的错误,并阻碍新功能的引入。
重构是在不改变代码外部行为的情况下改变其内部结构的过程。在本文中,我们将分解C#遗留代码重构的分步计划,从诊断到引入现代实践。您将学习如何使用.NET工具和经过验证的技术安全地改进旧项目。
\n\n1. 诊断与准备:从何开始?
\n\n在修改代码之前,有必要了解其当前状态。没有分析,您就有可能破坏功能。
\n\n1.1. 评估技术债务
\n使用Visual Studio内置或通过NuGet获取的代码分析器:
\n- \n
- Roslyn分析器 — 发现潜在错误和过时结构。 \n
- SonarQube(或SonarCloud) — 评估代码质量、重复、复杂度。 \n
- NDepend — 可视化类与模块之间的依赖关系。 \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\n1.3. 选择策略:“菜园策略”
\n不要试图一次性重构整个项目。选择一个带来最多问题的模块或类(高复杂度、频繁错误)。迭代工作:小步骤,频繁提交。
\n\n2. C#遗留代码重构的主要技术
\n\n让我们考虑一些关键技巧,帮助将“意大利面条式代码”转变为清晰的架构。
\n\n2.1. 摆脱上帝对象(大型类)
\n遗留代码通常包含什么都做的类:操作数据库、验证数据、发送电子邮件。使用单一职责原则(SRP)。
\n\n重构前:
\npublic 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重构后:
\npublic 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