fischerX/docs/development/coding-standards.md

12 KiB
Raw Permalink Blame History

开发规范

> 文档版本: v1.0.0 > 创建日期: 2026-05-25 > 适用范围: FischerX 项目开发人员

目录


代码规范

TypeScript 规范

类型定义

  • 使用 type 定义对象类型,使用 interface 定义类接口或需要扩展的类型
  • 始终使用严格的类型检查,避免使用 any
  • 优先使用联合类型和字面量类型
// 好的做法
type User = {
  id: string;
  name: string;
  email: string;
  role: 'admin' | 'user' | 'guest';
};

interface Repository {
  findById(id: string): Promise<User | null>;
  save(user: User): Promise<User>;
}

// 避免
type User = any;

命名规范

  • 类型名使用 PascalCase
  • 常量使用 UPPER_SNAKE_CASE
  • 变量和函数使用 camelCase
  • 类使用 PascalCase
  • React 组件使用 PascalCase
// 类型
type UserProfile = { ... };

// 常量
const MAX_RETRY_COUNT = 3;
const API_BASE_URL = 'https://api.example.com';

// 变量和函数
const userName = 'John';
function calculateTotal(price: number, quantity: number): number { ... }

// 类
class UserService { ... }

// React 组件
function UserProfileCard() { ... }

文件组织

  • 一个文件一个主要导出
  • 使用 index.ts 作为模块入口
  • 按功能组织文件,而不是按类型
// 好的做法
user/
├── index.ts
├── types.ts
├── service.ts
├── repository.ts
└── hooks.ts

React/Next.js 规范

组件设计

  • 使用函数组件,避免类组件
  • 组件文件使用 .tsx 扩展名
  • 组件名与文件名保持一致
// components/UserCard.tsx
interface UserCardProps {
  user: User;
  onEdit?: (user: User) => void;
}

export function UserCard({ user, onEdit }: UserCardProps) {
  return (
    <div className="user-card">
      <h3>{user.name}</h3>
      <p>{user.email}</p>
      {onEdit && <button onClick={() => onEdit(user)}>Edit</button>}
    </div>
  );
}

Hooks 规范

  • 自定义 Hook 以 use 开头
  • Hook 应该只负责单一职责
  • 使用 React Query 进行数据获取
  • 使用 Zustand 进行状态管理
// hooks/useUser.ts
import { useQuery } from '@tanstack/react-query';
import { userApi } from '@/lib/api';

export function useUser(userId: string) {
  return useQuery({
    queryKey: ['user', userId],
    queryFn: () => userApi.getById(userId),
    enabled: !!userId,
  });
}

表单处理

  • 使用 React Hook Form
  • 使用 Zod 进行验证
  • 显示友好的错误信息
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import * as z from 'zod';

const formSchema = z.object({
  name: z.string().min(2, 'Name too short'),
  email: z.string().email('Invalid email'),
});

type FormValues = z.infer<typeof formSchema>;

function UserForm() {
  const form = useForm<FormValues>({
    resolver: zodResolver(formSchema),
  });

  const onSubmit = (data: FormValues) => {
    console.log(data);
  };

  return <form onSubmit={form.handleSubmit(onSubmit)}>{/* ... */}</form>;
}

样式规范

  • 使用 Tailwind CSS
  • 组件内部样式放在 className
  • 复杂样式使用 clsxtailwind-merge
import { clsx } from 'clsx';
import { twMerge } from 'tailwind-merge';

function cn(...inputs: any[]) {
  return twMerge(clsx(inputs));
}

function Button({
  children,
  variant = 'primary',
  className,
}: {
  children: React.ReactNode;
  variant?: 'primary' | 'secondary' | 'danger';
  className?: string;
}) {
  const variants = {
    primary: 'bg-blue-600 text-white hover:bg-blue-700',
    secondary: 'bg-gray-200 text-gray-800 hover:bg-gray-300',
    danger: 'bg-red-600 text-white hover:bg-red-700',
  };

  return (
    <button
      className={cn(
        'px-4 py-2 rounded font-medium transition-colors',
        variants[variant],
        className
      )}
    >
      {children}
    </button>
  );
}

