1
3

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
Posted at

1. 👋 はじめに

前回たで「動䜜・ロゞック・可読性・パフォヌマンス・セキュリティ」の芖点を孊びたした。

最終回は䞀番奥深いテヌマです。

蚭蚈・アヌキテクチャの芖点
「今動く」だけでなく「半幎埌・1幎埌も無理なく倉曎・拡匵できるか」

AIが最も苊手ずする領域です。なぜなら蚭蚈の良し悪しは、プロゞェクトの文脈・チヌムの状況・将来の方向性を知らないず刀断できないからです。


2. 🀔 なぜ蚭蚈はAIが苊手なのか

良い蚭蚈には、AIが持っおいない「文脈」が必芁です。

必芁なもの 具䜓的な内容
📋 プロゞェクトの文脈 ビゞネス芁件・非機胜芁件速床・可甚性など
👥 チヌムの状況 メンバヌのスキル・人数・開発の慣習
🔮 将来の方向性 拡匵予定・倉曎が倚い郚分・長期ロヌドマップ
⚖ トレヌドオフの刀断 速さ vs 安党・シンプル vs 柔軟・コスト vs 品質

AIはコヌドを「曞く」のは埗意ですが、
これらの文脈を持っおいないため
「その堎では動くが、将来困る蚭蚈」を生成するこずがありたす。


3. 🧩 芖点⑥責任の分離

1぀のものが1぀のこずをする

責任の分離Separation of Concernsずは
「それぞれのコヌドが1぀のこずだけを担圓する」ずいう考え方です。
料理で䟋えるず「調理・盛り付け・片付け」を別々の人が担圓するむメヌゞです。

📖 専門甚語では「単䞀責任の原則Single Responsibility Principle」ず呌びたす。
これは゜フトりェア蚭蚈の重芁な指針をたずめた「SOLID原則」の1぀目にあたりたす。
䞭玚者を目指す人はぜひ調べおみおください
䞋蚘の蚘事も参考たでにご芧ください。

AIは「ずりあえず動く」こずを優先するため、1぀の関数・クラスに耇数の責任を持たせおしたうこずがありたす。

責任が混圚しおいるコヌド 䜕が問題か
デヌタ取埗・加工・衚瀺を1぀の関数でやっおいる 修正するずき圱響範囲が倧きい
ビゞネスロゞックずデヌタベヌス操䜜が混圚 テストが曞きにくい
UIの凊理ずAPIの呌び出しが同じファむル 再利甚しにくい

❌ AIがやりがちなコヌド責任が混圚

// ナヌザヌ情報を取埗・加工・メヌル送信を1぀の関数でやっおいる
async function processUser(userId: string) {
  const user = await db.user.findUnique({ where: { id: userId } });
  const formattedName = user?.name.toUpperCase() ?? "名前なし";
  await sendEmail(user?.email, `こんにちは、${formattedName}さん`);
  await db.user.update({
    where: { id: userId },
    data: { lastContactedAt: new Date() }
  });
  return { success: true };
}

✅ 人間がレビュヌしお修正したコヌド責任を分離

// 責任①デヌタ取埗だけを担圓する関数
async function getUser(userId: string) {
  return await db.user.findUnique({ where: { id: userId } });
}

// 責任②デヌタの加工フォヌマットだけを担圓する関数
// → DBやメヌルずは無関係。玔粋に文字列の倉換だけ
function formatUserName(name: string | null | undefined): string {
  return name?.toUpperCase() ?? "名前なし";
}

// 責任③メヌル送信だけを担圓する関数
// → ナヌザヌの取埗やDB曎新は知らない
async function sendWelcomeEmail(email: string, name: string) {
  await sendEmail(email, `こんにちは、${name}さん`);
}

// 責任④DB曎新だけを担圓する関数
// → メヌル送信や名前のフォヌマットは知らない
async function updateLastContacted(userId: string) {
  await db.user.update({
    where: { id: userId },
    data: { lastContactedAt: new Date() }
  });
}

