# TodoList 代码规范文档 v1.1.0

## 1. 概述
本文档定义 TodoList 项目的代码规范，包括 C#、JavaScript/TypeScript、Vue.js 和其他相关技术的编码标准。遵循这些规范有助于提高代码质量、可读性和可维护性。

## 2. 通用规范

### 2.1 命名约定
- **使用有意义的名称**: 变量、函数、类名应清晰表达其用途
- **避免缩写**: 除非是广泛认知的缩写（如 ID、URL、API）
- **一致性**: 在整个项目中保持命名风格一致

### 2.2 注释规范
- **公共 API 必须添加 XML 文档注释**
- **复杂逻辑添加行内注释**
- **避免注释显而易见的代码**
- **保持注释与代码同步更新**

### 2.3 代码格式化
- **使用统一的代码格式化工具**
- **保持一致的缩进和空格**
- **每行代码不超过 120 字符**
- **文件末尾保留一个空行**

## 3. C# 代码规范

### 3.1 命名规范

#### 类和接口
```csharp
// 类名使用 PascalCase
public class TaskService
{
}

// 接口名使用 PascalCase，以 I 开头
public interface ITaskService
{
}
```

#### 方法和属性
```csharp
// 方法名使用 PascalCase
public Task<List<Task>> GetTasksAsync()
{
}

// 属性名使用 PascalCase
public string Title { get; set; }
```

#### 变量和参数
```csharp
// 私有字段使用 _camelCase
private readonly ITaskRepository _taskRepository;

// 局部变量使用 camelCase
var taskList = await GetTasksAsync();

// 方法参数使用 camelCase
public void CreateTask(string title, TaskPriority priority)
{
}
```

#### 常量
```csharp
// 常量使用 PascalCase
public const int MaxTaskTitleLength = 200;
```

### 3.2 代码组织

#### 文件结构
```csharp
// 1. using 语句（按字母顺序）
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

// 2. 命名空间
namespace TodoList.Api.Services;

// 3. XML 文档注释
/// <summary>
/// 任务服务实现
/// </summary>
public class TaskService : ITaskService
{
    // 4. 私有字段
    private readonly ITaskRepository _taskRepository;

    // 5. 构造函数
    public TaskService(ITaskRepository taskRepository)
    {
        _taskRepository = taskRepository;
    }

    // 6. 公共方法
    public async Task<List<Task>> GetTasksAsync()
    {
        // 实现
    }

    // 7. 私有方法
    private bool ValidateTask(Task task)
    {
        // 实现
    }
}
```

#### 命名空间组织
- 每个文件只包含一个命名空间
- 命名空间结构应与目录结构一致
- 使用 `.` 分隔层级

### 3.3 编码规范

#### 异步编程
```csharp
// 异步方法应以 Async 结尾
public async Task<Task> GetTaskByIdAsync(int id)
{
    return await _taskRepository.GetByIdAsync(id);
}

// 使用 await 而非 .Result 或 .Wait
var task = await GetTaskByIdAsync(id);

// 使用 ConfigureAwait(false) 在库代码中
public async Task<List<Task>> GetTasksAsync()
{
    return await _taskRepository.GetAllAsync().ConfigureAwait(false);
}
```

#### 依赖注入
```csharp
// 优先使用构造函数注入
public class TaskService : ITaskService
{
    private readonly ITaskRepository _taskRepository;
    private readonly ILogger<TaskService> _logger;

    public TaskService(ITaskRepository taskRepository, ILogger<TaskService> logger)
    {
        _taskRepository = taskRepository;
        _logger = logger;
    }
}
```

#### 异常处理
```csharp
// 使用具体的异常类型
public async Task<Task> GetTaskByIdAsync(int id)
{
    var task = await _taskRepository.GetByIdAsync(id);
    
    if (task == null)
    {
        throw new NotFoundException($"Task with id {id} not found");
    }
    
    return task;
}

// 使用 using 语句管理资源
using var context = new TodoDbContext();
```

#### LINQ 使用
```csharp
// 优先使用方法语法
var completedTasks = tasks.Where(t => t.IsCompleted).ToList();

// 复杂查询使用查询语法
var query = from task in tasks
            where task.IsCompleted
            orderby task.CreatedAt descending
            select task;
```

### 3.4 文档注释
```csharp
/// <summary>
/// 获取指定 ID 的任务
/// </summary>
/// <param name="id">任务 ID</param>
/// <returns>任务对象</returns>
/// <exception cref="NotFoundException">当任务不存在时抛出</exception>
public async Task<Task> GetTaskByIdAsync(int id)
{
    // 实现
}
```

## 4. JavaScript/TypeScript 代码规范

### 4.1 命名规范

#### 变量和函数
```typescript
// 变量使用 camelCase
const taskList = [];
let currentTask = null;

// 函数使用 camelCase
function getTasks() {
  // 实现
}

// 常量使用 UPPER_SNAKE_CASE
const MAX_TASK_TITLE_LENGTH = 200;
```