NestJS 规范

模块结构

  • 按功能组织模块
  • 每个模块包含 Controller、Service、Module
  • 使用 Prisma 作为数据访问层
user/
├── user.module.ts
├── user.controller.ts
├── user.service.ts
├── dto/
│   ├── create-user.dto.ts
│   └── update-user.dto.ts
└── entities/
    └── user.entity.ts

控制器规范

  • Controller 只负责请求/响应处理
  • 业务逻辑委托给 Service
  • 使用 DTO 进行验证
  • 使用 Swagger 装饰器生成文档
import { Controller, Get, Post, Body, Param, UseGuards } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger';
import { UserService } from './user.service';
import { CreateUserDto } from './dto/create-user.dto';
import { JwtAuthGuard } from '../auth/jwt-auth.guard';

@ApiTags('users')
@Controller('users')
export class UserController {
  constructor(private readonly userService: UserService) {}

  @Post()
  @ApiOperation({ summary: 'Create user' })
  @ApiResponse({ status: 201, description: 'User created' })
  create(@Body() createUserDto: CreateUserDto) {
    return this.userService.create(createUserDto);
  }

  @Get(':id')
  @UseGuards(JwtAuthGuard)
  @ApiOperation({ summary: 'Get user by ID' })
  findOne(@Param('id') id: string) {
    return this.userService.findOne(id);
  }
}

服务规范

  • Service 包含业务逻辑
  • 使用依赖注入
  • 抛出业务异常
import { Injectable, NotFoundException } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { CreateUserDto } from './dto/create-user.dto';
import * as bcrypt from 'bcrypt';

@Injectable()
export class UserService {
  constructor(private prisma: PrismaService) {}

  async create(createUserDto: CreateUserDto) {
    const hashedPassword = await bcrypt.hash(createUserDto.password, 10);

    return this.prisma.user.create({
      data: {
        ...createUserDto,
        password: hashedPassword,
      },
    });
  }

  async findOne(id: string) {
    const user = await this.prisma.user.findUnique({ where: { id } });
    if (!user) {
      throw new NotFoundException(`User with ID ${id} not found`);
    }
    return user;
  }
}

DTO 规范

  • 使用 class-validator 进行验证
  • 使用 class-transformer 进行转换
  • DTO 放在 dto 目录下
import { IsEmail, IsString, MinLength } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';

export class CreateUserDto {
  @ApiProperty()
  @IsString()
  @MinLength(2)
  name: string;

  @ApiProperty()
  @IsEmail()
  email: string;

  @ApiProperty()
  @IsString()
  @MinLength(8)
  password: string;
}

Git 规范

分支策略

我们使用 Git Flow 工作流:

main (生产环境)
  └── develop (开发环境)
        ├── feature/feature-name (功能分支)
        ├── bugfix/bug-name (修复分支)
        ├── hotfix/hotfix-name (紧急修复)
        └── release/release-x.y.z (发布分支)

分支说明

分支类型 命名规范 说明
main main 生产环境代码,始终稳定
develop develop 开发环境代码,集成新功能
feature feature/xxx-yyy 新功能开发
bugfix bugfix/xxx-yyy Bug 修复
hotfix hotfix/xxx-yyy 生产环境紧急修复
release release/x.y.z 发布准备

创建分支

# 从 develop 创建功能分支
git checkout develop
git pull origin develop
git checkout -b feature/user-authentication

# 从 main 创建紧急修复分支
git checkout main
git pull origin main
git checkout -b hotfix/critical-login-bug

提交规范

我们使用 Conventional Commits 规范:

<type>(<scope>): <subject>

<body>

<footer>

Type 类型

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

