TDDで生成AIに仕様と設計を指示してみました

生成AIでプログラミングするには、コードを導くプロンプトを書きます。テスト駆動開発 (TDD) ではプロダクトコードを導くテストを書きます。それならば、人がテストを書いてAIにプロダクトコードを書いてもらったらどうだろうか。

そう思って実験してみたところ、思ったよりもスムーズに進み、プロダクトコードはほぼすべて生成AIだけで完成しました。プロダクトコードは、私が書いたテストおよび最終的な仕様を満たしています。あくまで所感ですが、以下のような効果がありました。

  • 仕様を満たすプロダクトコードが、短時間で完成した
  • 私が考えた設計意図を、テストを通して実装に繋げられた
  • コードの詳細な理解は、自分で書いたときよりは劣る
  • テストとしての網羅性は不完全。普通のTDDと同程度で、テストが特に多く必要とはならない

テストの網羅性が不完全というのは、網羅的なテストを書かなくても妥当なプロダクトコードができるという意味で、ここではメリットとして取り上げています。

TDDはテストを先に書く (テストファースト) というよりは、テストコードとプロダクトコードを同時に、並行して少しずつ書き足していくアプローチです。小さなテストをひとつ書き、プロダクトコードを少しだけ書き進める。今回の実験でも小さいサイクルで意識して、人間プログラマがテストをひとつ書き、生成AIにプロダクトコードを少し書いてもらうという繰り返しを実践しています。

やってみるなかで、AIを利用したTDDの上手いやり方や注意点もいくつか発見しました。

  • 人が仕様を元にテストを書いてAIにプロダクトコードを生成してもらうと良い
  • 内部設計についてのテストを書いて、設計意図を伝える
  • 生成結果をクリアにイメージできるようにテストを書く。生成結果がイメージと合っているか確認する
  • 生成されたコードが不十分なら、問題を指摘するテストを書く
  • 生成されたコードが理解できなくなったら、後退してからテストと設計を見直す
  • テストが失敗したらチャットでAIに直してもらう。失敗時の実行結果に加えて、問題や対応方針を読み取って伝える
  • テストの整理もAIに頼める。テストの構成がはっきりしていれば、テストの生成も部分的に頼める

今回の実験にあたり、クリエーションライン株式会社からAnthropicのAPIキーを提供していただきました。感謝いたします。なお私 (やっとむ)は、クリエーションライン株式会社をアジャイルコーチとして支援しています (2024年現在)。

お題はLeetCodeのものを改変した、独自のプログラミング課題を用いています。IDECursor、AIモデルはclaude-3.5-sonnet、言語はPythonとpytest、人間プログラマは私です。実験の様子はステップバイステップで記録し、どのようにテストとプロダクトコードを書き進めたか把握できるようにしています。また、生成AI対応IDEであるCursorとClaude3.5 Sonnetモデルの使い方の、説明にもなっていると思います。

資料は長くなってしまったので、Google Documentで読めるようにしました。以下から閲覧できます。

TDD&AIで仕様通りのテストとコードを書いていく - Google ドキュメント

スクラムが上手くいってないなら上手くいってる

スクラムでやっているんですが、問題が多くて、スクラム合わないのかなと思って……」

「問題あるならスクラムが上手くいってますね」

という会話をした。

スクラムをやっていて、いろいろ問題が起きる。スプリントゴールがわからないとか、チームの協力が難しいとか、プロダクトオーナーの権限がないとか。スクラムちゃんとできないなあ、うちには合わないのかなあ、と思う人は多いようだ。

だが、こうした問題が起きているならば、スクラムは正しく機能している。スクラムはチームや組織の問題を検出し、明らかにする仕組みだ。みんなが問題を意識できているなら、上手くいっているわけだ。「うちは〇〇だから、スクラム難しい」と思ったなら、その〇〇を解消できれば仕事がもっと上手くいき、よりよい成果が作れる。

