C# 中的 Clean Code:如何编写让人想读的代码
每个 .NET 开发人员都遇到过这样的情况:一两个月后,自己的代码变得难以阅读。为了避免这种情况,存在由 Robert Martin 推广的 Clean Code 哲学。在本文中,我们将通过具体示例分析 C# 中 Clean Code 的基本原则,帮助您编写可维护和可扩展的应用程序。
为什么 Clean Code 对 C# 开发人员很重要?
Clean Code 不仅仅是漂亮的格式。它是一套让代码具备以下特性的实践:
- 可读性 — 任何开发人员都能快速理解逻辑;
- 可维护性 — 易于修改而不会破坏系统;
- 可测试性 — 代码易于被单元测试覆盖;
- 高效性 — 没有多余的抽象和重复。
在 C# 中,凭借其强类型和 .NET 的强大功能(LINQ、async/await、Records),遵循 Clean Code 原则尤为重要。糟糕的 C# 代码可能导致难以发现的错误和性能问题。
原则 1:变量和方法的命名
变量或方法的名称应该回答"这是什么?"或"它做什么?"的问题。避免使用单字母缩写(循环索引除外)。
糟糕的示例
public class Data{ public int a; // 这是什么? public string b; // 不清楚
public void Do(int x, int y) // 这个方法做什么? { var r = x + y; Console.WriteLine(r); }}好的示例 (Clean Code)
public class Customer{ public int Id { get; set; } public string FullName { get; set; }
public void PrintCustomerSummary(int customerId, int orderCount) { var totalOrders = customerId + orderCount; Console.WriteLine($"Customer {customerId} has {totalOrders} orders"); }}规则:名称应该具有表现力。如果变量名为 data,这几乎总是不好的。请使用 customerData、orderList、invoiceTotal。
原则 2:单一职责的小方法
每个方法应该只做一件事。如果方法包含超过 10-15 行代码,很可能需要拆分。这是 Single Responsibility 原则(来自 SOLID)的基础。
糟糕的示例(方法做所有事情)
public void ProcessOrder(int orderId){ // 1. 验证 if (orderId <= 0) throw new ArgumentException("Invalid ID"); // 2. 从数据库获取数据 var order = _db.Orders.Find(orderId); // 3. 计算折扣 decimal discount = 0; if (order.Total > 1000) discount = order.Total * 0.1m; // 4. 发送邮件 var email = new MailMessage(); email.To.Add(order.CustomerEmail); email.Subject = "Order processed"; // 5. 日志记录 _logger.LogInformation("Order {Id} processed", orderId);}好的示例(重构后)
public void ProcessOrder(int orderId){ ValidateOrderId(orderId); var order = GetOrderFromDatabase(orderId); var discount = CalculateDiscount(order); SendConfirmationEmail(order, discount); LogOrderProcessing(orderId);}
private void ValidateOrderId(int orderId){ if (orderId <= 0) throw new ArgumentException("Order ID must be positive", nameof(orderId));}
private Order GetOrderFromDatabase(int orderId){ return _db.Orders.Find(orderId) ?? throw new InvalidOperationException("Order not found");}
private decimal CalculateDiscount(Order order){ return order.Total > 1000 ? order.Total * 0.1m : 0;}
private void SendConfir