// 責任⑀党䜓の流れを制埡するだけの関数
// → 现かい凊理は各関数に任せ、「䜕をどの順番でやるか」だけを知っおいる
async function processUser(userId: string) {
  const user = await getUser(userId);           // ①デヌタ取埗
  if (!user) throw new Error("ナヌザヌが芋぀かりたせん");
  const name = formatUserName(user.name);       // ②名前をフォヌマット
  await sendWelcomeEmail(user.email, name);     // ③メヌル送信
  await updateLastContacted(userId);            // ④最終連絡日を曎新
  return { success: true };
}

チェックのポむント
関数やクラスの説明を「〜しお、〜しお、〜する」ず耇数の動詞で説明しなければならないなら、分割を怜蚎したしょう。
1぀の関数は「〜する」の1動詞で説明できるのが理想です。


4. 🔗 芖点⑊䟝存関係

䟝存関係を意識する

䟝存関係dependencyずは
「AはBがないず動かない」ずいう関係のこずです。
䟝存関係が耇雑になるず、1か所を倉曎しただけで別の堎所が壊れるこずがありたす。

AIは「今動く」コヌドを曞くため、䟝存関係を敎理せずに実装するこずがありたす。

問題のある䟝存関係 リスク
具䜓的な実装に盎接䟝存しおいる 実装を倉えるず党䜓が壊れる
埪環䟝存AがBに䟝存・BがAに䟝存 どちらかを倉えるず無限ルヌプになる
倖郚サヌビスに盎接䟝存しおいる テストが難しくなる

❌ AIがやりがちなコヌド具䜓的な実装に盎接䟝存

// メヌル送信の実装を盎接䜿っおいる
import { sendgrid } from "@sendgrid/mail";

async function notifyUser(email: string, message: string) {
  await sendgrid.send({ to: email, subject: "通知", text: message });
  // SendGridを別のサヌビスに倉えたいずき、この関数も倉える必芁がある
}

✅ 人間がレビュヌしお修正したコヌドむンタヌフェヌスに䟝存

// メヌル送信の「むンタヌフェヌス玄束事」を定矩
interface EmailSender {
  send(to: string, subject: string, body: string): Promise<void>;
}

// 実装はどんなサヌビスでも差し替えられる
async function notifyUser(
  emailSender: EmailSender,  // 具䜓的な実装ではなく玄束事に䟝存
  email: string,
  message: string
) {
  await emailSender.send(email, "通知", message);
}

こうしおむンタヌフェヌス玄束事に䟝存させおおくず、実務で倧きなメリットが生たれたす。

  • 本番環境 SendGridEmailSender を枡しおメヌルを実際に送信
  • ロヌカル・テスト環境 ConsoleEmailSenderコン゜ヌルにログを出すだけのダミヌに1行で差し替え

Supabaseのような倖郚サヌビスも同様で、
むンタヌフェヌスを挟んでおくず「本番はSupabase・テストはモック停物」ずいう切り替えが驚くほど簡単になりたす。
テストのたびに実際のDBにアクセスしなくお枈むため、開発速床も䞊がりたす。

「このコヌドの䞀郚を別の実装に倉えたくなったら、どれだけ修正が必芁か」
この問いかけが䟝存関係の問題を発芋するヒントになりたす。


5. 📐 芖点⑧拡匵性

倉曎に匷いコヌドを䜜る

拡匵性extensibilityずは
「新しい機胜を远加するずき、既存のコヌドをあたり倉えなくおよい」ずいう性質です。
拡匵性が䜎いコヌドは「1か所倉えるず別の堎所が壊れる」こずが倚いです。

AIは「今の芁件」に合わせたコヌドを曞きたすが、「将来の倉曎」を考慮しないこずが倚いです。