スクラムが上手くいくと、問題が次々に現れる。問題を次々に解消していくと、仕事しやすくなり、コミュニケーションがスムーズになり、チームの能力が向上し、よりよいプロダクトになっていく。チームが成長し、組織が成長し、プロダクトが成長する。これがスクラムが、本当の意味で上手くいっている状態と言える。

ところが、問題を解決する方法をスクラムは教えてくれない。問題を発見すること、モニターすること、解消や改善のために時間を取るべきであることなどはスクラムの一部だが、具体的な解決方法は、それぞれのチームが自分で考えなくてはならない。

「うちは〇〇だ。仕方がない」と思ってしまえば、問題は残り続け、仕事は大変になり、モチベーションは下がり、改善は止まり、スクラムがひっそりと終息する。スクラムをやっていて何も問題がないというのは、実は「(解消できる) 問題はない (けれど解消できない問題が山積み)」という状況であることも、少なくなさそうな気がする。

人間は上手くいっているほうが大体モチベーションが出るし、いい仕事もできる。だから「上手くいってないスクラムがいい」と言われても困るかもしれない。実際には、スクラムは問題や障害を乗り越えるモチベーションを出す仕組みが組み込まれている。改善が目に見えて、仕事が楽になり、困難を解決し、自分たちが成長し、プロダクトがよりよくなる。本当に上手くいくプロセスは、自分たちのものだ。よい仕事をできるようになろう、そのためにスクラムを使おう。

『成長を支援するということ』(リチャード・ボヤツィス メルビン・スミス エレン・ヴァン・オーステン著、高山真由美 和田圭介 内山遼子訳、英治出版)を読みました。

よかった点:

  • 「思いやりコーチング」と称して、個人の夢を実現するために人生・生活全体に向けた関わりを提唱している
  • 「ポジティブな感情を誘引する因子(PEA)」と「ネガティブな感情を誘引する因子(NEA)」の概念を紹介し、両方をバランスよく(=PEA多めに)使うのが重要と説いている
  • インスピレーションを得て、感情を大事にし、持続する活動を生み出すことで理想の人生を目指すという流れを解説している
  • 人との関係性と、頼れる人的ネットワークの構築を勧めている

よくなかった点:

  • 事例が多い。多すぎる
  • 事例の登場人物が「人並み外れた努力家だった医師」「サッカー一家の3姉妹の末っ子」「15年マネジメント業務ののち博士号のため大学院に入学」など、そもそも際だった人の話ばかり
  • 冒頭(2章の終わり)で、自分自身がコーチングを受けて人生が変わったときのことを思い出すよう促されるが、思い出せなかった。この本はコーチ好き、人間好きな人向けと理解してNEAが発動した

よいことが沢山書いてありますが、すべてコーチングというパッケージにまとめられてしまって、利用・活用しにくくてもったいないなあと思いました

本日は「ボードゲーム・パズルプログラミング Advent Calendar 2022 - Adventarアドベントカレンダーへのエントリーです。

asobannについて

新型コロナの影響でワークショップなどに人が集まれないようになってきた2020年から、オンラインのボードゲームサービスhttps://games.yattom.jp/asobannasobann(遊盤)を開発しています。

asobannはボードゲームを遊ぶ環境として、一種の物理エンジン的なアプローチをしています。つまり、ゲーム固有の動きやルールを実装するのではなく、汎用的なカードを並べたり、手札にしたり、ボードを置いてそこにコマを自由に配置したりでき、逆にそれしかできません。同じ頃に活用を始めた、オンラインホワイトボードのMiroなどにも影響を受けています。

ボードゲームを遊ぶだけでなく、自作ゲームを実験したり人に遊んでもらう場としての活用も考えています。自分でも半分教育・半分遊びのゲームを作っており、心理的安全性ゲームボードゲーム『チームで勝て!』なども、asobannでオンライン化しました。『チームで勝て!』はasobann上で開発、テストを主にしています。

