$npx -y skills add virgo777/buddyme --skill coding-standards适用于 TypeScript、JavaScript、React 和 Node.js 开发的通用编码标准、最佳实践和模式。
| 1 | # 编码标准与最佳实践 (Coding Standards & Best Practices) |
| 2 | |
| 3 | 适用于所有项目的通用编码标准。 |
| 4 | |
| 5 | ## 何时启用 (When to Activate) |
| 6 | |
| 7 | - 启动新项目或模块时 |
| 8 | - 为了质量和可维护性进行代码审查(Code Review)时 |
| 9 | - 重构现有代码以遵循规范时 |
| 10 | - 强制执行命名、格式或结构的一致性时 |
| 11 | - 设置 linting、格式化或类型检查规则时 |
| 12 | - 引导新贡献者了解编码规范时 |
| 13 | |
| 14 | ## 代码质量原则 (Code Quality Principles) |
| 15 | |
| 16 | ### 1. 可读性优先 (Readability First) |
| 17 | - 代码被阅读的次数远多于编写的次数 |
| 18 | - 变量和函数命名应清晰明确 |
| 19 | - 优先选择自描述代码,而非依赖注释 |
| 20 | - 保持一致的格式化风格 |
| 21 | |
| 22 | ### 2. KISS 原则 (Keep It Simple, Stupid) |
| 23 | - 采用最简单的可行方案 |
| 24 | - 避免过度设计(Over-engineering) |
| 25 | - 不进行过早优化 |
| 26 | - 易于理解胜过奇技淫巧 |
| 27 | |
| 28 | ### 3. DRY 原则 (Don't Repeat Yourself) |
| 29 | - 将公共逻辑提取为函数 |
| 30 | - 创建可复用的组件 |
| 31 | - 在模块间共享工具函数 |
| 32 | - 避免“复制粘贴式”编程 |
| 33 | |
| 34 | ### 4. YAGNI 原则 (You Aren't Gonna Need It) |
| 35 | - 不要在功能被需要之前就构建它 |
| 36 | - 避免投机性的通用设计 |
| 37 | - 仅在必要时增加复杂性 |
| 38 | - 从简单开始,在需要时重构 |
| 39 | |
| 40 | ## TypeScript/JavaScript 规范 |
| 41 | |
| 42 | ### 变量命名 (Variable Naming) |
| 43 | |
| 44 | ```typescript |
| 45 | // ✅ 优:描述性命名 |
| 46 | const marketSearchQuery = 'election' |
| 47 | const isUserAuthenticated = true |
| 48 | const totalRevenue = 1000 |
| 49 | |
| 50 | // ❌ 劣:含义不明 |
| 51 | const q = 'election' |
| 52 | const flag = true |
| 53 | const x = 1000 |
| 54 | ``` |
| 55 | |
| 56 | ### 函数命名 (Function Naming) |
| 57 | |
| 58 | ```typescript |
| 59 | // ✅ 优:动词-名词模式 |
| 60 | async function fetchMarketData(marketId: string) { } |
| 61 | function calculateSimilarity(a: number[], b: number[]) { } |
| 62 | function isValidEmail(email: string): boolean { } |
| 63 | |
| 64 | // ❌ 劣:不清晰或仅有名词 |
| 65 | async function market(id: string) { } |
| 66 | function similarity(a, b) { } |
| 67 | function email(e) { } |
| 68 | ``` |
| 69 | |
| 70 | ### 不可变性模式(关键) (Immutability Pattern) |
| 71 | |
| 72 | ```typescript |
| 73 | // ✅ 始终使用展开运算符(Spread Operator) |
| 74 | const updatedUser = { |
| 75 | ...user, |
| 76 | name: 'New Name' |
| 77 | } |
| 78 | |
| 79 | const updatedArray = [...items, newItem] |
| 80 | |
| 81 | // ❌ 严禁直接修改(Mutate) |
| 82 | user.name = 'New Name' // 劣 |
| 83 | items.push(newItem) // 劣 |
| 84 | ``` |
| 85 | |
| 86 | ### 错误处理 (Error Handling) |
| 87 | |
| 88 | ```typescript |
| 89 | // ✅ 优:完善的错误处理 |
| 90 | async function fetchData(url: string) { |
| 91 | try { |
| 92 | const response = await fetch(url) |
| 93 | |
| 94 | if (!response.ok) { |
| 95 | throw new Error(`HTTP ${response.status}: ${response.statusText}`) |
| 96 | } |
| 97 | |
| 98 | return await response.json() |
| 99 | } catch (error) { |
| 100 | console.error('Fetch failed:', error) |
| 101 | throw new Error('Failed to fetch data') |
| 102 | } |
| 103 | } |
| 104 | |
| 105 | // ❌ 劣:没有错误处理 |
| 106 | async function fetchData(url) { |
| 107 | const response = await fetch(url) |
| 108 | return response.json() |
| 109 | } |
| 110 | ``` |
| 111 | |
| 112 | ### Async/Await 最佳实践 |
| 113 | |
| 114 | ```typescript |
| 115 | // ✅ 优:尽可能并行执行 |
| 116 | const [users, markets, stats] = await Promise.all([ |
| 117 | fetchUsers(), |
| 118 | fetchMarkets(), |
| 119 | fetchStats() |
| 120 | ]) |
| 121 | |
| 122 | // ❌ 劣:非必要的串行执行 |
| 123 | const users = await fetchUsers() |
| 124 | const markets = await fetchMarkets() |
| 125 | const stats = await fetchStats() |
| 126 | ``` |
| 127 | |
| 128 | ### 类型安全 (Type Safety) |
| 129 | |
| 130 | ```typescript |
| 131 | // ✅ 优:定义正确的类型 |
| 132 | interface Market { |
| 133 | id: string |
| 134 | name: string |
| 135 | status: 'active' | 'resolved' | 'closed' |
| 136 | created_at: Date |
| 137 | } |
| 138 | |
| 139 | function getMarket(id: string): Promise<Market> { |
| 140 | // 实现代码 |
| 141 | } |
| 142 | |
| 143 | // ❌ 劣:滥用 'any' |
| 144 | function getMarket(id: any): Promise<any> { |
| 145 | // 实现代码 |
| 146 | } |
| 147 | ``` |
| 148 | |
| 149 | ## React 最佳实践 |
| 150 | |
| 151 | ### 组件结构 (Component Structure) |
| 152 | |
| 153 | ```typescript |
| 154 | // ✅ 优:带类型的函数式组件 |
| 155 | interface ButtonProps { |
| 156 | children: React.ReactNode |
| 157 | onClick: () => void |
| 158 | disabled?: boolean |
| 159 | variant?: 'primary' | 'secondary' |
| 160 | } |
| 161 | |
| 162 | export function Button({ |
| 163 | children, |
| 164 | onClick, |
| 165 | disabled = false, |
| 166 | variant = 'primary' |
| 167 | }: ButtonProps) { |
| 168 | return ( |
| 169 | <button |
| 170 | onClick={onClick} |
| 171 | disabled={disabled} |
| 172 | className={`btn btn-${variant}`} |
| 173 | > |
| 174 | {children} |
| 175 | </button> |
| 176 | ) |
| 177 | } |
| 178 | |
| 179 | // ❌ 劣:无类型,结构不清晰 |
| 180 | export function Button(props) { |
| 181 | return <button onClick={props.onClick}>{props.children}</button> |
| 182 | } |
| 183 | ``` |
| 184 | |
| 185 | ### 自定义 Hook (Custom Hooks) |
| 186 | |
| 187 | ```typescript |
| 188 | // ✅ 优:可复用的自定义 Hook |
| 189 | export function useDebounce<T>(value: T, delay: number): T { |
| 190 | const [debouncedValue, setDebouncedValue] = useState<T>(value) |
| 191 | |
| 192 | useEffect(() => { |
| 193 | const handler = setTimeout(() => { |
| 194 | setDebouncedValue(value) |
| 195 | }, delay) |
| 196 | |
| 197 | return () => clearTimeout(handler) |
| 198 | }, [value, delay]) |
| 199 | |
| 200 | return debouncedValue |
| 201 | } |
| 202 | |
| 203 | // 使用示例 |
| 204 | const debouncedQuery = useDebounce(searchQuery, 500) |
| 205 | ``` |
| 206 | |
| 207 | ### 状态管理 (State Management) |
| 208 | |
| 209 | ```typescript |
| 210 | // ✅ 优:正确更新状态 |
| 211 | const [count, setCount] = useState(0) |
| 212 | |
| 213 | // 基于先前状态的函数式更新 |
| 214 | setCount(prev => prev + 1) |
| 215 | |
| 216 | // ❌ 劣:直接引用状态 |
| 217 | setCount(count + 1) // 在异步场景下可能会由于闭包导致状态过期 |
| 218 | ``` |
| 219 | |
| 220 | ### 条件渲染 (Conditional Rendering) |
| 221 | |
| 222 | ```typescript |
| 223 | // ✅ 优:清晰的条件渲染 |
| 224 | {isLoading && <Spinner />} |
| 225 | {error && <ErrorMessage error={error} />} |
| 226 | {data && <DataDisplay data={data} />} |
| 227 | |
| 228 | // ❌ 劣:三元运算符嵌套地狱 |
| 229 | {isLoading ? <Spinner /> : error ? <ErrorMessage error={error} /> : data ? <DataDisplay data={data} /> : null} |
| 230 | ``` |
| 231 | |
| 232 | ## API 设计规范 (API Design Standards) |
| 233 | |
| 234 | ### REST API 约定 (REST API Conventions) |
| 235 | |
| 236 | ``` |
| 237 | GET /api/markets # 列出所有市场 |
| 238 | GET /api/markets/:id # 获取特定市场 |
| 239 | POST /api/markets # 创建新市场 |
| 240 | PUT /api/markets/:id # 更新市场(完整更新) |
| 241 | PATCH /api/markets/:id # 更新市场(局部更新) |
| 242 | DELETE /api/markets/:id # 删除市场 |
| 243 | |
| 244 | # 用于过滤的查询参数 |
| 245 | GET /api/markets?status=active&limit=10&offset=0 |
| 246 | ``` |
| 247 | |
| 248 | ### 响应格式 (Response Format) |
| 249 | |
| 250 | ```typescript |
| 251 | // ✅ 优:一致的响应结构 |
| 252 | interface ApiResponse<T> { |
| 253 | success: boolean |
| 254 | data?: T |
| 255 | error?: string |
| 256 | meta?: { |
| 257 | total: number |
| 258 | page: number |
| 259 | limit: number |
| 260 | } |
| 261 | } |
| 262 | |
| 263 | // 成功响应 |
| 264 | return NextResponse.json({ |
| 265 | success: true, |
| 266 | data: markets, |
| 267 | meta: { total: 100, page: 1, limit: 10 } |
| 268 | }) |
| 269 | |
| 270 | // 错误响应 |
| 271 | return Ne |