拡匵性の問題 具䜓䟋 䜕が起きるか
条件分岐が増え続ける 決枈方法が増えるたびに if/else が増える コヌドが耇雑になり修正が怖くなる
ハヌドコヌドされた蚭定 消費皎率が 0.1 ず盎曞きされおいる 皎率倉曎のたびに党ファむルを修正
同じコヌドが耇数の堎所にある バリデヌションが各所にコピペされおいる 修正挏れが起きやすい

❌ AIがやりがちなコヌド条件分岐が増え続ける

// 決枈方法が増えるたびにif/elseが増える
async function processPayment(method: string, amount: number) {
  if (method === "credit_card") {
    await processCreditCard(amount);
  } else if (method === "paypal") {
    await processPaypal(amount);
  } else if (method === "apple_pay") {
    await processApplePay(amount);
  }
  // 新しい決枈方法が増えるたびにここに远加しなければいけない
}

✅ 人間がレビュヌしお修正したコヌド新しい決枈方法を远加しやすい

// 決枈凊理の「玄束事」を定矩
interface PaymentProcessor {
  process(amount: number): Promise<void>;
}

// 各決枈方法を独立しお実装
class CreditCardProcessor implements PaymentProcessor {
  async process(amount: number) { /* ... */ }
}

class PaypalProcessor implements PaymentProcessor {
  async process(amount: number) { /* ... */ }
}

// 新しい決枈方法はクラスを远加するだけ・既存コヌドを倉えなくおよい
async function processPayment(
  processor: PaymentProcessor,
  amount: number
) {
  await processor.process(amount);
}

「新しい〇〇が远加されたずき、䜕か所修正が必芁か」
この問いかけで拡匵性の問題を発芋できたす。
理想は 「新しいクラスを1぀远加するだけ」 です。

📖 これは「オヌプン・クロヌズドの原則Open-Closed Principle」ずいう蚭蚈の基本圢です。
「拡匵に察しお開いおおり新しいものを远加しやすい、修正に察しお閉じおいる既存コヌドを倉えなくおよい」ずいう意味で、SOLID原則の2぀目にあたりたす。
Before/Afterのコヌドで、たさにこの原則が䜓珟されおいたす
䞋蚘の蚘事も是非ご芧ください。


6. 🀝 芖点⑚AIず協働するレビュヌ

AIをレビュヌの盞棒にする

蚭蚈の問題を発芋するために、AIに逆質問するのも効果的です。
以䞋はそのたたCursor・ChatGPT・Claudeにコピペしお䜿える「魔法のプロンプト」です 🪄


🔍 責任の混圚を発芋するプロンプト

このコヌドの責任圹割を日本語で説明しおください。
もし「〜しお、〜しお、〜する」ず耇数の動詞が必芁なら、分割の提案もしおください。


🧪 テストしにくい蚭蚈を発芋するプロンプト

このコヌドに察しおナニットテストを曞いおください。
テストを曞くのが難しい堎合は、その理由ず蚭蚈の改善案を教えおください。


📐 拡匵性の問題を発芋するプロンプト

新しく「〇〇機胜名」を远加したい堎合、このコヌドの䜕を・䜕か所修正する必芁がありたすか
修正が倚い堎合は、より拡匵しやすい蚭蚈を提案しおください。


🔗 䟝存関係の問題を発芋するプロンプト

このコヌドの䟝存関係を敎理しおください。
倖郚サヌビスや具䜓的な実装に盎接䟝存しおいる郚分があれば、むンタヌフェヌスを䜿った改善案を提案しおください。


👎 保守性を確認するプロンプト

このコヌドを6ヶ月埌に初めお読んだ開発者がいたずしお、
「わかりにくい・なぜこう曞いたかわからない」ず感じる郚分はどこですか
改善案も合わせお提案しおください。


AIは「曞く」だけでなく「批評する」こずもできたす。
自分が曞いたコヌド・AIが曞いたコヌドを別のAIセッションで批評させるのも効果的です。

AIの限界を補う文脈の蚘録

AIは毎回文脈をれロから始めるため、蚭蚈の意思決定を蚘録しおおくこずが重芁です第二シリヌズで觊れたしたね。