#### 类和接口
```typescript
// 类名使用 PascalCase
class TaskService {
  // 实现
}

// 接口名使用 PascalCase
interface Task {
  id: number;
  title: string;
}

// 类型别名使用 PascalCase
type TaskPriority = 'high' | 'medium' | 'low';
```

### 4.2 代码组织

#### 文件结构
```typescript
// 1. 导入语句
import { ref, computed } from 'vue';
import { useTaskStore } from '@/stores/tasks';
import type { Task } from '@/types/task';

// 2. 类型定义
interface TaskForm {
  title: string;
  priority: TaskPriority;
}

// 3. 常量定义
const DEFAULT_PRIORITY: TaskPriority = 'medium';

// 4. 组合式函数或组件
export function useTasks() {
  // 实现
}
```

#### 模块导入
```typescript
// 优先使用 ES6 模块语法
import { ref } from 'vue';
import axios from 'axios';

// 导出使用具名导出
export function useTasks() {
  // 实现
}

export default useTasks;
```

### 4.3 TypeScript 规范

#### 类型定义
```typescript
// 为所有函数参数和返回值添加类型
function getTaskById(id: number): Task | null {
  // 实现
}

// 使用接口定义对象类型
interface Task {
  id: number;
  title: string;
  priority: TaskPriority;
  isCompleted: boolean;
  createdAt: Date;
}

// 使用类型别名定义联合类型
type TaskPriority = 'high' | 'medium' | 'low';

// 使用泛型提高代码复用性
interface ApiResponse<T> {
  data: T;
  message: string;
}
```

#### 类型断言
```typescript
// 优先使用类型守卫而非类型断言
function isTask(obj: unknown): obj is Task {
  return typeof obj === 'object' && obj !== null && 'id' in obj;
}

// 避免使用 as any
const task = response.data as Task; // 避免
```

### 4.4 异步编程
```typescript
// 使用 async/await 而非 Promise 链
async function getTasks(): Promise<Task[]> {
  const response = await axios.get('/api/tasks');
  return response.data;
}

// 错误处理
try {
  const tasks = await getTasks();
} catch (error) {
  console.error('Failed to fetch tasks:', error);
}
```

## 5. Vue.js 代码规范

### 5.1 组件命名
```vue
<!-- 组件名使用 PascalCase -->
<script setup lang="ts">
// 组件名应与文件名一致
</script>

<template>
  <!-- 模板中使用 kebab-case -->
  <task-item :task="task" />
</template>
```

### 5.2 组件结构
```vue
<template>
  <!-- 1. 模板 -->
  <div class="task-list">
    <task-item
      v-for="task in tasks"
      :key="task.id"
      :task="task"
    />
  </div>
</template>

<script setup lang="ts">
// 2. 导入
import { ref, computed } from 'vue';
import { useTaskStore } from '@/stores/tasks';
import TaskItem from './TaskItem.vue';

// 3. Props 定义
interface Props {
  filter: 'all' | 'active' | 'completed';
}

const props = withDefaults(defineProps<Props>(), {
  filter: 'all'
});

// 4. Emits 定义
const emit = defineEmits<{
  (e: 'task-created', task: Task): void;
}>();

// 5. 响应式状态
const taskStore = useTaskStore();
const tasks = computed(() => taskStore.filteredTasks(props.filter));

// 6. 方法
const handleCreateTask = async (title: string) => {
  const task = await taskStore.createTask(title);
  emit('task-created', task);
};
</script>

<style scoped>
/* 6. 样式 */
.task-list {
  padding: 16px;
}
</style>
```

### 5.3 组合式函数规范
```typescript
// composables/useTasks.ts
import { ref, computed } from 'vue';
import { useTaskStore } from '@/stores/tasks';

export function useTasks() {
  const taskStore = useTaskStore();
  const loading = ref(false);
  const error = ref<string | null>(null);

  const tasks = computed(() => taskStore.tasks);
  const completedTasks = computed(() => taskStore.completedTasks);

  const fetchTasks = async () => {
    loading.value = true;
    error.value = null;
    
    try {
      await taskStore.fetchTasks();
    } catch (err) {
      error.value = 'Failed to fetch tasks';
      console.error(err);
    } finally {
      loading.value = false;
    }
  };

  return {
    tasks,
    completedTasks,
    loading,
    error,
    fetchTasks
  };
}
```