asobann上の心理的安全性ゲーム

アーキテクチャと技術スタック

asobannが一番大事にしているのは、アナログゲームを人と一緒に遊んでいる感覚の再現です。カードは1枚1枚、ドラッグで引いてきて手札に並べます。手番を回すときは声を掛け合います(コミュニケーション機能はないので、Zoomなどの併用が必須です)。他の人がカードを選ぶとき、指先が迷っている様子が見えます。

そうしたリアルタイム性のため、Socket.IOを採用してプレイヤー間で状態を共有しています。状態はAWS ECS上にMongoDBを立て、そこで一元管理しつつ、各クライアント(ブラウザ)には動きの差分のみを送信して通信量と処理量を節約しています。

ゲームのコンポーネント(カード、ボード、カウンターなど)はシンプルですが、それでもドラッグする、裏返す、シャッフル、トレイに載せるなどの挙動の実装はそれなりに手間もかかり、複雑化します。テーブル全体の状態をクライアント間で矛盾なく共有するため、状態は操作元のクライアントで変更し、差分をサーバー経由で他クライアントにプッシュし、同時にサーバーが完全な状態をマスターとして保有しておいてクライアントがリフレッシュできるようにしました。おそらく対戦ゲームなどのノウハウが世の中にはたくさんあると思うのですが、手探りで設計、実装しました。

サーバーはPython / Flaskです。サーバーの実装は、ほぼクライアントからの差分を他クライアントに転送し、状態全体を更新・取得するだけの薄っぺらいものになっています。

クライアント(ブラウザ)はJavaScriptで、RE:DOMというごくシンプルなDOM操作フレームワークを使っています。ユーザーの操作(ローカルでもリモートでも)をDOMに反映するのには、独自のフレームワーク的なものをアプリ内で育てながら使っています。コンポーネントをDOMにするのか、それともCanvasで描画するほうがいいのか、あまり考えられておらず、もしかすると自前でCanvasにせっせと描画するほうが、安定するのかなという気もしています。

インフラは自分の勉強のつもりでAWS ECSとAWS CloudFormationを採用して、いちから調べながら実装しました。このへんの顛末は以前に当ブログに書いています

アプリの実装やインフラのコードはGitHubにあります。

github.com

困っていること・これからやりたいこと

まずはパフォーマンスの問題があって、人数が多かったりゲームが複雑(コンポーネントが多い)だったりすると、動きが緩慢になったり同期がおかしくなったりしています。Webソケットが詰まっている気がするのですが、理由があまりつかめていないので再現と原因調査が必要です。再現するための自動テストがなかなか面倒です。以前にも挑戦したのですがいまいち再現できませんでした。

ゲームを一緒にやっている感じを出すための機能も追加したいと思っています。emoteを打てるとか、相手にちょっかいを出せるとか、全体を回転できる(各自自分の正面でテーブルを囲むように見える)とか。

またゲーム開発をasobann上でするための機能を作り込んでいきたいところです。今は手元でJSONを作ってアップロードするだけですが、テーブル上でコンポーネントを編集できるようにしたいなあと考えています。

テスト駆動開発(TDD)のゴール「動作するきれいなコード」について考えてみる

「偉大な書籍は偉大な出だしで始まる。ケント・ベック著『テスト駆動開発』(2003, 2017)はこう始まります。

「動作するきれいなコード」。Ron Jeffriesのこの簡潔な言葉が、テスト駆動開発(TDD)のゴールだ。

テスト駆動開発エバンジェリストとして活躍している、和田卓人さん(t_wada)の講演より引用

セミナー講師やアジャイルコーチの立場で、私もTDDを教えることがよくあります。そんなときはこの言葉を意識しつつ、TDDはあくまでスキル、手法のひとつに過ぎず、本当に求めるべきは動作するきれいなコードなのだと、伝えるようにしています。そのことを説明する補助として、こんな図を作りました。

