476 lines
13 KiB
Markdown
476 lines
13 KiB
Markdown
# 1.3 注释规约
|
||
|
||
---
|
||
|
||
## 1. XML 文档注释
|
||
- 类注释
|
||
```csharp
|
||
/// <summary>
|
||
/// 订单服务,提供订单管理相关业务逻辑
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// 此服务负责:
|
||
/// - 订单创建、查询、更新、删除
|
||
/// - 订单状态流转
|
||
/// - 订单金额计算
|
||
/// </remarks>
|
||
public class OrderService : IOrderService
|
||
{
|
||
// ...existing code...
|
||
}
|
||
```
|
||
|
||
- 接口注释
|
||
```csharp
|
||
/// <summary>
|
||
/// 订单仓储接口,定义订单数据访问操作
|
||
/// </summary>
|
||
public interface IOrderRepository
|
||
{
|
||
/// <summary>
|
||
/// 根据订单ID获取订单详情
|
||
/// </summary>
|
||
/// <param name="orderId">订单ID</param>
|
||
/// <returns>订单实体,如果不存在返回 null</returns>
|
||
Task<Order> GetByIdAsync(int orderId);
|
||
}
|
||
```
|
||
|
||
- 方法注释
|
||
```csharp
|
||
/// <summary>
|
||
/// 创建新订单
|
||
/// </summary>
|
||
/// <param name="request">订单创建请求对象</param>
|
||
/// <returns>创建成功的订单实体</returns>
|
||
/// <exception cref="ArgumentNullException">当 request 为 null 时抛出</exception>
|
||
/// <exception cref="ValidationException">当订单数据验证失败时抛出</exception>
|
||
/// <exception cref="InsufficientStockException">当库存不足时抛出</exception>
|
||
/// <remarks>
|
||
/// 此方法执行以下步骤:
|
||
/// 1. 验证请求数据
|
||
/// 2. 检查库存
|
||
/// 3. 计算订单金额
|
||
/// 4. 创建订单记录
|
||
/// 5. 发送确认邮件
|
||
/// </remarks>
|
||
/// <example>
|
||
/// <code>
|
||
/// var request = new CreateOrderRequest
|
||
/// {
|
||
/// CustomerId = 123,
|
||
/// Items = new List<OrderItemDto>
|
||
/// {
|
||
/// new() { ProductId = 1, Quantity = 2 }
|
||
/// }
|
||
/// };
|
||
/// var order = await orderService.CreateOrderAsync(request);
|
||
/// </code>
|
||
/// </example>
|
||
public async Task<Order> CreateOrderAsync(CreateOrderRequest request)
|
||
{
|
||
// ...existing code...
|
||
}
|
||
```
|
||
|
||
- 属性注释
|
||
```csharp
|
||
/// <summary>
|
||
/// 获取或设置订单ID
|
||
/// </summary>
|
||
public int Id { get; set; }
|
||
|
||
/// <summary>
|
||
/// 获取或设置客户ID
|
||
/// </summary>
|
||
public int CustomerId { get; set; }
|
||
|
||
/// <summary>
|
||
/// 获取或设置订单总金额(含税)
|
||
/// </summary>
|
||
/// <value>订单总金额,单位:元</value>
|
||
public decimal TotalAmount { get; set; }
|
||
|
||
/// <summary>
|
||
/// 获取或设置订单是否已完成
|
||
/// </summary>
|
||
/// <value>
|
||
/// <c>true</c> 表示订单已完成;否则为 <c>false</c>
|
||
/// </value>
|
||
public bool IsCompleted { get; set; }
|
||
```
|
||
|
||
- 枚举注释
|
||
```csharp
|
||
/// <summary>
|
||
/// 订单状态枚举
|
||
/// </summary>
|
||
public enum OrderStatus
|
||
{
|
||
/// <summary>
|
||
/// 待处理
|
||
/// </summary>
|
||
Pending = 0,
|
||
|
||
/// <summary>
|
||
/// 处理中
|
||
/// </summary>
|
||
Processing = 1,
|
||
|
||
/// <summary>
|
||
/// 已完成
|
||
/// </summary>
|
||
Completed = 2,
|
||
|
||
/// <summary>
|
||
/// 已取消
|
||
/// </summary>
|
||
Cancelled = 3
|
||
}
|
||
```
|
||
|
||
- 泛型参数注释
|
||
```csharp
|
||
/// <summary>
|
||
/// 通用仓储接口
|
||
/// </summary>
|
||
/// <typeparam name="T">实体类型,必须是引用类型</typeparam>
|
||
public interface IRepository<T> where T : class
|
||
{
|
||
/// <summary>
|
||
/// 根据ID获取实体
|
||
/// </summary>
|
||
/// <param name="id">实体ID</param>
|
||
/// <returns>实体对象,如果不存在返回 null</returns>
|
||
Task<T> 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<List<Order>> 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<List<Order>> 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, List<OrderStatus>>
|
||
{
|
||
{ OrderStatus.Pending, new List<OrderStatus> { OrderStatus.Processing, OrderStatus.Cancelled } },
|
||
{ OrderStatus.Processing, new List<OrderStatus> { OrderStatus.Completed } },
|
||
{ OrderStatus.Completed, new List<OrderStatus> { 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<Order> GetOrders()
|
||
{
|
||
return _context.Orders
|
||
.Where(o => o.IsActive) // 代码已修改,但注释未更新
|
||
.ToList();
|
||
}
|
||
|
||
// ✅ 正确:更新注释
|
||
/// <summary>
|
||
/// 获取所有激活状态的订单
|
||
/// </summary>
|
||
public List<Order> 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;
|
||
``` |