Coding Standards

affaan-m/ECC/docs/ja-JP/skills/coding-standards

作者 affaan-mef648e01899ba3e8dc6371642deaaf64b4477775无许可证275K 个星标收录于 2026年10月9日更新于 2026年10月9日仓库4天前更新

TypeScript、JavaScript、React、Node.js開発のための汎用コーディング標準、ベストプラクティス、パターン。

AI 生成的概览

为 TypeScript、JavaScript、React 和 Node.js 开发提供通用编码标准与最佳实践。

功能
该技能提供一套编码标准、约定与模式的参考,涵盖代码质量原则、命名、不可变性、错误处理、async/await、类型安全、React 组件与自定义 Hook、REST API 设计、文件结构、注释、性能与测试。每条规则都配有正面与反面代码示例,并包含代码坏味道的识别指引。它产出的是书面规范,而非可执行产物。
适用场景
在编写、审查或重构 TypeScript、JavaScript、React 或 Node.js 代码,且需要统一的项目级标准时使用。也适用于新人上手或风格讨论,用具体示例说明推荐与不推荐的写法。
运行要求
无需任何工具、软件包或凭据;仅为说明性内容,不附带脚本。

コーディング標準とベストプラクティス

すべてのプロジェクトに適用される汎用的なコーディング標準。

コード品質の原則

1. 可読性優先

  • コードは書くよりも読まれることが多い
  • 明確な変数名と関数名
  • コメントよりも自己文書化コードを優先
  • 一貫したフォーマット

2. KISS (Keep It Simple, Stupid)

  • 機能する最もシンプルなソリューションを採用
  • 過剰設計を避ける
  • 早すぎる最適化を避ける
  • 理解しやすさ > 巧妙なコード