f:id:yach:20220212100829p:plain

絵を描いてみて気づいたのですが、「動作する(Works)」には2つの側面があります。書いたコードが、書いたつもりの通りに動くこと(Verification)と、期待に応えて働き実際に役立つこと(Validation)は、いずれも動作する様子を現しますが、大きく異なった観点です。仕様書とコードに乖離があったり、クラッシュするようなバグがあったら、Verificationの観点から「動き」ません。ユーザーにとって使えなかったり、資産を毀損するような重大な仕様の穴があったら、Validationの観点から「働き」ません。

そう考えると、動作するきれいなコードは書いた通りに動き、期待通りに働き、同時にきれいでなくてはならない。

TDDは主に開発者やプログラマーの活動です。しかし動作するきれいなコードに関心を持ち、実現したくなる他の種類の人々もいます。顧客、クライアントは働くコードを求めます。テスターやQA担当にとって、動くことが確認済みのコードはありがたいものです。コードを書いた本人以外のプログラマーは、安全に作業できるきれいなコードを好みます。

レッド・グリーン・リファクタリングのサイクルを回しながら、コードが動作する(Verified)かつきれい(Clean)であるようにするのは、プログラマーです。プログラマーがさらに、期待通りに動くか判断できる(Validated)、すなわち今書いているコードの受け取り手の立場にたって判断できる場合もあります。しかしこの判断には、プログラマー以外の人にも関わってもらうべきです。そのことを念頭に置き、図に3種類の人々のラベルを追加しました。開発者、顧客、QA(テスター)です。

f:id:yach:20220212100910p:plain

こちらの図では、人による価値の置き方の違いが見て取れます。プログラマーはコードが動き、きれいであるよう望みます。QA(テスター)はコードが動くことと働くことの両方を検証、確認します。顧客は働くコードを求めます。きれいなコードは顧客にも間接的に価値をもたらします。顧客としては、コードのきれいさには興味がないかもしれませんが、低コスト・短期間で追加変更できるのは嬉しいはずです。変更が安全かつ容易なのは、きれいなコードの特性です。

下側の2つの円が、プログラマーがTDDサイクルで重視する部分です。同時に上側の円、コードが本当に働くかどうかも重視すべきですが、働くか確認(Validate)できる人の助けを得なくては、動作するきれいなコードにはなりません。それぞれの立場の人々がお互いに助け合い、協力して動作するきれいなコードを追求する。その必要があると思い出すのに、この図が役立つよう願っています。

それぞれの立場の人が、TDDのサイクルを越えて一緒に働くわけです。あるいは、TDDサイクルの中で、一緒にモブプログラミングするのはもっと素晴らしいと思います。

この図はワークショップでも、「動作するきれいなコード」にまつわる活動や作業を見つけるために使えます。3つの円を大きく描いて、それぞれ「期待通り働く」「書いた通り動く」「きれい」とラベルをつけます。思いつく作業やタスク、活動、アイデアなどを付箋に書いて、3つの円の当てはまる場所に貼ります。円には重なっている部分があり、ここに付箋を貼れば2つ、3つの円に関係すると示せます。そうして、足らない部分を見つけたり、違う立場の人どうしが協力する仕方を話し合ったり、自分たちの「動作するきれいなコード」を定義したり、改善のアイデアを出したりと、なんでもやりたいことをしてください。

f:id:yach:20220206111449p:plain

さて、この図を示したところで、少しばかり懸念があります。3つの円、働く、動く、きれいという3つがすべて重要だと示しているつもりではあるのですが、人の役割を書き込んだことで勘違いが生じてしまうかもしれません。たとえば、「自分は開発者なので「期待通り働く」かどうかは気にしなくてよい」と思われては、本末転倒です。そうした間違いを避けるため、矢印を2本足した次の図を作りました。

f:id:yach:20220212102158p:plain

