「リーダブルコード」読書感想

## はじめに

エンジニア2年目になり、コードレビューを受ける機会が増えてきました。レビューで指摘される内容も1年目の頃とは変わり、単純な文法エラーよりも「可読性」や「保守性」に関するコメントが多くなりました。そんな中で「リーダブルコード」を読み、普段Python・Djangoでの開発にTDDを取り入れている私にとって、多くの学びを得ることができました。

## 重要なところの要約

### 「理解するまでの時間」を最優先に

本書の核心は「コードは他の人が最短時間で理解できるように書かなければならない」という点です。つまり、短いコードよりも、理解しやすいコードの方が価値が高いということです。

### 表面上の改善（第1部）

**命名の重要性**が特に印象に残りました。`tmp`や`data`といった汎用的な名前を避け、「何を表しているか」を明確にする。

```python
# 悪い例：汎用的すぎる名前
def get_data(request):
    data = User.objects.filter(status=1)
    tmp = []
    for d in data:
        tmp.append(d.name)
    return tmp

# 良い例：明確で具体的な名前
def get_active_user_names(request):
    active_users = User.objects.filter(is_active=True)
    user_names = []
    for user in active_users:
        user_names.append(user.name)
    return user_names

```

限界値には`max_`/`min_`、範囲には`first_`/`last_`を使うなど、具体的な指針も実践的でした。

```python
# 悪い例：曖昧な限界値
MAX_ITEMS = 10  # 10を含む？含まない？

# 良い例：明確な限界値
MAX_ITEMS_COUNT = 10  # 10個まで（10を含む）

```

**コメントの使い分け**については、「コードから推測できることは書かない」「なぜそうしたかの理由を書く」という原則が参考になりました。

```python
# 悪い例：コードを説明するだけ
# ユーザー一覧を取得
users = User.objects.all()

# 良い例：理由や背景を説明
# パフォーマンス向上のため、非アクティブユーザーは除外
# (過去のA/Bテストで応答時間が30%改善することを確認済み)
users = User.objects.filter(is_active=True)

```

### ロジックの単純化（第2部）

**早期リターンによるネスト削減**は、すぐに実践できる技法でした。

```python
# 悪い例：深いネスト
def create_post(request):
    if request.method == 'POST':
        if request.user.is_authenticated:
            if request.POST.get('title'):
                # メインの処理
                return create_post_logic(request)
            else:
                return JsonResponse({'error': 'タイトルが必要'})
        else:
            return JsonResponse({'error': 'ログインが必要'})
    else:
        return JsonResponse({'error': 'POSTのみ許可'})

# 良い例：早期リターンでネストを削減
def create_post(request):
    if request.method != 'POST':
        return JsonResponse({'error': 'POSTのみ許可'})

    if not request.user.is_authenticated:
        return JsonResponse({'error': 'ログインが必要'})

    if not request.POST.get('title'):
        return JsonResponse({'error': 'タイトルが必要'})

    # メインの処理（ネストなし）
    return create_post_logic(request)

```

**巨大な式の分割**で紹介された「説明変数」「要約変数」の概念も有用でした。

```python
# 悪い例：複雑な条件式
if request.user.is_staff and request.user.profile.department == 'IT' and request.user.profile.years_of_service > 3:
    # 処理

# 良い例：説明変数で分割
is_staff_member = request.user.is_staff
is_it_department = request.user.profile.department == 'IT'
has_sufficient_experience = request.user.profile.years_of_service > 3
can_access_admin_feature = is_staff_member and is_it_department and has_sufficient_experience

if can_access_admin_feature:
    # 処理

```

### コードの再編成（第3部）

- **「一度に1つのことを」**という原則は、関数設計の指針として非常に有用でした。

