最近はめっきり、自分の手でアプリのコードを書くことがなくなりました。

もっぱらCodexやClaudeにコードを書かせて、自分は指示を出すだけになっています。

そうなると、プログラムを読み書きできることや、コード全般の専門知識を持つことに、もはや意味はないのではないか、という疑問も出てくると思います。世間的にも「プログラミングはもう終わった」みたいな風潮が出てきている気がします。

確かに、今ではプログラムを読み書きできなくても、ソフトウェアを作れるようになりました。自分でも、コードをほとんど把握せずに、コーディングエージェントにソフトウェアを丸ごと作らせることはよくあります。

しかし、ある程度しっかりとしたソフトウェアを作ろうとすると、コーディングエージェントに実装を書かせるとしても、プログラムに関する知識、特にドメインモデルに関する知識が重要になってくると感じています。

コードの詳細はコーディングエージェントがやってくれる分、むしろドメインモデルを考え、議論することが、ソフトウェアエンジニアの主な仕事になってきているとも言えるかもしれません。

もともとやっていた開発手法

まず、自分はコーディングエージェントが登場する以前から、ドメインモデルを中心にソフトウェアを開発するということを実践してきました。

具体的には、まず大まかな仕様を把握して、主要なドメインモデルを考えます。

例えばメモアプリを作るなら、まず Memo というエンティティがありそうだな、と考える感じです。

それで、「メモはタグによって整理できる」という仕様が出てきたら、今度は Tag というモデルが必要そうだな、と考えます。このとき、Tagをエンティティにするのか、値オブジェクトにするのか、といったことも議論する必要があります。

そして、これらのモデルを使ってアプリを実装し、実際に動かしてみます。

もちろん、最初から完璧な仕様が決まっているわけではありません。アプリを使ってみた結果、仕様を変更したくなることもあります。

そうなったら、仕様に合わせてドメインモデルをアップデートして、実装に反映して、またアプリを使ってみる。

このようなループを回しながら、少しずつソフトウェアを作っていきます。

これはコーディングエージェントが登場する以前から自分が実践していた開発フローで、個人的にはとてもよく機能するものでした。

バイブコーディングだけでは難しくなる

コーディングエージェントが登場したことで、いわゆるバイブコーディングのように、コードをまったく見ず、作りたいものを言葉で伝えるだけでアプリを作る手法も出てきました。

自分もこういう作り方をすることはあります。

ただ、個人的には、これはちょっとしたアプリやプロトタイプを作るには便利でも、本格的にソフトウェアを開発していこうとすると、どこかでドメインモデルをしっかり定義して、それを中心とした開発にシフトしないと効率が悪くなると感じています。

なぜ効率が悪くなるのかというと、ソフトウェアが複雑になるほど、コーディングエージェントに仕様を正しく伝えることが難しくなるからです。

言ってみれば、用語や概念が定義されていないことで、言葉の齟齬が生じ、意図しない仕様が実装に埋め込まれてしまうことが増えてくるという現象です。

例えば、キャラクターとチャットできるソフトウェアを作っていたとします。

そこで「キャラクターがユーザーのことをもっと覚えておけるようにして」と指示したとします。

こちらとしては、ユーザーに関する事実をKey-Value形式で保持できる仕組みを想像していたのに、AIは過去のエピソードを文字列のリストとして記録する仕組みを作ってしまう、みたいなことが起こります。

もちろん、どちらが正しいというわけではありません。そもそも「ユーザーのことを覚える」という言葉自体が曖昧なのです。

人間同士でもこういう認識のズレは起こりますが、AI相手だと、こちらの曖昧な指示をそれらしく解釈して、そのまま一気に実装してしまうことがあります。

しかも厄介なのは、出来上がったものが一見ちゃんと動いてしまうことです。

後から別の機能を追加しようとしたときに、初めて想定していた設計と違うことに気づく、ということもあります。

こうしたことが積み重なると、機能を追加するたびに既存の実装を調べ直したり、設計を修正したりする必要が出てきて、だんだん開発効率が悪くなっていきます。

仕様駆動開発で解決するのか

こうした問題を解決する方法として、最近は仕様駆動開発のようなものも提案されています。

先に仕様書をしっかり書いて、それに従ってコーディングエージェントに実装させるという考え方です。

ただ、自分はこれも、あまり筋のいい解決方法ではないのではないかと思っています。

というのも、結局これは「仕様書を作って、それをコーダーに渡して実装してもらえばいい」という、旧来のソフトウェア開発が抱えていた問題と同じところに行き着く気がするからです。

もちろん、仕様書自体が悪いわけではありません。仕様を明文化することには意味がありますし、特に外部とのインターフェースや、満たすべき条件を明確にするには有効だと思います。

ただ、仕様書を書いて、それを完璧に実装へ反映させればいい、という考え方には限界があります。

それができればいいのですが、現実のソフトウェア開発では仕様は頻繁に変わります。

アプリを実際に使ってみて、やっぱりこうしたい、あの機能はいらなかった、ということは普通に起こります。

