← Posts

AIにコードを書かせるほど、設計を考えなくなっていた


はじめに

こんにちは。 2025年中盤からClaude Codeやcopilot等のエージェントツールが目まぐるしく進化し、コーディング作業はかなり楽になりました。 一方で、AI漬けの日々に疲れを感じることも増えてきて、休日くらいはAIデトックスして純粋にプログラミングを楽しんだほうがいいんじゃないかと思っています。

この記事では、AIエージェントに開発の舵を渡してしまっていた自分が、ペアプロをきっかけに「自分の意思で設計する」ことを取り戻した話を書きます。

AIに任せていた頃

エージェントってどういう使い方されてます?

私はというと、フレームワークのベストプラクティスをなんとなく拾ってきて読み込ませ、AI側にコーディングの規約や構造を判断させてレビューや開発をしていました。レガシー環境のプロジェクトでは、読み込ませる工程すら省いていたと思います。

自分でレビューや調整はしていたので、大きく意図と違う状態になることはあまりありませんでした。でも「なんか違う・・・」と感じたことは何回もあって、その度にまぁこんなもんやろとAIの評価をしていました。

今思えば、「自分はこう作りたい」が無い状態でAIに書かせていたので、出力の良し悪しを判断する基準がそもそも無かったんですよね。

転機 ― ペアプロで突きつけられたこと

AIに対する評価が180度変わったのは、0→1開発にアサインされた時のことでした。

バックエンド開発が主な内容で、私ともう一人の開発メンバー、そしてメンター兼レビュワーとして2人の先輩エンジニアという体制で進めていました。0→1開発の経験が浅く、開発期限にも余裕がなかったため、「設計思想は作りながら確立して、まずは動くものを」をベースに開発を進めていきました。

暫くして、歴が倍以上ある先輩エンジニアのTさんからペアプロの提案がありました。 正直、開発は進んでいるしスケジュールに間に合わせたい。悠長にリファクタリングしている暇は無い、と思っていました。

しかし、そもそもTさんの思考や技術を盗みたいと思ったからこのチームへの移籍願いを出したのだと思い出し、ペアプロを受けることにしました。

「このコード、どんな意思があって書いた?」

ペアプロでTさんによく言われたのはこういうことでした。

たとえば、あるAPIからのレスポンス変換処理をServiceクラスに書いていた時、「なんでここに置いたの?」と聞かれました。正直、明確な理由はなく「なんとなくServiceだから」としか答えられませんでした。

振り返ると、今まで自分がやっていたのは、バグが起こっていないか、先方から言われた仕様通りに動いているか、それだけでした。思想や自分の考えは基本無視して、どれだけIssueをこなすかだけを考えていた。そしてそれが評価に直結していたため、PRが通る=これでいいんだという感覚になり、「なぜこう書くのか」を考えるという当たり前のことを、いつの間にか忘れていました。

思想を整理する ― 設計ドキュメントを書いた

ペアプロを経て、私は現在のアーキテクチャ構造を選定した理由を細かい粒度で説明できるようにしようと決めました。各設計判断のメリット・デメリットとプロジェクトのドメインロジックから、設計のテーマを整理してTさんにも確認していただきながらドキュメントに落とし込みました。

なぜMVCでもクリーンアーキテクチャでもないのか

最初に向き合ったのは「なぜこの構造なのか」という問いでした。

どちらも「ダメ」ではなく、このプロジェクトには合わないという判断です。そこで、Modelの責務をUsecase/Serviceの2層に分離する方針を採用しました。

プレゼンテーション層 → ユースケース層 → サービス層

この構造なら、今後ビジネスロジックが複雑化してもユースケース層は「サービスの呼び出し順序」だけを管理するので、コードがシンプルに保たれます。新しい処理はサービス層に追加し、ユースケース層で差し替えるだけ。改修時のバグリスクも抑えられます。

迷ったポイント:サービス間のDIを禁止した理由

設計を整理する中で特に迷ったのは、サービス同士の依存をどうするかでした。

ServiceAからServiceBを呼びたい場面は当然出てきます。でも、それを許可するとサービス間の依存関係がスパゲッティ化して、どこで何が呼ばれているか追えなくなる。結局「サービスはサービスをコンストラクタで受け取らない(サービス間のDI禁止)」というルールにしました。

サービス間で処理を共有したい場合は、ユースケース層で両方のサービスを呼び出して組み立てる。こうすれば処理の流れはユースケース層を見れば全て分かります。

メソッドの分類ルール

サービス層のメソッドは以下の3種類に分類するルールも定めました。

この分類があると、メソッドを見た瞬間に「これは何をする処理か」が分かります。レビューする側も楽になりますし、AIにレビューさせる時も判断基準が明確になります。

:::details 当時作成した設計ドキュメントの全文

各層の責務

プレゼンテーション層

ユースケース層

サービス層

主要なコンポーネント

DTO

依存性の管理

コーディング規約

層の責務

サービス

例外処理

バリデーション

インジェクション

頭が整理されると、手が止まらなくなる

思想を整理し、ルールを定義し、ドキュメントに記載することで予想外のメリットがありました。リファクタリングの作業効率が格段に上がったのです。

ドキュメントを書く過程で「ここはこうする」「ここはこの理由でこうしない」を一つずつ決断しているので、頭が整理された状態でコードに向き合えます。以前は「この処理、どこに置くべきだろう」と毎回迷っていたのが、自分の定めたルールに沿って判断するだけになりました。

AIエージェントとの組み合わせがいい

そしてこれは副産物でしたが、設計ドキュメントを整備したことでAIエージェントの出力品質が劇的に変わりました。

AIエージェントが自分の思想を基に実行してくれるため、出力の再現性がかなり高くなります。「なんか違う」がほぼ無くなりました。

レビューをさせても、ドキュメントを正としてレビューしてくれるので、プロジェクトに沿わない提案はほとんどしなくなりました。以前は「ベストプラクティス的にはこうすべき」という一般論を提案されて困ることがありましたが、設計思想が明文化されていればAIもそれに従います。

つまり、AIが違和感のあるコードを提供していた原因は、AIの性能ではなく、自分が舵を持っていなかったことだったのです。

まとめ

アーキテクチャの決定を蔑ろにすること=意思の放棄、とまでは言いません。 ただ、今後エンジニアとして生き残るために大切なのは、AIに流されず「自分はなぜこう作るのか」を考え続けることではないでしょうか。

もし今、なんとなくAIの出力を受け入れている感覚があるなら、まずは今のプロジェクトで一つだけ試してみてください。「なぜこの構造にしたのか」をREADMEやドキュメントに1段落書いてみる。 それだけで、AIとの関係が変わり始めると思います。 私の場合はアーキテクチャ設計がきっかけでしたが、手段は何でもいいと思います。命名規則でも、テスト方針でも、コードレビューの基準でも。大事なのは、自分の意思で「なぜこうするのか」を言語化することです。 自分の思想や意思を放棄しないでください。