# Hua.Todo 代码规范文档 v1.1.0 ## 1. 概述 本文档定义 Hua.Todo 项目的代码规范,包括 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> 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 Hua.Todo.Api.Services; // 3. XML 文档注释 /// /// 任务服务实现 /// public class TaskService : ITaskService { // 4. 私有字段 private readonly ITaskRepository _taskRepository; // 5. 构造函数 public TaskService(ITaskRepository taskRepository) { _taskRepository = taskRepository; } // 6. 公共方法 public async Task> GetTasksAsync() { // 实现 } // 7. 私有方法 private bool ValidateTask(Task task) { // 实现 } } ``` #### 命名空间组织 - 每个文件只包含一个命名空间 - 命名空间结构应与目录结构一致 - 使用 `.` 分隔层级 ### 3.3 编码规范 #### 异步编程 ```csharp // 异步方法应以 Async 结尾 public async Task GetTaskByIdAsync(int id) { return await _taskRepository.GetByIdAsync(id); } // 使用 await 而非 .Result 或 .Wait var task = await GetTaskByIdAsync(id); // 使用 ConfigureAwait(false) 在库代码中 public async Task> GetTasksAsync() { return await _taskRepository.GetAllAsync().ConfigureAwait(false); } ``` #### 依赖注入 ```csharp // 优先使用构造函数注入 public class TaskService : ITaskService { private readonly ITaskRepository _taskRepository; private readonly ILogger _logger; public TaskService(ITaskRepository taskRepository, ILogger logger) { _taskRepository = taskRepository; _logger = logger; } } ``` #### 异常处理 ```csharp // 使用具体的异常类型 public async 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 /// /// 获取指定 ID 的任务 /// /// 任务 ID /// 任务对象 /// 当任务不存在时抛出 public async 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 { 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 { const response = await axios.get('/api/task'); return response.data; } // 错误处理 try { const tasks = await getTasks(); } catch (error) { console.error('Failed to fetch tasks:', error); } ``` ## 5. Vue.js 代码规范 ### 5.1 组件命名 ```vue ``` ### 5.2 组件结构 ```vue ``` ### 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(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([]); const loading = ref(false); const error = ref(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/task'); 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 // 本项目的任务端点采用 Dynamic API 路由约定:/api/task(由中间件反射分发) [HttpGet("task")] public async Task>> GetTasks() { } // 使用资源 ID [HttpGet("task/{id}")] public async Task> GetTask(int id) { } // 使用 HTTP 方法表示操作 [HttpPost("task")] public async Task> CreateTask(CreateTaskDto dto) { } [HttpPut("task")] public async Task> UpdateTask(UpdateTaskDto dto) { } [HttpDelete("task/{id}")] public async Task DeleteTask(int id) { } ``` ### 6.2 响应格式 ```csharp // 统一的响应格式 public class ApiResponse { public bool Success { get; set; } public T Data { get; set; } public string Message { get; set; } public List Errors { get; set; } } // 成功响应 return Ok(new ApiResponse { Success = true, Data = task, Message = "Task created successfully" }); // 错误响应 return BadRequest(new ApiResponse { Success = false, Message = "Validation failed", Errors = new List { "Title is required" } }); ``` ## 7. Git 提交规范 ### 7.1 提交信息格式 ``` ():