你一定有过这样的感受——深陷遗留C#代码库时,总觉得某些地方不对劲。虽然说不清具体问题,但那种不安感如影随形。就像走进房间闻到异味却找不到源头,这就是代码异味(Code Smell)。它预示着潜在的bug、技术债务和维护噩梦。
作为拥有15年C#开发经验的程序员,我深刻明白这些异味很少是无害的。它们往往会滚雪球般演变成代价高昂的问题。下面我将列举十大最常被忽视的代码异味(没错,有些坑我自己也踩过)。这不是理论说教,而是从真实痛苦中提炼出的经验之谈,真希望有人能早点告诉我这些。
如果一个方法需要滚动屏幕才能看完,那它肯定干了太多事。我曾接手过一个500多行的ProcessAllData()
方法,里面嵌套着if判断、foreach循环和switch语句。调试这种怪物就像在无光的洞穴里探险。
代码示例:
public void ProcessAllData()
{
foreach (var user in users)
{
if (user.IsActive)
{
// 进行某些过滤
if (user.Orders != null && user.Orders.Any())
{
foreach (var order in user.Orders)
{
switch (order.Status)
{
case OrderStatus.Pending:
// 更新状态
break;
// 还有几十个case
}
}
}
}
}
// 剩余几百行代码
}
解决方法:拆分子方法,用清晰的命名。未来的你和同事都会感谢这个决定。
我曾见过一个支付系统:用string表示货币代码,用decimal处理所有金额,靠注释来保证类型安全。听起来很熟悉?
解决方案:创建有意义的值对象。大胆定义CurrencyCode
、Money
或EmailAddress
这样的类。
public class EmailAddress
{
public string Value { get; }
public EmailAddress(string value)
{
if (!IsValidEmail(value)) throw new ArgumentException();
Value = value;
}
private bool IsValidEmail(string email)
{
return Regex.IsMatch(email, "^[^@\s]+@[^@\s]+\.[^@\s]+$");
}
}
如果你看到这样的代码:
if (user.Type == "XJ9")
快逃!这些字面量毫无意义,就像恐怖片里灾难发生前的诡异符号。
应该使用枚举、常量或封装成有意义的抽象:
public enum UserType { Admin, Regular, Guest }
如果需要长篇大论解释代码,那肯定有问题:
// 这部分有点取巧,但目前能工作
我们都写过这种注释。"目前"往往意味着"永远",直到有人修改它并引发灾难。
重构代码使其自解释,用意图清晰的命名替代注释。
当方法变成这样时:
public void CreateUser(string firstName, string lastName, string email, string phone, string street, string city, string zip)
这不是在传参数,而是在乞求有人把zip和phone参数传反。
应该将相关数据分组:
public class ContactInfo { public string Email; public string Phone; }
public class Address { public string Street; public string City; public string Zip; }
想改一个功能却要动10个文件?这不是重构,而是人质谈判。
当业务逻辑分散在不相关的地方时就会出现这种情况。如果改个业务规则需要同时更新UI代码、辅助类、验证器和视图模型,就该考虑整合了。
采用合理的分层架构,将业务规则集中到领域层。
当一个类过度访问另一个类的数据时:
var fullName = user.FirstName + " " + user.LastName;
应该让User类自己处理格式化:
public string GetFullName() => $"{FirstName} {LastName}";
类应该对自己的数据负责。
如果总是传递同一组参数:
SendEmail(string from, string to, string subject, string body);
不如封装成类:
SendEmail(EmailMessage message);
更清晰、更安全、更易测试。
被注释的代码、未使用的方法、过时的类,就像代码库里的囤积癖。
// public void OldProcess() { ... }
直接删除吧,版本控制就是干这个的。
像这样调用方法毫无上下文:
Process(true, false);
改用枚举或描述性参数对象:
Process(ProcessingMode.Fast);
忽视代码异味就像对建筑物里的烟雾视而不见。也许现在还没着火,但你在玩火。保持敏锐的嗅觉,无情地重构。
所有这些异味都来自真实项目,来自血泪教训。不要重蹈我的覆辙。整洁代码不是追求完美,而是体现专业、清晰和匠心。
而C#语言本身已为你提供了所有工具,关键在于你是否使用它们。