# 外卖SaaS系统 - 开发规范

## 1. 代码规范

### 1.1 命名规范

#### C#命名规范
```csharp
// 类名：PascalCase
public class OrderService { }

// 接口：I + PascalCase
public interface IOrderRepository { }

// 方法：PascalCase
public async Task<Order> CreateOrderAsync() { }

// 私有字段：_camelCase
private readonly IOrderRepository _orderRepository;

// 公共属性：PascalCase
public string OrderNo { get; set; }

// 局部变量：camelCase
var orderTotal = 100.00m;

// 常量：PascalCase
public const int MaxOrderItems = 50;

// 枚举：PascalCase
public enum OrderStatus
{
    Pending = 1,
    Confirmed = 2,
    Completed = 3
}
```

#### 数据库命名规范
```sql
-- 表名：小写，下划线分隔，复数
orders
order_items
merchant_stores

-- 字段名：小写，下划线分隔
order_no
created_at
total_amount

-- 索引：idx_表名_字段名
idx_orders_merchant_id
idx_orders_created_at

-- 外键：fk_表名_引用表名
fk_orders_merchants
```

### 1.2 代码组织

#### 项目结构
```
TakeoutSaaS/
├── src/
│   ├── TakeoutSaaS.Api/              # Web API层
│   │   ├── Controllers/              # 控制器
│   │   ├── Filters/                  # 过滤器
│   │   ├── Middleware/               # 中间件
│   │   ├── Models/                   # DTO模型
│   │   └── Program.cs
│   ├── TakeoutSaaS.Application/      # 应用层
│   │   ├── Services/                 # 应用服务
│   │   ├── DTOs/                     # 数据传输对象
│   │   ├── Interfaces/               # 服务接口
│   │   ├── Validators/               # 验证器
│   │   ├── Mappings/                 # 对象映射
│   │   └── Commands/                 # CQRS命令
│   │       └── Queries/              # CQRS查询
│   ├── TakeoutSaaS.Domain/           # 领域层
│   │   ├── Entities/                 # 实体
│   │   ├── ValueObjects/             # 值对象
│   │   ├── Enums/                    # 枚举
│   │   ├── Events/                   # 领域事件
│   │   └── Interfaces/               # 仓储接口
│   ├── TakeoutSaaS.Infrastructure/   # 基础设施层
│   │   ├── Data/                     # 数据访问
│   │   │   ├── EFCore/              # EF Core实现
│   │   │   ├── Dapper/              # Dapper实现
│   │   │   └── Repositories/        # 仓储实现
│   │   ├── Cache/                    # 缓存实现
│   │   ├── MessageQueue/             # 消息队列
│   │   └── ExternalServices/         # 外部服务
│   └── TakeoutSaaS.Shared/           # 共享层
│       ├── Constants/                # 常量
│       ├── Exceptions/               # 异常
│       ├── Extensions/               # 扩展方法
│       └── Results/                  # 统一返回结果
├── tests/
│   ├── TakeoutSaaS.UnitTests/        # 单元测试
│   ├── TakeoutSaaS.IntegrationTests/ # 集成测试
│   └── TakeoutSaaS.PerformanceTests/ # 性能测试
└── docs/                             # 文档
```

### 1.3 代码注释

```csharp
/// <summary>
/// 订单服务接口
/// </summary>
public interface IOrderService
{
    /// <summary>
    /// 创建订单
    /// </summary>
    /// <param name="request">订单创建请求</param>
    /// <returns>订单信息</returns>
    /// <exception cref="BusinessException">业务异常</exception>
    Task<OrderDto> CreateOrderAsync(CreateOrderRequest request);
}

// 复杂业务逻辑添加注释
public async Task<decimal> CalculateOrderAmount(Order order)
{
    // 1. 计算菜品总金额
    var dishAmount = order.Items.Sum(x => x.Price * x.Quantity);

    // 2. 计算配送费（距离 > 3km，每公里加收2元）
    var deliveryFee = CalculateDeliveryFee(order.Distance);

    // 3. 应用优惠券折扣
    var discount = await ApplyCouponDiscountAsync(order.CouponId, dishAmount);

    // 4. 计算最终金额
    return dishAmount + deliveryFee - discount;
}
```

### 1.4 异常处理

```csharp
// 自定义业务异常
public class BusinessException : Exception
{
    public int ErrorCode { get; }

    public BusinessException(int errorCode, string message)
        : base(message)
    {
        ErrorCode = errorCode;
    }
}

// 全局异常处理中间件
public class ExceptionHandlingMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<ExceptionHandlingMiddleware> _logger;

    public async Task InvokeAsync(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (BusinessException ex)
        {
            _logger.LogWarning(ex, "业务异常：{Message}", ex.Message);
            await HandleBusinessExceptionAsync(context, ex);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "系统异常：{Message}", ex.Message);
            await HandleSystemExceptionAsync(context, ex);
        }
    }

    private static Task HandleBusinessExceptionAsync(HttpContext context, BusinessException ex)
    {
        context.Response.StatusCode = StatusCodes.Status422UnprocessableEntity;
        return context.Response.WriteAsJsonAsync(new
        {
            success = false,
            code = ex.ErrorCode,
            message = ex.Message
        });
    }
}

// 使用示例
public async Task<Order> GetOrderAsync(Guid orderId)
{
    var order = await _orderRepository.GetByIdAsync(orderId);
    if (order == null)
    {
        throw new BusinessException(404, "订单不存在");
    }
    return order;
}
```

