Communitygithub.com

程式碼撰寫規範與最佳實務

跨專案共通的程式碼撰寫慣例,涵蓋命名、可讀性、不變性與程式碼品質審查。當無特定框架技能可套用時,用於審查程式碼品質或命名。

程式碼撰寫規範與最佳實務 是什麼?

此技能「coding-standards」定義了一套跨專案共通的程式碼撰寫慣例,作為所有開發工作的基礎標準。它專注於描述性命名、預設不變性、可讀性優先、以及 KISS、DRY、YAGNI 等原則的強制執行,並涵蓋錯誤處理與程式碼異味偵測。此技能並非特定框架的詳細指南;當涉及 React、後端架構或 API 設計等特定領域時,應參考更專門的技能(如 frontend-patterns 或 backend-patterns)。它支援 TypeScript、JavaScript 及 React 等技術棧,並提供了包括變數與函式命名、不變性模式、錯誤處理、非同步最佳實務、型別安全、並行執行、重複使用邏輯、以及提升應用程式可讀性與可維護性的具體程式碼範例。開發者在啟動新專案、進行程式碼審查、重構或設定 linting 規則時,應啟動此技能。

相容平台~Claude Code✓Codex CLI~Cursor
npx skills add https://github.com/affaan-m/ECC/tree/main/skills/coding-standards

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

程式碼撰寫規範與最佳實務 是做什麼的?

跨專案適用的基礎程式碼慣例。

此技能是共通的基準,而非詳細的框架實戰手冊。

  • 對於 React、狀態、表單、渲染和 UI 架構,請使用 frontend-patterns。
  • 對於 repository/service 層、端點設計、驗證和特定伺服器問題,請使用 backend-patterns 或 api-design。
  • 當你需要最簡短的可重用規則層而非完整的技能引導時,請使用 rules/common/coding-style.md。

啟用時機

  • 啟動新專案或模組時
  • 審查程式碼以確保品質與可維護性時
  • 重構現有程式碼以遵循慣例時
  • 強制執行命名、格式化或結構一致性時
  • 設定 linting、格式化或型別檢查規則時
  • 引導新貢獻者了解程式碼慣例時

範疇界定

啟用此技能處理:

  • 描述性命名
  • 預設不變性
  • 可讀性、KISS、DRY 與 YAGNI 的強制執行
  • 錯誤處理預期與程式碼異味審查

請勿將此技能作為下列情況的主要來源:

  • React 組合、hooks 或渲染模式
  • 後端架構、API 設計或資料庫分層
  • 當存在更狹義的 ECC 技能時,特定領域的框架指導

程式碼品質原則

1. 可讀性優先

  • 程式碼被閱讀的次數遠多於撰寫
  • 清晰的變數與函式名稱
  • 偏好自我文件化的程式碼而非註解
  • 一致性的格式化

2. KISS(保持簡單,笨蛋)

  • 能運作的最簡單方案
  • 避免過度工程化
  • 不進行過早最佳化
  • 易於理解 > 精巧的程式碼

3. DRY(不要重複自己)

  • 將通用邏輯提取為函式
  • 建立可重用的元件
  • 跨模組共享工具函式
  • 避免複製貼上程式設計

4. YAGNI(你不需要它)

  • 不要在需要之前就建立功能
  • 避免推測性的通用性
  • 只在必要時增加複雜度
  • 從簡單開始,需要時再重構

TypeScript/JavaScript 標準

變數命名

// PASS: 良好:描述性的名稱
const marketSearchQuery = 'election'
const isUserAuthenticated = true
const totalRevenue = 1000

// FAIL: 不良:不明確的名稱
const q = 'election'
const flag = true
const x = 1000

函式命名

// PASS: 良好:動詞-名詞模式
async function fetchMarketData(marketId: string) { }
function calculateSimilarity(a: number[], b: number[]) { }
function isValidEmail(email: string): boolean { }

// FAIL: 不良:不明確或純名詞
async function market(id: string) { }
function similarity(a, b) { }
function email(e) { }

