mi-assessment/docs/开发规范/1-编程规约/1.3-注释规约.md
2026-02-03 20:50:51 +08:00

476 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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&lt;OrderItemDto&gt;
/// {
/// 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;
```