1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

日本人エンジニアの「コメント山盛り」あるある、AI時代に改善してみた

1
Last updated at Posted at 2026-04-05

こんにちは。@m_koshikawa です。

Xで「英語圏以外のエンジニアはどうやってコードを書いてるの?」という問いを見かけました。

自分の答えはこうでした。

日本人にとって、プログラミング言語はそもそもが異次元の言語です。だから関数や変数の宣言、ifやswitchの分岐のたびに、日本語コメントを山ほどつけて「日本語で理解できる状態」にしています。

これは自分自身が長年体験し続けてきたことです。そして多くの日本人エンジニアに心当たりがあるはずです。

この習慣は、人間がコードを読む時代には正しかったと思います。しかし今、コードを読むのは人間だけではありません。AIエージェントがコードを読み、レビューし、修正を提案する時代になりました。

コードの読み手が人間だけからAIにも広がったなら、「丁寧さ」の届け先も変える必要があります。

本記事では、日本人エンジニアのコーディング「あるある」を4つ挙げ、AI時代にどう改善したかを書きます。

日本人のコーディング「あるある」4選

実際のプロジェクトで日常的に見かけるパターンです。どれも「丁寧に書こう」という善意から生まれています。

あるある1: ステップ番号コメント

def upload_file(client, container, path, download):
    # 1. ストレージからダウンロード
    content = download(container, path)

    # 2. 一時ファイルに保存
    tmp = tempfile.NamedTemporaryFile(mode='w', suffix='.csv', delete=False)
    tmp.write(content)
    tmp.close()

    # 3. APIにアップロード
    with open(tmp.name, "rb") as f:
        uploaded = client.files.create(file=f, purpose="assistants")

    return uploaded.id, tmp.name

手順を日本語で番号付きに説明しています。コードを上から読めばわかることを、もう一度日本語で書いています。

あるある2: 関数名を日本語で翻訳するdocstring

def apply_header_style(ws, row, col_start, col_end):
    """ヘッダー行にスタイルを適用する"""
    for col in range(col_start, col_end + 1):
        cell = ws.cell(row=row, column=col)
        cell.font = HEADER_FONT
        cell.fill = HEADER_FILL

apply_header_style が「ヘッダー行にスタイルを適用する」ことは、関数名がそのまま言っています。docstringが関数名の日本語翻訳になっています。

あるある3: 冗長なArgs/Returns/Raises

def download_text(container_name, blob_path, encoding="utf-8"):
    """
    ストレージからテキストをダウンロードして文字列として返す

    Args:
        container_name: コンテナ名
        blob_path: ファイルパス
        encoding: テキストエンコーディング(デフォルト: utf-8)

    Returns:
        str: ファイルの内容

    Raises:
        Exception: ダウンロードに失敗した場合
    """
    client = get_client()
    blob = client.get_blob_client(container=container_name, blob=blob_path)
    return blob.download_blob().readall().decode(encoding)

Google Style Docstringを丁寧に書いています。しかし、型ヒントがあればArgs/Returnsの大半は不要です。container_name: str と書けば「コンテナ名」であることは明白です。

C/Java系のプロジェクトでは、さらにインパクトのあるバージョンを見かけます。

