Coding Standards

affaan-m/ECC/docs/zh-TW/skills/coding-standards

作者 affaan-mef648e01899ba3e8dc6371642deaaf64b4477775無授權條款275K 個星標收錄於 2026年10月9日更新於 2026年10月9日儲存庫4 天前更新

Universal coding standards, best practices, and patterns for TypeScript, JavaScript, React, and Node.js development.

AI 產生的概覽

為 TypeScript、JavaScript、React 與 Node.js 專案提供通用程式碼標準與最佳實務。

功能
此技能提供一套程式碼標準參考,涵蓋可讀性、KISS、DRY 與 YAGNI 原則,以及 TypeScript/JavaScript 的命名、不可變性、錯誤處理、非同步模式與型別安全等具體慣例。它也記錄了 React 元件、Hook 與狀態模式、REST API 設計與驗證、檔案組織、註解、效能與測試慣例。它產出的是指引與範例,而非產生的程式碼或檔案。
適用情境
在撰寫、審查或重構 TypeScript、JavaScript、React 或 Node.js 程式碼,且需要一致的專案標準時使用。它也適合用於新成員上手,或釐清風格與結構方面的歧見。
執行需求
不需要任何工具、套件或憑證;僅為說明性內容,不附帶指令碼。

程式碼標準與最佳實務

適用於所有專案的通用程式碼標準。

程式碼品質原則

1. 可讀性優先

  • 程式碼被閱讀的次數遠多於被撰寫的次數
  • 使用清晰的變數和函式名稱
  • 優先使用自文件化的程式碼而非註解
  • 保持一致的格式化

2. KISS(保持簡單)

  • 使用最簡單的解決方案
  • 避免過度工程
  • 不做過早優化
  • 易於理解 > 聰明的程式碼

3. DRY(不重複自己)

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

4. YAGNI(你不會需要它)

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

TypeScript/JavaScript 標準

變數命名

typescript
// PASS: 良好:描述性名稱const marketSearchQuery = 'election'const isUserAuthenticated = trueconst totalRevenue = 1000
// FAIL: 不良:不清楚的名稱const q = 'election'const flag = trueconst x = 1000

函式命名

typescript
// 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) { }

不可變性模式(關鍵)

typescript
// PASS: 總是使用展開運算符const updatedUser = {  ...user,  name: 'New Name'}
const updatedArray = [...items, newItem]
// FAIL: 永遠不要直接修改user.name = 'New Name'  // 不良items.push(newItem)     // 不良

錯誤處理

typescript
// 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 最佳實務

typescript
// PASS: 良好:可能時並行執行const [users, markets, stats] = await Promise.all([  fetchUsers(),  fetchMarkets(),  fetchStats()])
// FAIL: 不良:不必要的順序執行const users = await fetchUsers()const markets = await fetchMarkets()const stats = await fetchStats()

型別安全

typescript
// PASS: 良好:正確的型別interface Market {  id: string  name: string  status: 'active' | 'resolved' | 'closed'  created_at: Date}
function getMarket(id: string): Promise<Market> {  // 實作}
// FAIL: 不良:使用 'any'function getMarket(id: any): Promise<any> {  // 實作}

React 最佳實務

元件結構

typescript
// 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

typescript
// PASS: 良好:可重用的自訂 hookexport 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)

狀態管理

typescript
// PASS: 良好:正確的狀態更新const [count, setCount] = useState(0)
// 基於先前狀態的函式更新setCount(prev => prev + 1)
// FAIL: 不良:直接引用狀態setCount(count + 1)  // 在非同步情境中可能過時

條件渲染

typescript
// 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

回應格式

typescript
// 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 })

輸入驗證

typescript
import { z } from 'zod'
// PASS: 良好:Schema 驗證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.errors      }, { 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          # 元件用 PascalCasehooks/useAuth.ts              # hooks 用 camelCase 加 'use' 前綴lib/formatDate.ts             # 工具用 camelCasetypes/market.types.ts         # 型別用 camelCase 加 .types 後綴

註解與文件

何時註解

typescript
// PASS: 良好:解釋「為什麼」而非「什麼」// 使用指數退避以避免在服務中斷時壓垮 APIconst delay = Math.min(1000 * Math.pow(2, retryCount), 30000)
// 為了處理大陣列的效能,此處刻意使用突變items.push(newItem)
// FAIL: 不良:陳述顯而易見的事實// 將計數器加 1count++
// 將名稱設為使用者的名稱name = user.name

公開 API 的 JSDoc

typescript
/** * 使用語意相似度搜尋市場。 * * @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[]> {  // 實作}

效能最佳實務

記憶化

typescript
import { useMemo, useCallback } from 'react'
// PASS: 良好:記憶化昂貴的計算const sortedMarkets = useMemo(() => {  return markets.sort((a, b) => b.volume - a.volume)}, [markets])
// PASS: 良好:記憶化回呼函式const handleSearch = useCallback((query: string) => {  setSearchQuery(query)}, [])

延遲載入

typescript
import { lazy, Suspense } from 'react'
// PASS: 良好:延遲載入重型元件const HeavyChart = lazy(() => import('./HeavyChart'))
export function Dashboard() {  return (    <Suspense fallback={<Spinner />}>      <HeavyChart />    </Suspense>  )}

資料庫查詢

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

測試標準

測試結構(AAA 模式)

typescript
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)})

測試命名

typescript
// 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. 過長函式

typescript
// FAIL: 不良:函式超過 50 行function processMarketData() {  // 100 行程式碼}
// PASS: 良好:拆分為較小的函式function processMarketData() {  const validated = validateData()  const transformed = transformData(validated)  return saveData(transformed)}

2. 過深巢狀

typescript
// FAIL: 不良:5 層以上巢狀if (user) {  if (user.isAdmin) {    if (market) {      if (market.isActive) {        if (hasPermission) {          // 做某事        }      }    }  }}
// PASS: 良好:提前返回if (!user) returnif (!user.isAdmin) returnif (!market) returnif (!market.isActive) returnif (!hasPermission) return
// 做某事

3. 魔術數字

typescript
// FAIL: 不良:無解釋的數字if (retryCount > 3) { }setTimeout(callback, 500)
// PASS: 良好:命名常數const MAX_RETRIES = 3const DEBOUNCE_DELAY_MS = 500
if (retryCount > MAX_RETRIES) { }setTimeout(callback, DEBOUNCE_DELAY_MS)

記住:程式碼品質是不可協商的。清晰、可維護的程式碼能實現快速開發和自信的重構。

來源與署名

來源:affaan-m/ECC位於docs/zh-TW/skills/coding-standards提交ef648e0

授權條款: 無授權條款

內容歸原作者所有。SourceWeft 從公開儲存庫中收錄這些內容。

檢舉或申請下架