```python
# 悪い例：複数のことを一度に行う
def process_user_data(user_id):
    # ユーザー取得
    user = User.objects.get(id=user_id)

    # データ変換
    user_data = {
        'name': user.first_name + ' ' + user.last_name,
        'age': calculate_age(user.birth_date)
    }

    # ログ出力
    logger.info(f"User {user_id} processed")

    # メール送信
    send_notification_email(user.email, user_data)

    return user_data

# 良い例：責任を分割
def get_user_by_id(user_id):
    return User.objects.get(id=user_id)

def format_user_data(user):
    return {
        'name': f"{user.first_name} {user.last_name}",
        'age': calculate_age(user.birth_date)
    }

def log_user_processing(user_id):
    logger.info(f"User {user_id} processed")

def notify_user_processing(user_email, user_data):
    send_notification_email(user_email, user_data)

def process_user_data(user_id):
    user = get_user_by_id(user_id)
    user_data = format_user_data(user)
    log_user_processing(user_id)
    notify_user_processing(user.email, user_data)
    return user_data

```

## 本書で得た気付き

### 1. コードレビューでの指摘が理解できるように

これまでレビューで「もう少し読みやすくできませんか？」と言われても具体的にどうすべきかわからないことがありました。しかし、本書の原則を知ることで、レビュアーの意図が理解できるようになりました。

例えば、「この条件分岐は複雑すぎる」という指摘は、8章の「巨大な式を分割する」の話だったのだと今なら理解できます。

### 2. TDDとの相性の良さ

TDDで開発していると、テストコードも含めて読みやすさが重要だと実感しています。テストメソッド名も「何をテストしているか」が一目でわかるよう命名することで、テストの保守性が向上しました。

```python
# 改善前
def test_user_validation(self):
    pass

# 改善後
def test_should_reject_user_registration_with_invalid_email(self):
    pass

```

### 4. 「6ヶ月後の自分」も他人という視点

特に響いたのは**「6ヶ月後の自分も他人」**という考え方です。実際に過去のコードを見返すと、当時は理解していたつもりでも、今見ると意図がわからないコードが多数ありました。この経験により、未来の自分のためにもコードを書くという意識が芽生えました。

## 今後のコーディングスタイル

### 1. 命名規則の徹底

- 変数名・関数名は処理内容を具体的に表現する
- ブール値には`is_`、`has_`、`can_`を積極的に使用
- 単位がある値には単位を付加（`timeout_sec`、`max_retry_count`など）

```python
# 改善予定のスタイル
def fetch_active_users_with_recent_login(days_threshold=30):
    cutoff_date = timezone.now() - timedelta(days=days_threshold)
    return User.objects.filter(
        is_active=True,
        last_login__gte=cutoff_date
    )

```

### 2. 関数設計の原則

- 1つの関数は1つのことだけを行う
- 引数は3つ以下を目指す
- 早期リターンを活用してネストを浅くする
- 副作用のない純粋関数を心がける

### 3. コメント戦略

- WHATではなくWHYを書く
- TODOコメントには期限や担当者を明記
- 複雑なビジネスロジックには要約コメントを付ける

```python
# 改善予定のコメントスタイル
def calculate_discount_rate(user, product):
    # ゴールド会員は特別価格適用のため、
    # 通常の割引計算とは異なるロジックを使用
    if user.membership_level == 'GOLD':
        return calculate_gold_member_discount(user, product)

    # TODO(2024-07-01): プレミアム会員制度導入時に追加予定
    return calculate_standard_discount(product)

```

### 4. コードレビューでの活用

- 自分のコードをcommitする前にセルフレビューする際の基準として使用
- レビューコメントを理解するための共通言語として活用
- リファクタリングの指針として参照

### 5. 継続的な改善

- 月1回、過去に書いたコードをリーダブルコードの観点で見直す
- 新しい技術や設計パターンを学ぶ際も、可読性を重視した選択をする

## まとめ

「リーダブルコード」は、技術的なスキルだけでなく、「他者への思いやり」の重要性を教えてくれました。コードは自分だけのものではなく、チームメンバーや未来の自分のためのコミュニケーションツールです。

2年目という成長段階で本書と出会えたことで、悪い癖が固まる前に正しい方向性を学ぶことができました。まだまだ完璧に実践できているわけではありませんが、意識することから始めて、日々のコーディングで少しずつ改善していきたいと思います。