/****************************************/
/* 関数名: get_user_info                */
/* 機能:   ユーザー情報を取得する       */
/* 引数:   user_id - ユーザーID         */
/* 戻り値: 0:正常 / -1:異常            */
/* 作成者: 山田                         */
/* 作成日: 2024/06/15                   */
/****************************************/
int get_user_info(int user_id) {

関数の上に「仕様書」を丸ごと書くスタイルです。Google Style Docstringはこの装飾枠をなくしてモダンにしたものですが、根っこの発想は同じです。どちらも「関数名を見ればわかること」を別の言語(日本語)で繰り返しています。(さらに言えば、この仕様書コメントの閉じ位置やインデントが正しくない、というだけで従来のレビューでは指摘を受けたりしていました。本質ではない装飾にレビューの時間が使われていたのです)

あるある4(良い例): 規程への参照コメント

# 契約社員・派遣社員に管理者以上は禁止(権限管理規程 第5章2項)
if employment_type in ("契約社員", "派遣社員") and permission_type in ("admin", "privileged"):
    results.append(RuleResult(
        status=Status.NG,
        description="権限管理規程 第5章2項: 管理者以上の権限を付与してはならない",
    ))

これは消すべきではないコメントです。なぜなら、「契約社員に管理者権限を付与してはならない」というビジネスルールは、コードの構造からは読み取れないからです。しかも規程の章・項まで参照先が明記されています。

あるある1〜3は「何をしているか(What)」の説明です。あるある4は「なぜそうしているか(Why)」の記録です。

この違いが、AI時代に決定的に重要になります。

AI時代に何が問題か

問題1: コンテキストの無駄な消費

AIにはコンテキストウィンドウ(一度に読める量)の上限があります。日本語コメントが大量にあると、その分だけ「AIが本質的な処理に使える注意力」が減ります。

さらに厄介なのが、日本語はトークン効率が悪いという事実です。200万以上の翻訳文ペアを分析したCJK言語のトークン効率調査によると、日本語は英語の平均2.12倍のトークンを消費します。

コード内のコメントで比較してみましょう。

テキスト トークン数(GPT-4o) 倍率
# Download from storage 4
# ストレージからダウンロード 9 2.25倍

カタカナが1〜2文字単位で細かく分割されるのが主な原因です。あるある1のようなステップ番号コメントが関数ごとにあると、ファイル全体で数百トークンの浪費になります。

ただし誤解しないでください。「だから英語でプロンプトを書け」と言いたいわけではありません。英語が読み書きできるならそれに越したことはありませんが、そうでなければ日本語で読み書きできるようにAIエージェントへ指示するほうが生産的です。これは「認知負荷」の話であり、本記事のテーマからは外れるため深くは触れません。

問題2: 古いコメントがハルシネーションの種になる

コメントが多いほど、この「地雷」も比例して増えます。あるある3のような詳細なdocstringほど、改修時に更新が漏れやすく、AIへの誤誘導リスクが高くなります。

問題3: Whyがないと検証が浅い

よくあるコミットメッセージとPRの記述を見てみましょう。

commit: バグ修正
PR:     〇〇を実装しました

これをAIにレビューさせても、返ってくるのは「コードスタイルは問題ありません」程度です。

なぜこの方法? なぜこの範囲? なぜ今?

この「Why」が記録されていないと、AIは表面をなぞることしかできません。あるある4の規程参照コメントがAIにとって有用なのは、まさに「Why」が書かれているからです。

改善してみた

改善1: コード自体が語る書き方へ

あるある1〜3を改善するとこうなります。

def upload_csv_to_agent(
    client: OpenAIClient,
    container: str,
    blob_path: str,
    download: Callable[[str, str], str],
) -> tuple[str, str]:
    """Upload a CSV from blob storage to the OpenAI Files API."""
    content = download(container, blob_path)

    tmp = tempfile.NamedTemporaryFile(mode="w", suffix=".csv", delete=False)
    tmp.write(content)
    tmp.close()

    with open(tmp.name, "rb") as f:
        uploaded = client.files.create(file=f, purpose="assistants")

    return uploaded.id, tmp.name

変えたこと:

  • 関数名が意図を語る(upload_fileupload_csv_to_agent
  • 型ヒントがドキュメント代わり(Callable[[str, str], str] → 引数の型と返り値が明白)
  • docstringはWhyだけ1行(何をする関数かは名前でわかる)
  • インラインコメント: ゼロ

ステップ番号コメントの # 1. # 2. # 3. を消しても、コードの読みやすさは変わりません。上から順に「ダウンロード → 一時保存 → アップロード」と読めます。

改善2: Whyの分離先を作る — インストラクションファイルが実質ADR

ADR(Architecture Decision Records)とは、設計判断とその理由をMarkdownで記録する仕組みです。docs/adr/NNN-タイトル.md に置き、Context → Decision → Consequencesの構造で書きます。

しかし、正式なADRをいきなり導入するのはハードルが高いかもしれません。

筆者は、インストラクションファイル(CLAUDE.md)とチーム向けドキュメントがADRの役割を果たせることに気づきました。

たとえば、筆者のプロジェクトの CLAUDE.md にはこう書いてあります。

### エラーハンドリング方針
- 外部API呼び出しは必ずリトライ付きで実装する(最大3回、指数バックオフ)
  理由: 本番環境でAPI側の一時障害による500エラーが頻発し、
  ユーザーに不要なエラー画面が表示されていた(2026/02 障害対応)
- ただし、認証エラー(401/403)はリトライせず即座にエラーを返す
  理由: リトライしても回復しない。トークン期限切れの場合は
  再認証フローに遷移させる必要がある

これは立派なADRです。Decision(リトライ付きで実装する)とContext(なぜそうするか=本番障害の経験)とConsequences(ただし認証エラーは除外する)が含まれています。

同様に、設計判断の記録にはこういうエントリがあります。

### typing.Listではなく組み込みlist[]を使う
- 事実: AIが `from typing import List, Dict` を使ったコードを生成した。
  Python 3.9以降では非推奨だが、レビューで見落とされた
- 判断: CLAUDE.mdに「Python 3.10+の型ヒント記法を使うこと」を明記。
  AIが古い書き方を出力しても、インストラクションで上書きされる

この記録があることで、AIは次回から非推奨の書き方を避けるようになります。正式なADRでなくても、「判断の理由」が構造化されて参照可能な場所に置いてあることが本質です。

改善3: コミットとPRに「背景の記録」を

コミットメッセージのBefore/Afterです。

Before:

バグ修正

After:

fix(user): 退職済みユーザーが有効扱いされる問題を修正

退会済みユーザーのis_activeフラグが未チェックだったため
課金処理が実行されていた。
参照: docs/policy/account-lifecycle.md

Conventional Commits形式で書くと、fix feat refactor などのプレフィックスだけでAIが変更の性質を判別できます。

PR記述には4つの要素を入れます。

要素 内容
What 何を変えたか(1行)
Why なぜ変えたか + 関連ドキュメントへのリンク
How どう実装したか(差分の補足)
Impact 影響範囲と確認済み事項

改善4: AIレビューにWhyを問わせる

AIへのレビュー依頼にも、効く依頼と効かない依頼があります。

効かない依頼:

このPRをレビューして

→「コードスタイルは問題ありません」で終わります。

効く依頼:

リポジトリ全体と関連ドキュメントを読み込んだ上で、
このPRを以下の観点で検証してください:

1. account-lifecycle.mdとの整合性
2. 課金モジュールへの副作用
3. 退会後30日間のエッジケース
4. この実装への疑問点

問題点・改善提案・承認可否を明確に回答してください。

「不思議に思う点を挙げろ」というフレームが、AIの検証力を引き出します。ただし、これが機能するのはWhyが参照可能な場所に記録されている場合だけです。ADRもPR記述もないリポジトリでは、AIも浅い検証しかできません。

明日から何を変えるか

一気にやる必要はありません。

Step 1: まずここから

  • 関数名・変数名を英語で明確にします(get_userfind_active_user_by_id
  • 「コードを読めばわかるコメント」を書かないようにします
  • 型ヒントを入れます(Python 3.10以降なら int | None 記法が使えます)

Step 2: PRとコミットにWhyを書く

  • Conventional Commits形式を導入します(fix: feat: refactor:
  • What / Why / How / Impact の4要素をPRに書きます

Step 3: インストラクションファイルにWhyを蓄積する

  • CLAUDE.md やCopilot Instructions、.cursorrules などにチームのルールと理由を書きます
  • 「なぜこのルールがあるのか」をセットで記録します
  • フィードバックや失敗事例も構造化して残します

Step 4: AIレビューにWhyを問わせる

  • レビュー依頼に「関連ドキュメントを読んだ上で」を入れます
  • 「不思議に思う点を挙げろ」のフレームを使います

まとめ

レイヤー 何を語るか
コード What(何をしているか)を構造で語る
コメント 最小限のWhy(ビジネスルール・規程参照)だけ残す
インストラクションファイル チームのWhy(ルールの理由・過去の失敗)を蓄積する
PR / コミット 変更のWhy(なぜ今この変更か)を記録する
AIレビュー Whyとの整合性を検証する

「コメントを減らせ」という話ではありません。Whyの届け先を変えるということです。

日本語コメントを山ほど書いてきた丁寧さは、弱みではありません。「理解しようとする姿勢」は、AI時代でもエンジニアの強みです。その丁寧さを、AIにも届く場所に届ければ、人間もAIも、あなたのコードをもっと深く理解できるようになります。

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?