3. DRY (Don't Repeat Yourself)

  • 共通ロジックを関数に抽出
  • 再利用可能なコンポーネントを作成
  • ユーティリティ関数をモジュール間で共有
  • コピー&ペーストプログラミングを避ける

4. YAGNI (You Aren't Gonna Need It)

  • 必要ない機能を事前に構築しない
  • 推測的な一般化を避ける
  • 必要なときのみ複雑さを追加
  • シンプルに始めて、必要に応じてリファクタリング

TypeScript/JavaScript標準

変数の命名

typescript
// PASS: GOOD: Descriptive namesconst marketSearchQuery = 'election'const isUserAuthenticated = trueconst totalRevenue = 1000
// FAIL: BAD: Unclear namesconst q = 'election'const flag = trueconst x = 1000

関数の命名

typescript
// PASS: GOOD: Verb-noun patternasync function fetchMarketData(marketId: string) { }function calculateSimilarity(a: number[], b: number[]) { }function isValidEmail(email: string): boolean { }
// FAIL: BAD: Unclear or noun-onlyasync function market(id: string) { }function similarity(a, b) { }function email(e) { }

不変性パターン(重要)

typescript
// PASS: ALWAYS use spread operatorconst updatedUser = {  ...user,  name: 'New Name'}
const updatedArray = [...items, newItem]
// FAIL: NEVER mutate directlyuser.name = 'New Name'  // BADitems.push(newItem)     // BAD

エラーハンドリング

typescript
// PASS: GOOD: Comprehensive error handlingasync 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: BAD: No error handlingasync function fetchData(url) {  const response = await fetch(url)  return response.json()}

Async/Awaitベストプラクティス

typescript
// PASS: GOOD: Parallel execution when possibleconst [users, markets, stats] = await Promise.all([  fetchUsers(),  fetchMarkets(),  fetchStats()])
// FAIL: BAD: Sequential when unnecessaryconst users = await fetchUsers()const markets = await fetchMarkets()const stats = await fetchStats()

型安全性

typescript
// PASS: GOOD: Proper typesinterface Market {  id: string  name: string  status: 'active' | 'resolved' | 'closed'  created_at: Date}
function getMarket(id: string): Promise<Market> {  // Implementation}
// FAIL: BAD: Using 'any'function getMarket(id: any): Promise<any> {  // Implementation}

Reactベストプラクティス

コンポーネント構造

typescript
// PASS: GOOD: Functional component with typesinterface 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: BAD: No types, unclear structureexport function Button(props) {  return <button onClick={props.onClick}>{props.children}</button>}

カスタムフック

typescript
// PASS: GOOD: Reusable custom 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}
// Usageconst debouncedQuery = useDebounce(searchQuery, 500)

状態管理

typescript
// PASS: GOOD: Proper state updatesconst [count, setCount] = useState(0)
// Functional update for state based on previous statesetCount(prev => prev + 1)
// FAIL: BAD: Direct state referencesetCount(count + 1)  // Can be stale in async scenarios

条件付きレンダリング

typescript
// PASS: GOOD: Clear conditional rendering{isLoading && <Spinner />}{error && <ErrorMessage error={error} />}{data && <DataDisplay data={data} />}
// FAIL: BAD: Ternary hell{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: GOOD: Consistent response structureinterface ApiResponse<T> {  success: boolean  data?: T  error?: string  meta?: {    total: number    page: number    limit: number  }}
// Success responsereturn NextResponse.json({  success: true,  data: markets,  meta: { total: 100, page: 1, limit: 10 }})
// Error responsereturn NextResponse.json({  success: false,  error: 'Invalid request'}, { status: 400 })

入力検証

typescript
import { z } from 'zod'
// PASS: GOOD: Schema validationconst 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)    // Proceed with validated data  } 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 フック├── lib/                  # ユーティリティと設定│   ├── api/             # API クライアント│   ├── utils/           # ヘルパー関数│   └── constants/       # 定数├── types/                # TypeScript 型定義└── styles/              # グローバルスタイル

ファイル命名

components/Button.tsx          # コンポーネントは PascalCasehooks/useAuth.ts              # フックは 'use' プレフィックス付き camelCaselib/formatDate.ts             # ユーティリティは camelCasetypes/market.types.ts         # 型定義は .types サフィックス付き camelCase

コメントとドキュメント

コメントを追加するタイミング

typescript
// PASS: GOOD: Explain WHY, not WHAT// Use exponential backoff to avoid overwhelming the API during outagesconst delay = Math.min(1000 * Math.pow(2, retryCount), 30000)
// Deliberately using mutation here for performance with large arraysitems.push(newItem)
// FAIL: BAD: Stating the obvious// Increment counter by 1count++
// Set name to user's namename = user.name

パブリックAPIのJSDoc

typescript
/** * Searches markets using semantic similarity. * * @param query - Natural language search query * @param limit - Maximum number of results (default: 10) * @returns Array of markets sorted by similarity score * @throws {Error} If OpenAI API fails or Redis unavailable * * @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[]> {  // Implementation}

パフォーマンスベストプラクティス

メモ化

typescript
import { useMemo, useCallback } from 'react'
// PASS: GOOD: Memoize expensive computationsconst sortedMarkets = useMemo(() => {  return markets.sort((a, b) => b.volume - a.volume)}, [markets])
// PASS: GOOD: Memoize callbacksconst handleSearch = useCallback((query: string) => {  setSearchQuery(query)}, [])

遅延読み込み

typescript
import { lazy, Suspense } from 'react'
// PASS: GOOD: Lazy load heavy componentsconst HeavyChart = lazy(() => import('./HeavyChart'))
export function Dashboard() {  return (    <Suspense fallback={<Spinner />}>      <HeavyChart />    </Suspense>  )}

データベースクエリ

typescript
// PASS: GOOD: Select only needed columnsconst { data } = await supabase  .from('markets')  .select('id, name, status')  .limit(10)
// FAIL: BAD: Select everythingconst { 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: GOOD: Descriptive test namestest('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: BAD: Vague test namestest('works', () => { })test('test search', () => { })

コードスメルの検出

以下のアンチパターンに注意してください。

1. 長い関数

typescript
// FAIL: BAD: Function > 50 linesfunction processMarketData() {  // 100 lines of code}
// PASS: GOOD: Split into smaller functionsfunction processMarketData() {  const validated = validateData()  const transformed = transformData(validated)  return saveData(transformed)}

2. 深いネスト

typescript
// FAIL: BAD: 5+ levels of nestingif (user) {  if (user.isAdmin) {    if (market) {      if (market.isActive) {        if (hasPermission) {          // Do something        }      }    }  }}
// PASS: GOOD: Early returnsif (!user) returnif (!user.isAdmin) returnif (!market) returnif (!market.isActive) returnif (!hasPermission) return
// Do something

3. マジックナンバー

typescript
// FAIL: BAD: Unexplained numbersif (retryCount > 3) { }setTimeout(callback, 500)
// PASS: GOOD: Named constantsconst MAX_RETRIES = 3const DEBOUNCE_DELAY_MS = 500
if (retryCount > MAX_RETRIES) { }setTimeout(callback, DEBOUNCE_DELAY_MS)

覚えておいてください: コード品質は妥協できません。明確で保守可能なコードにより、迅速な開発と自信を持ったリファクタリングが可能になります。

来源与署名

来源:affaan-m/ECC位于docs/ja-JP/skills/coding-standards提交ef648e0

许可证: 无许可证

内容归原作者所有。SourceWeft 从公开仓库中收录这些内容。

举报或申请下架