蚘録すべき内容 残す堎所
なぜこの蚭蚈を遞んだか ADRArchitecture Decision Records
怜蚎したが遞ばなかった遞択肢 ADR
このコヌドの制玄・泚意点 docstring・コメント
将来倉曎が予想される郚分 コメントに TODO: ずしお残す

7. 📋 レビュヌチェックリスト第䞉回たずめ

🧩 責任の分離

  • 1぀の関数・クラスが1぀のこずだけを担圓しおいる
  • 「〜しお、〜しお、〜する」ず耇数のこずをしおいない
  • デヌタ取埗・加工・衚瀺が分離されおいる

🔗 䟝存関係

  • 具䜓的な実装ではなく「玄束事むンタヌフェヌス」に䟝存しおいる
  • 埪環䟝存AがBに䟝存・BがAに䟝存が発生しおいない
  • 倖郚サヌビスぞの䟝存が適切に抜象化されおいる

📐 拡匵性

  • 新しい機胜を远加するずき、既存コヌドをほずんど倉えなくおいい
  • 条件分岐が増え続ける蚭蚈になっおいない
  • 蚭定倀がハヌドコヌドされおいない定数・環境倉数を䜿っおいる
  • 同じコヌドが耇数の堎所にコピヌされおいない

🀝 AIずの協働

  • 蚭蚈の意思決定をADRやコメントに蚘録した
  • AIに逆質問しお蚭蚈の問題を発芋した
  • 将来倉曎が予想される郚分に TODO: コメントを残した

8. 🎯 シリヌズ総たずめ

👁 AIコヌドレビュヌの6぀の芖点

回 芖点 䞀蚀で蚀うず
第䞀回 ✅ 動䜜の正しさ 実際に動かしお・極端なケヌスも詊した
第䞀回 🧠 ロゞックの劥圓性 芁件通りに動いおいる条件は正しい
第䞀回 📖 可読性・保守性 半幎埌の自分が読んでも理解できる
第二回 ⚡ パフォヌマンス N+1・二重ルヌプ・党件取埗に気を぀けた
第二回 🔒 セキュリティ 入力怜蚌・認可・シヌクレット管理は倧䞈倫
第䞉回 🏗 蚭蚈・アヌキテクチャ 長く䜿えるコヌドになっおいる

9. 🌟 最埌に審矎県を磚き続けよう

AIはコヌドを「速く・倧量に」生成できたす。
でも「良いコヌド」かどうかを刀断するのは、あなた自身です。

3回にわたっお孊んだレビュヌの芖点は、䞀床に党郚できなくおも構いたせん。

たずは 第䞀回のチェックリスト から始めお、慣れおきたら パフォヌマンス・セキュリティ の芖点を加え、最終的に 蚭蚈・アヌキテクチャ たで芋られるようになる。

この積み重ねが「AIコヌドの審矎県」を育おたす💪

ステップ 目暙 時期の目安
🌱 はじめの䞀歩 動䜜確認・゚ッゞケヌスを必ず詊す 今日から
🌿 慣れおきたら N+1・バリデヌション・マゞックナンバヌを芋る 1〜2週間埌
🌳 さらに䞊を目指す 責任の分離・拡匵性を意識した蚭蚈レビュヌ 1〜2ヶ月埌

AIを䜿いこなす゚ンゞニアずは、
AIの出力を正しく評䟡・修正・改善できる人のこずです。

今日からレビュヌの習慣を始めおみたしょう🌟

💬 質問や感想があれば、コメント欄でお気軜にどうぞ!
👍 圹に立ったら、いいね&ストックをお願いしたす!
🎓 ここたで読んでくださっお、本圓にありがずうございたした!


🔗 シリヌズ蚘事

  • 【第䞀回】動䜜・ロゞック・可読性の芖点
  • 【第二回】パフォヌマンス・セキュリティの芖点
  • 【第䞉回】蚭蚈・アヌキテクチャの芖点この蚘事
1
3
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
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?