LESSON 15分

ストーリー

高橋アーキテクト
優れたコードは、まるで優れた文章のように読める
高橋アーキテクト
メトリクスが良くても、読んでいて意味がわからないコードは良いコードとは言えない。最後に、人間にとって読みやすいコードの原則をおさらいしよう

命名の原則

名前はコードの中で最も多く読まれる要素です。良い名前は、コメントがなくてもコードの意図を伝えます。

変数名

// 悪い命名
const d = new Date();
const n = users.filter(u => u.a);
const tmp = calculateTotal(items);

// 良い命名
const currentDate = new Date();
const activeUsers = users.filter(user => user.isActive);
const orderTotal = calculateTotal(items);

関数名

// 悪い命名:何をするのか不明
function process(data: User[]): void { /* ... */ }
function handle(event: Event): void { /* ... */ }
function doStuff(): void { /* ... */ }

// 良い命名:動詞 + 目的語で明確
function deactivateExpiredUsers(users: User[]): void { /* ... */ }
function logNavigationEvent(event: NavigationEvent): void { /* ... */ }
function calculateMonthlyRevenue(): number { /* ... */ }

ブーリアン変数

// 悪い命名
const flag = true;
const status = false;

// 良い命名:is/has/can/should で始める
const isActive = true;
const hasPermission = false;
const canDelete = user.role === 'admin';
const shouldRetry = attemptCount < MAX_RETRIES;

関数の長さとレベル

1つの関数は1つのことを

// 悪い例:複数のことを同時にやっている
function processUserRegistration(form: FormData): void {
  // バリデーション
  if (!form.email.includes('@')) throw new Error('Invalid email');
  if (form.password.length < 8) throw new Error('Password too short');
  // DB保存
  const user = db.insert('users', { email: form.email, password: hash(form.password) });
  // メール送信
  smtp.send(form.email, 'Welcome!', `Hello ${form.name}...`);
  // ログ記録
  logger.info(`User registered: ${user.id}`);
}

// 良い例:1つの関数が1つの抽象レベルの処理
function processUserRegistration(form: FormData): void {
  validateRegistrationForm(form);
  const user = createUser(form);
  sendWelcomeEmail(user);
  logRegistration(user);
}

抽象レベルを揃える

// 悪い例:抽象レベルが混在
function generateReport(): string {
  const data = this.reportService.fetchData();     // 高レベル
  const formatted = data.map(d => {                // 低レベル開始
    const date = new Date(d.timestamp);
    const y = date.getFullYear();
    const m = String(date.getMonth() + 1).padStart(2, '0');
    return `${y}-${m}: ${d.value.toFixed(2)}`;     // 低レベル終了
  });
  return this.reportService.buildPdf(formatted);   // 高レベル
}

// 良い例:同じ抽象レベルで統一
function generateReport(): string {
  const data = this.reportService.fetchData();
  const formatted = this.formatReportData(data);
  return this.reportService.buildPdf(formatted);
}

コメントの使い方

書くべきコメント

// WHY(なぜ)を説明するコメント
// 税率は年度ごとに変わるため、ハードコードせずに設定から取得する
const taxRate = config.getTaxRate(fiscalYear);

// 非自明なビジネスルールの説明
// 30日以上経過した仮登録ユーザーは自動削除対象
const expiredUsers = users.filter(u =>
  u.status === 'provisional' && daysSince(u.createdAt) > 30
);

// TODO/FIXME/HACK(技術的負債の明示)
// TODO: パフォーマンス改善 - N+1クエリを修正する (#1234)

書くべきでないコメント

// WHAT(何を)を繰り返すだけのコメントは不要
// ユーザーの年齢を取得する
const age = user.getAge();  // コードを読めばわかる

// 変更履歴をコメントで残す(Gitがある)
// 2024-01-15 田中: メール送信機能追加
// 2024-02-01 佐藤: バグ修正

まとめ

ポイント内容
命名意図が伝わる具体的な名前をつける
関数の長さ1つの関数は1つのことをする
抽象レベル同じ関数内で抽象レベルを揃える
コメントWHYを書き、WHATは書かない

チェックリスト

  • 良い命名の原則を理解した
  • 関数を1つの責任に絞る考え方を理解した
  • 適切なコメントと不要なコメントの区別ができる

次のステップへ

Step 1 の最後は理解度チェックのクイズです。ここまで学んだコード品質の基礎知識を確認しましょう。


推定読了時間: 15分