Scope 范围

  • web: Web 应用
  • admin: 管理后台
  • api: API 服务
  • ui: UI 组件库
  • core: 核心业务包
  • types: 类型定义
  • utils: 工具函数
  • config: 配置

提交示例

# 新功能
git commit -m "feat(web): add user login page"

# Bug 修复
git commit -m "fix(api): handle null user in authentication"

# 文档更新
git commit -m "docs: update quick start guide"

# 重构
git commit -m "refactor(ui): restructure button component"

# 带正文的提交
git commit -m "feat(web): add password reset

- Add password reset form
- Add email verification
- Update API client

Closes #123"

PR 规范

PR 流程

  1. 创建分支并开发
  2. 提交代码
  3. 推送分支到远程
  4. 创建 Pull Request
  5. CI 检查
  6. 代码审查
  7. 修改(如果需要)
  8. 合并

PR 模板

## 描述
简要描述这个 PR 的改动。

## 类型
- [ ] feat (新功能)
- [ ] fix (Bug 修复)
- [ ] docs (文档更新)
- [ ] style (代码格式)
- [ ] refactor (重构)
- [ ] perf (性能优化)
- [ ] test (测试)
- [ ] chore (构建/工具)

## 改动范围
- [ ] apps/web
- [ ] apps/admin
- [ ] services/api
- [ ] packages/ui
- [ ] packages/core
- [ ] packages/types
- [ ] packages/utils
- [ ] 其他: ___

## 测试
- [ ] 单元测试已添加/更新
- [ ] 集成测试已添加/更新
- [ ] E2E 测试已添加/更新
- [ ] 手动测试已完成

## 截图(如果适用)
添加 UI 变化的截图。

## 相关 Issue
Closes #123, #456

## 检查清单
- [ ] 代码符合项目规范
- [ ] 已添加必要的测试
- [ ] 文档已更新
- [ ] CI 检查通过

代码审查清单

审查者应该检查以下内容:

功能正确性

  • 代码实现了预期功能
  • 边界情况已处理
  • 错误处理正确

代码质量

  • 代码清晰易读
  • 命名有意义
  • 没有重复代码
  • 复杂度适中

性能

  • 没有明显的性能问题
  • 数据库查询优化
  • 缓存使用合理

安全

  • 输入已验证
  • 没有 SQL 注入风险
  • 敏感数据已保护
  • 权限控制正确

测试

  • 测试覆盖充分
  • 测试可以通过
  • 测试有意义

文档

  • 代码注释充分
  • API 文档已更新
  • 使用文档已更新

合并策略

  • Squash Merge: 功能分支合并到 develop保持提交历史整洁
  • Rebase Merge: 保持线性历史
  • Merge Commit: 保留完整提交历史(用于 main 分支)
# Squash 合并示例
git checkout develop
git merge --squash feature/user-authentication
git commit -m "feat(web): add user authentication"

最佳实践提示

开发工作流

  1. 开始工作前

    git checkout develop
    git pull origin develop
    
  2. 创建分支

    git checkout -b feature/your-feature-name
    
  3. 定期提交

    git add .
    git commit -m "feat: your commit message"
    
  4. 推送到远程

    git push -u origin feature/your-feature-name
    
  5. 创建 PR

    • 在 GitHub/GitLab 上创建 PR
    • 填写 PR 模板
    • 请求审查
  6. 更新分支

    git checkout develop
    git pull origin develop
    git checkout feature/your-feature-name
    git rebase develop
    

避免常见错误

  • 不要直接提交到 main 或 develop
  • 不要提交大文件(使用 Git LFS
  • 不要提交敏感信息API 密钥、密码等)
  • 不要忽略测试失败
  • 保持提交小而专注
  • 写有意义的提交信息
  • 及时更新文档

下一步


> 文档维护: 本文档由开发团队维护,如有问题或建议请提交 Issue。 > 最后更新: 2026-05-25