正直なところ、この矢印がなにを意味するべきか、まだ自分の中でもまとまっていません。たとえば、こんなふうに言えるとは考えています。

  • 開発者は動く・きれいに責任を持つが、働くかどうかも気にしたい。そのためには顧客と会話したり一緒に作業して、顧客を理解し顧客視点を得たい
  • QA(テスター)は開発者と積極的に関わるとよい。そうすると、開発者がコードをきれいにする考え方を知り、そこからテスト容易性に結びつけたり、テスト観点を見直したりできる

これ以外にも解釈や洞察があるのではないかと思います。この図の矢印について、思いついたことをコメントなどで教えていただけると嬉しいです。もっと言うとここで紹介した図についての感想やコメントもぜひお願いします。

What it takes for TDD to make Clean Code That Works?

"Great books begin with great openings. 'Test-Driven Development' by Kent Beck (2003) begins with this sentence: Clean code that works, in Ron Jeffries' pithy phrase, is the goal of Test-Driven Development (TDD)." (Quoted from talks by Takuto Wada (和田卓人), or t_wada, the TDD evangelist actively working in Japan.)

When I teach about TDD, I always try to stress that TDD is just a skill and that's Clean Code That Works you really want. To supplement this idea, I came up with an diagram.

f:id:yach:20220205114650p:plain

It was interesting to find out that the 'Works' part can be split into two: It works as intended (Verification) and also it works to fulfill expectations (Validation). In other words, code is not broken (Verified) and valuable (Validated). So, it must be validated, verified, and clean to be called as clean code that works.

TDD is chiefly an activity for developers or programmers. But other people also see values in Clean Code That Works. Clients would receive no value if a part of code does not work. Testers will be relieved if code is already confirmed to work. Programmers who need to read and modify someone else's code will feel safer if the code is clean.

In the Red-Green-Refactoring cycle, programmers make sure the code is clean and verified (Green and Refactored.) Sometimes they also know how to validate, i.e. make sure it's valuable to anyone who receive the software. But sometimes other people are required for validation. So, along with Programmer, I add two kinds of people to the diagram: QA (tester) and Client.

f:id:yach:20220205120205p:plain

This version of diagram gives us some ideas of who values what: Programmer want the code verified and clean. QA (tester) make the code validated and verified. Client likes validated and clean code. Maybe clients doesn't care (or doesn't know) about clean code, but they sure value ease of change. Safety and easiness in modification is a great virtue of clean code.

Lower half is usually where programmers put focus with TDD cycle. The diagram will help remembering that validation is also crucial to make sure the code really works. And help from other kind of people is essential to validate programmers' work. Everyone helps each other ― everyone works for each other, outside of TDD cycles. Or, perhaps, everyone participates in TDD cycle as a mob!

It may be a good idea to use the diagram in workshops to gather activities to create Clean Code That Works. Draw three big circles, label them Validate / Verify / Clean. Write down ideas, processes, activities or tasks on sticky notes and then put them into appropriate areas. Find out lacking activities, discuss about collaborative overlaps, define your Clean Code That Works, look for ideas for improvements, or do anything you like to do together.

f:id:yach:20220206111449p:plain

Now I have a worry that the diagram might send a wrong message. It is meant to all three - Validated / Verified / Clean - are important, but someone might read like "I'm a programmer, so validation is none of my business." To mitigate my fear, I made another version of the diagram with two dotted arrows.

f:id:yach:20220205122353p:plain

I'm not really sure what the arrows mean. Maybe I can say like "Programmers are not only responsible for Verification and Clean but also for Validation. To do that, programmers need to collaborate with clients to understand and share client's vision." I'd like to hear what do you think of the arrows, or rather, any versions of the diagram.

オンラインホワイトボードで自己紹介

f:id:yach:20211029134735p:plain