不變性模式(關鍵)

// PASS: 總是使用展開運算子
const updatedUser = {
  ...user,
  name: 'New Name'
}

const updatedArray = [...items, newItem]

// FAIL: 絕對不要直接變異
user.name = 'New Name'  // 不良
items.push(newItem)     // 不良

錯誤處理

// PASS: 良好:全面的錯誤處理
async function fetchData(url: string) {
  try {
    const response = await fetch(url)

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`)
    }

    return await response.json()
  } catch (error) {
    console.error('Fetch failed:', error)
    throw new Error('Failed to fetch data')
  }
}

// FAIL: 不良:沒有錯誤處理
async function fetchData(url) {
  const response = await fetch(url)
  return response.json()
}

Async/Await 最佳實務

// PASS: 良好:盡可能平行執行
const [users, markets, stats] = await Promise.all([
  fetchUsers(),
  fetchMarkets(),
  fetchStats()
])

// FAIL: 不良:不必要地順序執行
const users = await fetchUsers()
const markets = await fetchMarkets()
const stats = await fetchStats()

型別安全

// PASS: 良好:適當的型別
interface Market {
  id: string
  name: string
  status: 'active' | 'resolved' | 'closed'
  created_at: Date
}

function getMarket(id: string): Promise<Market> {
  // Implementation
}

// FAIL: 不良:使用 'any'
function getMarket(id: any): Promise<any> {
  // Implementation
}

React 最佳實務

元件結構

// PASS: 良好:具有型別的函式元件
interface ButtonProps {
  children: React.ReactNode
  onClick: () => void
  disabled?: boolean
  variant?: 'primary' | 'secondary'
}

export function Button({
  children,
  onClick,
  disabled = false,
  variant = 'primary'
}: ButtonProps) {
  return (
    <button
      onClick={onClick}
      disabled={disabled}
      className={`btn btn-${variant}`}
    >
      {children}
    </button>
  )
}

// FAIL: 不良:沒有型別,結構不明確
export function Button(props) {
  return <button onClick={props.onClick}>{props.children}</button>
}

自訂 Hooks

// PASS: 良好:可重用的自訂 hook
export function useDebounce<T>(value: T, delay: number): T {
  const [debouncedValue, setDebouncedValue] = useState<T>(value)

  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value)
    }, delay)

    return () => clearTimeout(handler)
  }, [value, delay])

  return debouncedValue
}

// 使用方式
const debouncedQuery = useDebounce(searchQuery, 500)

狀態管理

// PASS: 良好:適當的狀態更新
const [count, setCount] = useState(0)

// 基於先前狀態的函式更新
setCount(prev => prev + 1)

// FAIL: 不良:直接參考狀態
setCount(count + 1)  // 在非同步場景下可能過時

條件渲染

// PASS: 良好:清晰的條件渲染
{isLoading && <Spinner />}
{error && <ErrorMessage error={error} />}
{data && <DataDisplay data={data} />}

// FAIL: 不良:三元運算子地獄
{isLoading ? <Spinner /> : error ? <ErrorMessage error={error} /> : data ? <DataDisplay data={data} /> : null}

API 設計標準

REST API 慣例

GET    /api/markets              # 列出所有市場
GET    /api/markets/:id          # 取得特定市場
POST   /api/markets              # 建立新市場
PUT    /api/markets/:id          # 更新市場(完整)
PATCH  /api/markets/:id          # 更新市場(部分)
DELETE /api/markets/:id          # 刪除市場

# 用於篩選的查詢參數
GET /api/markets?status=active&limit=10&offset=0

回應格式

// PASS: 良好:一致的回應結構
interface ApiResponse<T> {
  success: boolean
  data?: T
  error?: string
  meta?: {
    total: number
    page: number
    limit: number
  }
}

// 成功回應
return NextResponse.json({
  success: true,
  data: markets,
  meta: { total: 100, page: 1, limit: 10 }
})

// 錯誤回應
return NextResponse.json({
  success: false,
  error: 'Invalid request'
}, { status: 400 })

輸入驗證

import { z } from 'zod'

// PASS: 良好:綱要驗證
const CreateMarketSchema = z.object({
  name: z.string().min(1).max(200),
  description: z.string().min(1).max(2000),
  endDate: z.string().datetime(),
  categories: z.array(z.string()).min(1)
})

export async function POST(request: Request) {
  const body = await request.json()

  try {
    const validated = CreateMarketSchema.parse(body)
    // 使用驗證過的資料繼續
  } catch (error) {
    if (error instanceof z.ZodError) {
      return NextResponse.json({
        success: false,
        error: 'Validation failed',
        details: error.issues
      }, { status: 400 })
    }
  }
}

檔案組織

專案結構

src/
├── app/                    # Next.js App Router
│   ├── api/               # API 路由
│   ├── markets/           # 市場頁面
│   └── (auth)/           # 驗證頁面(路由群組)
├── components/            # React 元件
│   ├── ui/               # 通用 UI 元件
│   ├── forms/            # 表單元件
│   └── layouts/          # 佈局元件
├── hooks/                # 自訂 React hooks
├── lib/                  # 工具函式與設定
│   ├── api/             # API 客戶端
│   ├── utils/           # 輔助函式
│   └── constants/       # 常數
├── types/                # TypeScript 型別
└── styles/              # 全域樣式

檔案命名

components/Button.tsx          # 元件使用 PascalCase
hooks/useAuth.ts              # camelCase 搭配 'use' 前綴
lib/formatDate.ts             # 工具函式使用 camelCase
types/market.types.ts         # camelCase 搭配 .types 後綴

註解與文件

何時需加註解

// PASS: 良好:解釋 WHY,而非 WHAT
// 使用指數退避以避免在服務中斷期間壓垮 API
const delay = Math.min(1000 * Math.pow(2, retryCount), 30000)

// 為了處理大型陣列的效能,在此特意使用變異
items.push(newItem)

// FAIL: 不良:陳述顯而易見的事
// 計數器加 1
count++

// 將名稱設為使用者的名稱
name = user.name

公開 API 的 JSDoc

/**
 * 使用語義相似度搜尋市場。
 *
 * @param query - 自然語言搜尋查詢
 * @param limit - 最大結果數量(預設:10)
 * @returns 按相似度分數排序的市場陣列
 * @throws {Error} 如果 OpenAI API 失敗或 Redis 不可用
 *
 * @example
 * ```typescript
 * const results = await searchMarkets('election', 5)
 * console.log(results[0].name) // "Trump vs Biden"
 * ```
 */
export async function searchMarkets(
  query: string,
  limit: number = 10
): Promise<Market[]> {
  // 實作內容
}

效能最佳實務

記憶化

import { useMemo, useCallback } from 'react'

// PASS: 良好:記憶化昂貴的計算
// 排序前先複製 - Array.prototype.sort 會原地變異
const sortedMarkets = useMemo(() => {
  return [...markets].sort((a, b) => b.volume - a.volume)
}, [markets])

// PASS: 良好:記憶化回呼
const handleSearch = useCallback((query: string) => {
  setSearchQuery(query)
}, [])

延遲載入

import { lazy, Suspense } from 'react'

// PASS: 良好:延遲載入重量級元件
const HeavyChart = lazy(() => import('./HeavyChart'))

export function Dashboard() {
  return (
    <Suspense fallback={<Spinner />}>
      <HeavyChart />
    </Suspense>
  )
}

資料庫查詢

// PASS: 良好:只選取需要的欄位
const { data } = await supabase
  .from('markets')
  .select('id, name, status')
  .limit(10)

// FAIL: 不良:選取所有內容
const { data } = await supabase
  .from('markets')
  .select('*')

測試標準

測試結構(AAA 模式)

test('calculates similarity correctly', () => {
  // Arrange(安排)
  const vector1 = [1, 0, 0]
  const vector2 = [0, 1, 0]

  // Act(執行)
  const similarity = calculateCosineSimilarity(vector1, vector2)

  // Assert(斷言)
  expect(similarity).toBe(0)
})

測試命名

// PASS: 良好:描述性的測試名稱
test('returns empty array when no markets match query', () => { })
test('throws error when OpenAI API key is missing', () => { })
test('falls back to substring search when Redis unavailable', () => { })

// FAIL: 不良:模糊的測試名稱
test('works', () => { })
test('test search', () => { })

程式碼異味偵測

留意這些反模式:

1. 過長的函式

// FAIL: 不良:函式超過 50 行
function processMarketData() {
  // 100 行程式碼
}

// PASS: 良好:拆分為較小的函式
function processMarketData() {
  const validated = validateData()
  const transformed = transformData(validated)
  return saveData(transformed)
}

2. 深層巢狀

// FAIL: 不良:5 層以上的巢狀
if (user) {
  if (user.isAdmin) {
    if (market) {
      if (market.isActive) {
        if (hasPermission) {
          // 執行某些操作
        }
      }
    }
  }
}

// PASS: 良好:提前回傳
if (!user) return
if (!user.isAdmin) return
if (!market) return
if (!market.isActive) return
if (!hasPermission) return

// 執行某些操作

3. 魔術數字

// FAIL: 不良:未經說明的數字
if (retryCount > 3) { }
setTimeout(callback, 500)

// PASS: 良好:具名常數
const MAX_RETRIES = 3
const DEBOUNCE_DELAY_MS = 500

if (retryCount > MAX_RETRIES) { }
setTimeout(callback, DEBOUNCE_DELAY_MS)

請記住:程式碼品質不容妥協。清晰、可維護的程式碼能促成快速的開發與自信的重構。

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

affaan-m/ECC

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

affaan-m/fal-ai-media

Unified media generation via fal.ai MCP — image, video, and audio. Covers text-to-image (Nano Banana), text/image-to-video (Seedance, Kling, Veo 3), text-to-speech (CSM-1B), and video-to-audio (ThinkSound). Use when the user wants to generate images, videos, or audio with AI.

affaan-m/manim-video

日本語翻訳:このファイルは manim-video 用の日本語翻訳が必要です

affaan-m/remotion-video-creation

Remotion のベストプラクティス - React で動画を作成する。3D、アニメーション、音声、字幕、チャート、トランジションなどをカバーするドメイン固有の29のルール。

affaan-m/video-editing

AI-assisted video editing workflows for cutting, structuring, and augmenting real footage. Covers the full pipeline from raw capture through FFmpeg, Remotion, ElevenLabs, fal.ai, and final polish in Descript or CapCut. Use when the user wants to edit video, cut footage, create vlogs, or build video content.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

agent-self-evaluation

Use after completing any non-trivial task. The agent self-rates its output on 5 axes — accuracy, completeness, clarity, actionability, conciseness — with concrete evidence per criterion. Produces a structured 1-5 scorecard with specific improvement suggestions.

agent-sort

Build an evidence-backed ECC install plan for a specific repo by sorting skills, commands, rules, hooks, and extras into DAILY vs LIBRARY buckets using parallel repo-aware review passes. Use when ECC should be trimmed to what a project actually needs instead of loading the full bundle.

ai-first-engineering

Engineering operating model for teams where AI agents generate a large share of implementation output. Use when setting team process, review gates, or ownership rules for a codebase largely written by agents.

ai-regression-testing

Regression testing strategies for AI-assisted development. Sandbox-mode API testing without database dependencies, automated bug-check workflows, and patterns to catch AI blind spots where the same model writes and reviews code. Use when adding regression coverage to AI-assisted code, or when the same model both wrote and reviewed a change.

android-clean-architecture

Clean Architecture patterns for Android and Kotlin Multiplatform projects — module structure, dependency rules, UseCases, Repositories, and data layer patterns. Use when structuring modules, layers, or data flow in an Android or KMP project.

angular-developer

Generates Angular code and provides architectural guidance. Trigger when creating projects, components, or services, or for best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling (component styles, Tailwind CSS), testing, or CLI tooling.

相關技能