### 5.4 状态管理规范
```typescript
// stores/tasks.ts
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
import type { Task } from '@/types/task';

export const useTaskStore = defineStore('tasks', () => {
  // State
  const tasks = ref<Task[]>([]);
  const loading = ref(false);
  const error = ref<string | null>(null);

  // Getters
  const activeTasks = computed(() => 
    tasks.value.filter(task => !task.isCompleted)
  );

  const completedTasks = computed(() => 
    tasks.value.filter(task => task.isCompleted)
  );

  // Actions
  async function fetchTasks() {
    loading.value = true;
    try {
      const response = await fetch('/api/tasks');
      tasks.value = await response.json();
    } catch (err) {
      error.value = 'Failed to fetch tasks';
    } finally {
      loading.value = false;
    }
  }

  return {
    tasks,
    loading,
    error,
    activeTasks,
    completedTasks,
    fetchTasks
  };
});
```

## 6. API 设计规范

### 6.1 RESTful API 设计
```csharp
// 使用名词复数形式
[HttpGet("tasks")]
public async Task<ActionResult<List<Task>>> GetTasks()
{
}

// 使用资源 ID
[HttpGet("tasks/{id}")]
public async Task<ActionResult<Task>> GetTask(int id)
{
}

// 使用 HTTP 方法表示操作
[HttpPost("tasks")]
public async Task<ActionResult<Task>> CreateTask(CreateTaskDto dto)
{
}

[HttpPut("tasks/{id}")]
public async Task<ActionResult<Task>> UpdateTask(int id, UpdateTaskDto dto)
{
}

[HttpDelete("tasks/{id}")]
public async Task<ActionResult> DeleteTask(int id)
{
}
```

### 6.2 响应格式
```csharp
// 统一的响应格式
public class ApiResponse<T>
{
    public bool Success { get; set; }
    public T Data { get; set; }
    public string Message { get; set; }
    public List<string> Errors { get; set; }
}

// 成功响应
return Ok(new ApiResponse<Task>
{
    Success = true,
    Data = task,
    Message = "Task created successfully"
});

// 错误响应
return BadRequest(new ApiResponse<object>
{
    Success = false,
    Message = "Validation failed",
    Errors = new List<string> { "Title is required" }
});
```

## 7. Git 提交规范

### 7.1 提交信息格式
```
<type>(<scope>): <subject>

<body>

<footer>
```

### 7.2 Type 类型
- `feat`: 新功能
- `fix`: 修复 bug
- `docs`: 文档更新
- `style`: 代码格式调整（不影响代码运行）
- `refactor`: 重构（既不是新功能也不是修复 bug）
- `perf`: 性能优化
- `test`: 测试相关
- `chore`: 构建过程或辅助工具的变动

### 7.3 示例
```
feat(api): add task completion endpoint

- Add PATCH /api/tasks/{id}/complete endpoint
- Update task service to handle completion logic
- Add unit tests for completion functionality

Closes #123
```

## 8. 测试规范

### 8.1 单元测试
```csharp
// 测试类命名: ClassName + Tests
public class TaskServiceTests
{
    [Fact]
    public async Task GetTasksAsync_ReturnsAllTasks()
    {
        // Arrange
        var mockRepository = new Mock<ITaskRepository>();
        var service = new TaskService(mockRepository.Object);
        
        // Act
        var result = await service.GetTasksAsync();
        
        // Assert
        Assert.NotNull(result);
        Assert.Equal(3, result.Count);
    }
}
```

### 8.2 集成测试
```csharp
public class ApiIntegrationTests : IClassFixture<WebApplicationFactory<Program>>
{
    private readonly HttpClient _client;

    public ApiIntegrationTests(WebApplicationFactory<Program> factory)
    {
        _client = factory.CreateClient();
    }

    [Fact]
    public async Task GetTasks_ReturnsSuccessAndCorrectContentType()
    {
        // Act
        var response = await _client.GetAsync("/api/tasks");

        // Assert
        response.EnsureSuccessStatusCode();
        Assert.Equal("application/json", response.Content.Headers.ContentType?.MediaType);
    }
}
```

## 9. 代码审查清单

### 9.1 代码质量
- [ ] 代码符合项目规范
- [ ] 变量和函数命名清晰
- [ ] 没有重复代码
- [ ] 复杂逻辑有注释说明
- [ ] 没有硬编码的魔法数字

### 9.2 功能正确性
- [ ] 功能实现符合需求
- [ ] 边界条件已处理
- [ ] 错误处理完善
- [ ] 有相应的单元测试

### 9.3 性能和安全
- [ ] 没有性能问题
- [ ] 敏感数据已保护
- [ ] 输入验证完善
- [ ] 没有安全漏洞

## 10. 工具配置

### 10.1 C# 工具
- **代码格式化**: dotnet format
- **代码分析**: Roslyn Analyzers
- **代码风格**: .editorconfig
- **文档生成**: DocFX

### 10.2 JavaScript/TypeScript 工具
- **代码格式化**: Prettier
- **代码检查**: ESLint
- **类型检查**: TypeScript
- **代码风格**: .prettierrc

### 10.3 .editorconfig 示例
```ini
root = true

[*.cs]
indent_style = space
indent_size = 4
end_of_line = crlf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.{js,ts,vue}]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
```