神経の衰弱しない自己紹介」という、オンラインホワイトボードを使ったグループアクティビティを紹介します。初めての人が集まるリモートの場で、アイスブレークを兼ねた自己紹介をするものです。CC-BY 4.0で公開します。(CC-BY 4.0 やっとむ, 合同会社やっとむ屋)

カードに書かれたキーワードを使って、自分の話したいことを語ってもらいます。カードはトランプのように「伏せて」あり、めくって(カード裏をドラッグでどかして)出たキーワードで語るというサプライズ要素もあります。

試してみる用のMiroを公開してます。使い方も書いてあります。お気軽にさわってみてください。

miro.com

気に入ったら、自由に使ってください。同じMiroなら、コピー&ペーストで自分のMiroに貼り付けられます。それ以外でしたらアイデアやテキストの再利用は自由です。

使い方

  1. 参加者1人ずつ付箋に、「今日呼ばれたい名前」と「普段の仕事をひとことで」書き、書けた人から一列に並べる(先頭はファシリテーターや主催者などにする)
  2. 付箋の順に、1人ずつ以下の手順で自己紹介をする。
  3. まず名前と仕事を言い、次にカードを各枠から1枚ずつ選んで、そのことについて語る。「好き」な「ペット・動植物」とか、「自慢」の「趣味」など
  4. すでにめくってあるカードを選んでもよいし、伏せてあるカードをめくってもよい。カードを「めくる」とは、トランプ裏の画像をドラッグして横にずらすこと
  5. 1人の話が長くなる場合などは、ファシリテーターが適宜調整します
  6. 1人ずつ進めるとき、いま誰の順番かわかりやすいよう、イマココの矢印で指し示すのがお勧めです

一番手にファシリテーターが自己紹介して、そのときカードのめくり方を実演すると伝わりやすいです。各枠の一番上の、伏せてあるカードを使います。

カードの枚数は10名程度想定、内容はIT技術者向けです。参加者の人数や性質に応じて適宜追加変更してください。

イデアと背景

お互いを知らないところで自己紹介するのは緊張しがちですが、そこで仕事のことでもプライベートのことでも、その人を知れる話ができると後の時間が楽しくなります(たぶん)。いっぽう、ファシリテーションでありがちな「自分の特技」や「今日のグッドニュース」のようなネタに抵抗を感じたり、緊張が強まったりする人もいます。このアクティビティでは、カードを使ったゲーム感覚でネタを選べ、サプライズも可能で、各人それぞれで安心して楽しめるレベルを調整しやすくなります。

人によって、安心な話題を自分で選びたい人もいれば、サプライズで盛り上がりたい人もいます。めくってあるカードから選んでも、自分でめくってもいいのは、そこの調整の役割があります。プレッシャーを感じている参加者のために、自由に選んでもいいし、1枚めくってもナシにしてめくり直してもいいなどと、ファシリテーターが繰り返し説明するとよいでしょう。場の種類によっては、必ず新たにめくるようにしてもいいかもしれません。

最初からめくってあるカードは、誰でも話しやすくかつネガティブな内容や機微な内容になりにくいものです。自己紹介が億劫な人でも選びやすくしてあります。他のカードは、めくったけれど話しにくいという場合もあり得ます。話しにくい、話せることがない、というときは別のカードをめくり直すか、出ている他のカードを選んでもらいましょう。

冒頭で名前を付箋に書いた順に並べると、比較的話すのに抵抗がない、慣れている人が最初に回りやすく、進行がスムーズになりやすいようです。後に回った人はめくったカードの選択肢が増え、話しやすくなります。

カードの内容はIT技術者向けに作ってありますが、多くは一般的に使えると思います。参加者の属性にあわせて、自由に追加変更してみてください。センシティブな内容につながりかねないものを避けるように意識しています(例: 居住地・出身地、学歴や職歴、○年前なにをしていたか、人生の目標、など)。また話題を選びやすくする意図で、複数の項目を1枚に入れて範囲を広げています。