fengling-platform/.planning/codebase/CONVENTIONS.md
movingsam 1b8c937aa4
Some checks failed
Build and Push Docker / build (push) Failing after 23s
Publish NuGet Packages / build (push) Failing after 8s
feat: 添加 Gateway 路由实体到 Platform
- 新增 GatewayAggregate 领域实体 (GwTenant, GwTenantRoute, GwServiceInstance)
- 新增 IRouteStore, RouteStore, IInstanceStore, InstanceStore
- 新增 IRouteManager, RouteManager
- 合并 GatewayDbContext 到 PlatformDbContext
- 统一 Extensions.AddPlatformCore 注册所有服务
2026-02-28 23:53:00 +08:00

6.4 KiB
Raw Blame History

代码约定

分析日期: 2026-02-28

命名模式

文件

  • 类/记录: PascalCaseApplicationUser.csTenantManager.csTenantInfo.cs
  • 枚举: PascalCaseTenantStatus,定义在 Tenant.cs 中)
  • 接口: PascalCase + "I" 前缀(如 ITenantStore.csITenantManager.cs
  • 配置: PascalCase + "Configuration" 后缀(如 TenantConfiguration.cs

目录

  • 聚合文件夹: PascalCaseUserAggregate/TenantAggregate/RoleAggregate/
  • 用途文件夹: PascalCaseConfigurations/Migrations/

命名空间

  • 模式: Fengling.Platform.{层级}.{聚合}.{组件}
  • 示例:
    • Fengling.Platform.Domain.AggregatesModel.TenantAggregate
    • Fengling.Platform.Domain.AggregatesModel.UserAggregate
    • Fengling.Platform.Infrastructure

类型

类型 模式 示例
PascalCase TenantManager, PlatformDbContext
接口 I + PascalCase ITenantManager, ITenantStore
记录 PascalCase TenantInfo
枚举 PascalCase TenantStatus
枚举值 PascalCase Active, Inactive, Frozen
属性 PascalCase TenantCode, CreatedAt, IsDeleted
方法 PascalCase FindByIdAsync, GetAllAsync
参数 camelCase tenantId, tenantCode, cancellationToken
私有字段 camelCase _context, _tenants

代码风格

项目配置

  • 目标框架: .NET 10.0
  • 隐式 using: 启用
  • 可空: 启用
  • 文档生成: 启用(<GenerateDocumentationFile>true</GenerateDocumentationFile>
  • 集中包管理: 启用(<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>

格式化

  • 大括号: K&R 风格(开括号在同一行)
  • 缩进: 标准 Visual Studio 默认4 空格)
  • 行尾: 平台默认Unix LFWindows CRLF

全局 Using

Domain 项目 (Fengling.Platform.Domain/GlobalUsings.cs):

global using NetCorePal.Extensions.Domain;
global using NetCorePal.Extensions.Primitives;
global using System.ComponentModel.DataAnnotations;

Infrastructure 项目 (Fengling.Platform.Infrastructure/GlobalUsings.cs):

global using NetCorePal.Extensions.Domain;
global using NetCorePal.Extensions.Primitives;
global using NetCorePal.Extensions.Repository;
global using NetCorePal.Extensions.Repository.EntityFrameworkCore;
global using MediatR;
global using Microsoft.EntityFrameworkCore;
global using Microsoft.EntityFrameworkCore.Metadata.Builders;

导入组织

顺序

  1. 系统命名空间(通过 ImplicitUsings 隐式)
  2. 外部包MediatR、EF Core
  3. 领域命名空间(本地项目)
  4. 基础设施命名空间(本地项目)

完全限定

  • 需要时使用 Microsoft.AspNetCore.Identity 的完全限定(如 ITenantStore.cs 中的 Microsoft.AspNetCore.Identity.IdentityResult

错误处理

空检查

模式: 显式参数空检查并抛出异常

if (modelBuilder is null)
{
    throw new ArgumentNullException(nameof(modelBuilder));
}
  • 位置: PlatformDbContext.cs 第 20-23 行

空返回

模式: 对可空结果返回 Task.FromResult<T?>(null)

if (tenantId == null) return Task.FromResult<Tenant?>(null);
  • 位置: TenantStore.cs 第 23 行

验证

  • 查询中使用 string.IsNullOrEmpty() 进行字符串验证
  • 对引用类型使用可空注解 ? 后缀

记录类型

值对象

模式: 带参数的主构造函数记录

public record TenantInfo(long? TenantId, string? TenantCode, string? TenantName)
{
    public TenantInfo(Tenant? tenant)
        : this(tenant?.Id, tenant?.TenantCode, tenant?.Name)
    {
    }
    
    public static TenantInfo Admin => new TenantInfo(null, null, null);
}
  • 位置: TenantInfo.cs

实体设计

贫血领域模型

  • Tenant: 贫血模型(带公共 setter 的数据容器)
  • ApplicationUser: 富模型,带到 TenantInfo 的导航属性
  • ID 类型: 所有实体标识使用 long

属性模式

public long Id { get; set; }
public string TenantCode { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public DateTime? UpdatedAt { get; set; }
public bool IsDeleted { get; set; }

类设计

主构造函数

模式: 用于依赖注入的主构造函数

public sealed class TenantManager(ITenantStore store) : ITenantManager
{
    // 构造函数参数自动成为私有 readonly 字段
}
  • 位置: TenantManager.cs 第 21 行

泛型约束

public class TenantStore<TContext> : ITenantStore
where TContext : PlatformDbContext

方法返回类型

  • 异步方法: 返回 Task<T>Task
  • 集合查询: 返回 IList<T>IQueryable<T>
  • 单个实体: 返回 T?

注释

何时注释

  • 中文注释: 用于领域概念和解释
    /// <summary>
    /// 租户信息
    /// </summary>
    public record TenantInfo(...)
    
  • XML 文档: 用于公共 API
  • 最少行内注释: 仅用于复杂业务逻辑

JSDoc/TSDoc

  • 对公共 API 使用 /// <summary>/// <param name="...">
  • 位置: TenantInfo.cs 第 3-8 行、11-13 行

函数设计

异步方法

  • 始终接受 CancellationToken cancellationToken = default 作为最后一个参数
  • 一致使用 async/await
  • 对有返回值操作返回 Task<T>

查询方法

  • 分页: 接受 pagepageSize 参数
  • 过滤: 接受可选过滤参数(nametenantCodestatus
  • 排序: 按创建日期应用 OrderByDescending

IdentityResult 模式

业务操作返回 IdentityResult:

Task<IdentityResult> CreateAsync(Tenant tenant, CancellationToken cancellationToken = default);
Task<IdentityResult> UpdateAsync(Tenant tenant, CancellationToken cancellationToken = default);
Task<IdentityResult> DeleteAsync(Tenant tenant, CancellationToken cancellationToken = default);

DbContext 设计

配置

  • 模式: OnModelCreating 中的流式 API
  • 实体配置: 使用 modelBuilder.Entity<T>(entity => {...})
  • 索引配置: 使用 entity.HasIndex(e => e.Property)
  • 拥有类型: 使用 entity.OwnsOne(e => e.TenantInfo, navigationBuilder => {...})

配置发现

modelBuilder.ApplyConfigurationsFromAssembly(typeof(PlatformDbContext).Assembly);

约定分析: 2026-02-28