Interactive

リファクタリング

社内で取り決めたリファクタリングのルールをシステムプロンプトに含めておくことで、ClaudeCodeは一貫したコードスタイルを生成できます。弊社では、ファイルを小さく保ちトークンを節約する実用的なルールや、可読性を向上させるルールを設定することで、効率的な開発環境の実現を図っています。

弊社の推奨ルール

  1. 1ファイル1責務の原則 - 1つのファイルに1つの関数またはクラスのみを定義する
  2. 命名規則の統一 - ファイル名は小文字ケバブケース、関数名はキャメルケース
  3. 型安全性の確保 - anyは許容するが、実行時エラーを引き起こす型アサーションは禁止
  4. 分割代入を避ける - propsや引数の出所を明確にするため
  5. 変数名は内容が分かる命名 - dataやresultなどの汎用的な名前を避ける

ClaudeCodeでの利用

「このファイルを1ファイル1関数に分割して。
各関数は適切なファイル名で別ファイルに切り出して」
「変数名をすべて内容が分かる名前に変更して。
配列は複数形、Boolean はis/hasプレフィックスを付けて」
「分割代入を使っている箇所をすべてpropsから直接参照する形に変更して」
「ファイル名をすべて小文字ケバブケースに変更して。
関数名はキャメルケース、Reactコンポーネントはパスカルケースに」

複数の機能ではなく1ファイル1責務を使う

ファイルの責務を明確にするため、1つのファイルに1つの機能のみを定義します。

// ❌ 避ける:複数の機能が混在
// utils.ts
export function uploadFile(file: File) { /* ... */ }
export function validateEmail(email: string) { /* ... */ }
export function formatDate(date: Date) { /* ... */ }

// ✅ 推奨:1ファイル1機能
// upload-file.ts
export async function uploadFile(file: File): Promise<string> {
  const formData = new FormData()
  formData.append('file', file)
  const response = await fetch('/api/upload', { 
    method: 'POST', 
    body: formData 
  })
  return response.json()
}

// validate-email.ts
export function validateEmail(email: string): boolean {
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)
}

// format-date.ts
export function formatDate(date: Date): string {
  return date.toLocaleDateString('ja-JP')
}

大文字ファイル名ではなく小文字ケバブケースを使う

Webフレームワークのルーティングとの整合性のため、すべて小文字で統一します。

// ❌ 避ける:大文字やキャメルケース
UserService.ts
xxxPayPay.ts
AdminPanel.tsx

// ✅ 推奨:小文字ケバブケース
user-service.ts
xxx-paypay.ts     // PayPayも小文字
admin-panel.tsx

分割代入ではなく直接参照を使う

変数の出所を明確にし、リファクタリング時の問題を防ぎます。

// ❌ 避ける:分割代入
type Props = {
  name: string
  age: number
}

function MyComponent({ name, age }: Props) {
  return <p>{name} ({age})</p> // nameの出所が不明確
}

// ✅ 推奨:propsから直接参照
function MyComponent(props: Props) {
  return <p>{props.name} ({props.age})</p> // propsから来たことが明確
}

型アサーションではなくanyを使う

型が不明な場合は危険な型アサーションよりもanyを使用します。

// ❌ 避ける:危険な型アサーション
const user = data as User // dataがUserでない可能性
const name = user.name! // 実行時エラーのリスク

// ✅ 推奨:anyを使用
const data: any = await fetchUnknownAPI()
// TODO: APIの型定義が決まったら修正する
if (data && data.name) {
  console.log(data.name) // 安全にアクセス
}

汎用的な名前ではなく内容が分かる名前を使う

変数の中身を名前から推測できるようにします。

// ❌ 避ける:汎用的で中身が不明
const data = await getPosts()      // dataの中身は?
const result = await getUser(id)   // resultの型は?
const items = users.filter(u => u.active) // 何のitems?

// ✅ 推奨:内容が明確
const posts = await getPosts()           // 複数の投稿
const user = await getUser(id)           // 1件のユーザー
const activeUsers = users.filter(u => u.active) // アクティブなユーザー

// Boolean変数はis/hasプレフィックス
const isLoading = false
const hasPermission = true
const canEdit = user.role === 'admin'

よくある問題

複数形が分からない単語がある

英語の複数形が不明または不自然な単語がある問題です。ListItemsArrayなどの接尾辞を使用することで解決できます。

// ❌ 複数形が不明または不自然
const informations = []    // informationは不可算名詞
const newses = []          // newsは単複同形
const historys = []        // historyの複数形はhistories

// ✅ 代替案
const infoList = []        // Listを付ける
const newsItems = []       // Itemsを付ける
const historyEntries = []  // 具体的な名詞を使う

長い変数名になってしまう

変数名が長くなりすぎる問題です。コンテキストから明確な部分を省略することで解決できます。

// ❌ 冗長
class UserService {
  private userServiceActiveUsersList: User[] = []
  
  getUserServiceActiveUsersListCount() {
    return this.userServiceActiveUsersList.length
  }
}

// ✅ コンテキストから明確な部分を省略
class UserService {
  private activeUsers: User[] = []
  
  getActiveCount() {
    const active = this.activeUsers.filter(u => !u.deletedAt)
    return active.length
  }
}

日本語の概念に対応する英単語が分からない

適切な英単語が見つからない問題です。一般的なWeb開発で使われる単語を調査して使用することで解決できます。

// ✅ 一般的な対応
const draft = {}        // 下書き
const published = {}    // 公開済み
const archived = {}     // アーカイブ済み
const pending = {}      // 保留中
const approved = {}     // 承認済み