# 1.3 注释规约
---
## 1. XML 文档注释
- 类注释
```csharp
///
/// 订单服务,提供订单管理相关业务逻辑
///
///
/// 此服务负责:
/// - 订单创建、查询、更新、删除
/// - 订单状态流转
/// - 订单金额计算
///
public class OrderService : IOrderService
{
// ...existing code...
}
```
- 接口注释
```csharp
///
/// 订单仓储接口,定义订单数据访问操作
///
public interface IOrderRepository
{
///
/// 根据订单ID获取订单详情
///
/// 订单ID
/// 订单实体,如果不存在返回 null
Task GetByIdAsync(int orderId);
}
```
- 方法注释
```csharp
///
/// 创建新订单
///
/// 订单创建请求对象
/// 创建成功的订单实体
/// 当 request 为 null 时抛出
/// 当订单数据验证失败时抛出
/// 当库存不足时抛出
///
/// 此方法执行以下步骤:
/// 1. 验证请求数据
/// 2. 检查库存
/// 3. 计算订单金额
/// 4. 创建订单记录
/// 5. 发送确认邮件
///
///
///
/// var request = new CreateOrderRequest
/// {
/// CustomerId = 123,
/// Items = new List<OrderItemDto>
/// {
/// new() { ProductId = 1, Quantity = 2 }
/// }
/// };
/// var order = await orderService.CreateOrderAsync(request);
///
///
public async Task CreateOrderAsync(CreateOrderRequest request)
{
// ...existing code...
}
```
- 属性注释
```csharp
///
/// 获取或设置订单ID
///
public int Id { get; set; }
///
/// 获取或设置客户ID
///
public int CustomerId { get; set; }
///
/// 获取或设置订单总金额(含税)
///
/// 订单总金额,单位:元
public decimal TotalAmount { get; set; }
///
/// 获取或设置订单是否已完成
///
///
/// true 表示订单已完成;否则为 false
///
public bool IsCompleted { get; set; }
```
- 枚举注释
```csharp
///
/// 订单状态枚举
///
public enum OrderStatus
{
///
/// 待处理
///
Pending = 0,
///
/// 处理中
///
Processing = 1,
///
/// 已完成
///
Completed = 2,
///
/// 已取消
///
Cancelled = 3
}
```
- 泛型参数注释
```csharp
///
/// 通用仓储接口
///
/// 实体类型,必须是引用类型
public interface IRepository where T : class
{
///
/// 根据ID获取实体
///
/// 实体ID
/// 实体对象,如果不存在返回 null
Task GetByIdAsync(int id);
}
```
## 2. 行内注释使用场景
- 解释复杂业务逻辑
```csharp
public decimal CalculateDiscount(Order order)
{
// 根据业务规则BR-2023-001:
// VIP客户订单金额超过1000元享受9折优惠
// 新客户首单享受95折优惠
// 优惠不可叠加,取最优惠方案
if (order.Customer.IsVip && order.TotalAmount > 1000)
{
return order.TotalAmount * 0.1m;
}
if (order.Customer.IsNewCustomer && order.IsFirstOrder)
{
return order.TotalAmount * 0.05m;
}
return 0;
}
```
- 解释不明显的代码意图
```csharp
public void ProcessOrder(Order order)
{
// 将订单状态设置为处理中,防止并发处理同一订单
order.Status = OrderStatus.Processing;
order.LastModifiedDate = DateTime.UtcNow;
// 使用UTC时间避免时区问题
var processStartTime = DateTime.UtcNow;
// 临时解决方案:忽略已删除的订单项
// TODO: 后续需要从数据库层面过滤
var activeItems = order.Items.Where(i => !i.IsDeleted).ToList();
}
```
- 标记临时代码或待优化代码
```csharp
public async Task> GetOrdersAsync(int customerId)
{
// HACK: 临时解决方案,直接加载所有订单
// 性能问题:当订单量大时会导致内存占用过高
// TODO: 实现分页加载
var orders = await _context.Orders
.Where(o => o.CustomerId == customerId)
.ToListAsync();
return orders;
}
```
- 解释算法或公式
```csharp
public decimal CalculateShippingFee(Order order)
{
// 运费计算公式:
// 基础运费 = 10元
// 重量费用 = 总重量 * 2元/kg
// 距离费用 = 距离 * 0.5元/km
// 如果订单金额超过200元,免运费
if (order.TotalAmount >= 200)
{
return 0;
}
var baseFee = 10m;
var weightFee = order.TotalWeight * 2m;
var distanceFee = order.DeliveryDistance * 0.5m;
return baseFee + weightFee + distanceFee;
}
```
## 3. `TODO`、`FIXME`、`HACK`、`NOTE`/`IMPORTANT` 标记使用
- `TODO` - 待实现功能
```csharp
public class OrderService
{
public async Task CreateOrderAsync(Order order)
{
await _repository.AddAsync(order);
// TODO: 实现订单创建后发送确认邮件
// TODO: 实现库存扣减逻辑
// TODO: 集成支付网关
}
// TODO: [张三] 2024-01-15 实现退款功能
public Task RefundOrderAsync(int orderId)
{
throw new NotImplementedException();
}
}
```
- `FIXME` - 已知问题需要修复
```csharp
public async Task> GetOrdersAsync(int pageIndex, int pageSize)
{
// FIXME: 当pageSize过大时会导致性能问题
// FIXME: 未处理pageIndex为负数的情况
return await _context.Orders
.Skip(pageIndex * pageSize)
.Take(pageSize)
.ToListAsync();
}
public decimal CalculateTotal(Order order)
{
// FIXME: 并发情况下可能导致重复计算
// 需要添加锁机制或使用数据库事务
return order.Items.Sum(i => i.Price * i.Quantity);
}
```
- `HACK` - 临时解决方案
```csharp
public async Task ProcessOrderAsync(int orderId)
{
// HACK: 临时方案,硬编码重试3次
// 应该从配置文件读取重试次数
for (int i = 0; i < 3; i++)
{
try
{
await ProcessAsync(orderId);
break;
}
catch (Exception ex)
{
if (i == 2)
{
throw;
}
await Task.Delay(1000);
}
}
}
```
- `NOTE`/`IMPORTANT` - 重要说明
```csharp
public class PaymentService
{
// NOTE: 此方法会修改订单状态,调用前请确保已获取锁
// IMPORTANT: 必须在事务中调用此方法
public async Task ProcessPaymentAsync(Payment payment)
{
// ...existing code...
}
}
```
## 4. 复杂业务逻辑注释要求
- 业务规则注释
```csharp
public bool CanApplyDiscount(Order order, Customer customer)
{
// 业务规则 BR-2024-001: 折扣适用条件
// 1. 客户必须是激活状态
// 2. 订单金额必须大于等于100元
// 3. 客户当月订单数量不超过10个
// 4. 产品不在促销黑名单中
if (!customer.IsActive)
{
return false;
}
if (order.TotalAmount < 100)
{
return false;
}
var monthlyOrderCount = GetMonthlyOrderCount(customer.Id);
if (monthlyOrderCount > 10)
{
return false;
}
var hasBlacklistedProducts = order.Items.Any(i => IsProductBlacklisted(i.ProductId));
return !hasBlacklistedProducts;
}
```
- 状态机转换注释
```csharp
public void UpdateOrderStatus(Order order, OrderStatus newStatus)
{
// 订单状态转换规则:
// Pending -> Processing (允许)
// Pending -> Cancelled (允许)
// Processing -> Completed (允许)
// Processing -> Cancelled (不允许,必须先退款)
// Completed -> Refunded (允许,需要走退款流程)
// Cancelled -> * (不允许任何转换)
var allowedTransitions = new Dictionary>
{
{ OrderStatus.Pending, new List { OrderStatus.Processing, OrderStatus.Cancelled } },
{ OrderStatus.Processing, new List { OrderStatus.Completed } },
{ OrderStatus.Completed, new List { OrderStatus.Refunded } }
};
if (!allowedTransitions.ContainsKey(order.Status) || !allowedTransitions[order.Status].Contains(newStatus))
{
throw new InvalidOperationException($"不允许从 {order.Status} 转换到 {newStatus}");
}
order.Status = newStatus;
}
```
- 复杂计算注释
```csharp
public decimal CalculateCommission(Order order, Salesperson salesperson)
{
// 佣金计算规则(2024年Q1版本):
//
// 基础佣金率:
// - 初级销售:订单金额的 3%
// - 中级销售:订单金额的 5%
// - 高级销售:订单金额的 8%
//
// 阶梯奖励(累加):
// - 月度销售额超过 10万,额外 +1%
// - 月度销售额超过 50万,额外 +2%
// - 月度销售额超过100万,额外 +3%
//
// 特殊产品加成:
// - 高端产品类别,佣金率 *1.5
var baseRate = salesperson.Level switch
{
SalesLevel.Junior => 0.03m,
SalesLevel.Intermediate => 0.05m,
SalesLevel.Senior => 0.08m,
_ => 0.03m
};
var monthlySales = GetMonthlySales(salesperson.Id);
var bonusRate = monthlySales switch
{
>= 1000000 => 0.03m,
>= 500000 => 0.02m,
>= 100000 => 0.01m,
_ => 0m
};
var finalRate = baseRate + bonusRate;
var hasHighEndProducts = order.Items.Any(i => i.Product.Category == ProductCategory.HighEnd);
if (hasHighEndProducts)
{
finalRate *= 1.5m;
}
return order.TotalAmount * finalRate;
}
```
## 5. 注释的维护与更新
- 注释应与代码同步更新
```csharp
// ❌ 错误:注释已过时
// 返回所有订单(实际代码已改为返回激活订单)
public List GetOrders()
{
return _context.Orders
.Where(o => o.IsActive) // 代码已修改,但注释未更新
.ToList();
}
// ✅ 正确:更新注释
///
/// 获取所有激活状态的订单
///
public List GetActiveOrders()
{
return _context.Orders
.Where(o => o.IsActive)
.ToList();
}
```
- 删除无用注释
```csharp
// ❌ 错误:保留已注释的旧代码
public void ProcessOrder(Order order)
{
// var oldDiscount = order.TotalAmount * 0.05m;
// order.DiscountAmount = oldDiscount;
// 新的折扣计算逻辑
var newDiscount = CalculateDiscount(order);
order.DiscountAmount = newDiscount;
}
// ✅ 正确:删除已注释代码,使用版本控制系统管理历史
public void ProcessOrder(Order order)
{
var discount = CalculateDiscount(order);
order.DiscountAmount = discount;
}
```
- 避免显而易见的注释
```csharp
// ❌ 错误:显而易见的注释
// 设置客户名称
customer.Name = "张三";
// 增加计数器
counter ++;
// ✅ 正确:只注释需要解释的内容
// 使用UTC时间避免时区转换问题
order.CreatedDate = DateTime.UtcNow;
// 预留30天的订单保留期
var retentionDays = 30;
```