## 2. Git工作流

### 2.1 分支管理

```
main            # 主分支，生产环境代码
├── develop     # 开发分支
│   ├── feature/order-management    # 功能分支
│   ├── feature/payment-integration # 功能分支
│   └── bugfix/order-calculation    # 修复分支
└── hotfix/critical-bug             # 紧急修复分支
```

### 2.2 分支命名规范

- **功能分支**：`feature/功能名称`（如：`feature/order-management`）
- **修复分支**：`bugfix/问题描述`（如：`bugfix/order-calculation`）
- **紧急修复**：`hotfix/问题描述`（如：`hotfix/payment-error`）
- **发布分支**：`release/版本号`（如：`release/v1.0.0`）

### 2.3 提交信息规范

```bash
# 格式：<type>(<scope>): <subject>

# type类型：
# feat: 新功能
# fix: 修复bug
# docs: 文档更新
# style: 代码格式调整
# refactor: 重构
# perf: 性能优化
# test: 测试相关
# chore: 构建/工具相关

# 示例
git commit -m "feat(order): 添加订单创建功能"
git commit -m "fix(payment): 修复支付回调处理错误"
git commit -m "docs(api): 更新API文档"
git commit -m "refactor(service): 重构订单服务"
```

### 2.4 工作流程

```bash
# 1. 从develop创建功能分支
git checkout develop
git pull origin develop
git checkout -b feature/order-management

# 2. 开发并提交
git add .
git commit -m "feat(order): 添加订单创建功能"

# 3. 推送到远程
git push origin feature/order-management

# 4. 创建Pull Request到develop分支

# 5. 代码审查通过后合并

# 6. 删除功能分支
git branch -d feature/order-management
git push origin --delete feature/order-management
```

## 3. 代码审查

### 3.1 审查清单

- [ ] 代码符合命名规范
- [ ] 代码逻辑清晰，易于理解
- [ ] 适当的注释和文档
- [ ] 异常处理完善
- [ ] 单元测试覆盖
- [ ] 性能考虑（N+1查询、大数据量处理）
- [ ] 安全性考虑（SQL注入、XSS、权限校验）
- [ ] 日志记录完善
- [ ] 无硬编码配置
- [ ] 符合SOLID原则

### 3.2 审查重点

```csharp
// ❌ 不好的实践
public class OrderService
{
    public Order CreateOrder(CreateOrderRequest request)
    {
        // 直接在服务层操作DbContext
        var order = new Order();
        _dbContext.Orders.Add(order);
        _dbContext.SaveChanges();

        // 硬编码配置
        var deliveryFee = 5.0m;

        // 没有异常处理
        // 没有日志记录

        return order;
    }
}

// ✅ 好的实践
public class OrderService : IOrderService
{
    private readonly IOrderRepository _orderRepository;
    private readonly IUnitOfWork _unitOfWork;
    private readonly ILogger<OrderService> _logger;
    private readonly IOptions<OrderSettings> _settings;

    public async Task<OrderDto> CreateOrderAsync(CreateOrderRequest request)
    {
        try
        {
            // 参数验证
            if (request == null)
                throw new ArgumentNullException(nameof(request));

            _logger.LogInformation("创建订单：{@Request}", request);

            // 业务逻辑
            var order = new Order
            {
                // ... 初始化订单
                DeliveryFee = _settings.Value.DefaultDeliveryFee
            };

            // 使用仓储
            await _orderRepository.AddAsync(order);
            await _unitOfWork.SaveChangesAsync();

            _logger.LogInformation("订单创建成功：{OrderId}", order.Id);

            return _mapper.Map<OrderDto>(order);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "创建订单失败：{@Request}", request);
            throw;
        }
    }
}
```



## 4. 单元测试规范

### 4.1 测试命名
- 命名格式：`MethodName_Scenario_ExpectedResult`
- 测试覆盖率要求：核心业务逻辑 >= 80%

### 4.2 测试示例

```csharp
[Fact]
public async Task CreateOrder_ValidRequest_ReturnsOrderDto()
{
    // Arrange
    var request = new CreateOrderRequest { /* ... */ };

    // Act
    var result = await _orderService.CreateOrderAsync(request);

    // Assert
    result.Should().NotBeNull();
    result.OrderNo.Should().NotBeNullOrEmpty();
}
```

## 5. 性能优化规范

### 5.1 数据库查询优化
- 避免N+1查询，使用Include预加载
- 大数据量查询使用Dapper
- 合理使用索引

### 5.2 缓存策略
- 商家信息：30分钟
- 菜品信息：15分钟
- 配置信息：1小时
- 用户会话：2小时

## 6. 文档要求

### 6.1 代码文档
- 所有公共API必须有XML文档注释
- 复杂业务逻辑添加详细注释
- README.md说明项目结构和运行方式

### 6.2 变更日志
维护CHANGELOG.md记录版本变更