そのたびに仕様書と実装の同期を取るというのは、なかなか大変なことです。

しかも、コーディングエージェントは仕様書と実装に矛盾があると、仕様書を優先するべきなのか、現在の実装を優先するべきなのか判断に迷い、結果として変な実装をしてしまうこともあります。(体験談)

詳細な仕様書を維持すること自体が、新しい負担になってしまうわけです。

少なくとも、自分が日々アプリを作りながら仕様を変更していくような開発では、仕様書を中心に据えるよりも、ドメインモデルを中心に据える方がうまくいくと感じています。

ドメインモデルをAIとの共通言語にする

コーディングエージェントを使った開発をだいぶやってきた実感として、今のところ最もうまくいくのは、人間だけでソフトウェアを開発していたときと、基本的には同じことをするという方法です。

つまり、仕様をドメインモデルに落とし込み、そのモデルを使ってアプリを実装し、実際にアプリをレビューする。

仕様が変わったら、ドメインモデルを変更して、再びアプリに反映する。

これを繰り返すわけです。

変わったのは、ドメインモデルやそれを使ったユースケースのコードを書くのが人間ではなくAIになったことです。

さらには、仕様をドメインモデルに落とし込む作業自体も、AIに手伝ってもらえるようになりました。

では、それだったら人間は何をするのか、という話になります。

ここで重要なのは、仕様を適切なドメインモデルに落とし込むという作業は、まだAIが完璧にできるものではないということです。

これはAIの設計能力が足りないという話だけではなく、そもそも人間が頭の中で考えている仕様を、AIに完璧に伝えること自体が難しいという問題だと思っています。

言葉には限界があります。

人間の頭の中にあるイメージを直接脳からスキャンして、そのままモデルに変換するような技術でも出てこない限り、この問題を完全に解決するのは難しいのではないかと思います。

もっとも、そもそも人間自身も、最初から完璧な仕様を知っているわけではないんですけどね。

だからこそ、AIと議論しながらドメインモデルを考え、それを実装して動かし、実際のアプリを見ながら、何を作りたいのかを少しずつ明確にしていく必要があるのだと思います。

そして、一度ドメインモデルが定義できたら、今度はそのモデルを共通言語としてAIとコミュニケーションを取れるようになります。

例えば、先ほどのメモアプリの例で言えば、

「タグは名前を変更したら、そのタグが紐付いているすべてのメモに反映したい。だからTagは独立したIDを持つエンティティとして設計しよう」

といった指示ができます。

この場合、単に「タグの名前を変更できるようにして」と言うよりも、ずっと明確に意図を伝えられます。

Tagがどういう存在で、Memoとどういう関係にあるのかが定義されていれば、AIもその前提に沿って実装を考えられるからです。

また、UIを作るときにもドメインモデルは役に立ちます。

例えば「Memoに紐付いているTagを一覧表示して、Tagの選択でメモを絞り込めるようにして」といった具合に、ドメインモデルをどう表示し、どう操作したいのかを伝えれば、かなり具体的なUIを言葉だけで作れるようになります。

新しい機能を追加するときも、いきなり画面や処理の実装を指示するのではなく、まず既存のドメインモデルにどんな変更が必要なのかを議論できます。

こうして考えると、ドメインモデルは単にコードを整理するための設計ではなく、人間とAIがソフトウェアについて共通認識を持つための仕組みとしても機能しているのだと思います。

コードを書かなくなったからこそ、モデルを考える

もちろん、ドメインモデルを定義すればすべて解決するという話ではありません。

モデル自体が間違っていることもありますし、実装との整合性を保つ必要もあります。

ただ、少なくとも、何も定義されていない状態で自然言語による指示を繰り返すよりも、共通のモデルを持って開発する方が、ずっと安定してソフトウェアを作れるという実感があります。

以前は、自分でドメインモデルを設計して、自分でコードを書いていました。

今は、ドメインモデルの設計もAIと議論しながら進め、実際のコードはほとんどAIに書かせています。

その分、自分は「このアプリにはどういう概念が存在するのか」「それぞれのモデルは何を保持し、どう振る舞うのか」「モデル同士はどう関係するのか」といったことを考える時間が増えました。

コードを書く時間が減ったことで、ソフトウェアの構造そのものについて考える時間が増えたとも言えます。

プログラミングの知識が不要になったというよりも、その知識を使う場所が変わってきた、という感覚に近いです。

以前は自分で正しく実装するために必要だった知識が、今はAIと正しく設計を議論し、AIが作ったものを評価するために必要になっています。

そんなわけで、今のところ自分にとっては、ドメインモデルをAIと共有し、それを共通のコンテキストとしてコミュニケーションを取りながらソフトウェアを作っていくというのが、最もうまくいく開発手法になっています。

今後、AIの能力がさらに上がれば、このあたりも変わっていくのかもしれません。

ただ、少なくとも現時点では、コードを書くことよりも、何をどうモデル化するかを考えることの方が、ソフトウェア開発における人間の重要な役割になってきているのではないかと思っています。