Devin を使って API + フロントを一括実装してみたメモ(ACU 4$分)
はじめに
Devinを個人プロジェクトで使ってみた感想を「まだ使ったことのない人向け」に書いてみたいと思っています。
個人的には「意外と使えるかも?」という感想です。
個人プロジェクトと追加したかった機能
実際にどう使ったかというと、本当に個人的なツールで技術記事をいい感じに集めて読めるようにするWEBアプリを趣味で作っているのですが、そこに 1 つ追加したい機能がありました。
集めた記事をDBで管理して「お気に入り機能」と「既読機能」を持たせていて、小規模なので機能数も少ないのですが、未読一覧とお気に入り一覧という 2 つのフロントページがあります。
未読一覧からは既読にしたらその記事が消えてほしい(API から取得できなくなる)と考えていました。
技術記事で気になったもの、特に自分が試した系の記事は Twitter に上げたり会社の Slack の雑談チャンネルに投げたりと共有したくなります。本当にその記事からインスピレーションをもらって実際に試すことも多いので、お気に入りは「あとでアーカイブしておきたい」用途です。
一方で「最近読んだ記事」も表示したいと思い、過去 3 日間に読んだ記事リストのページを考えていました。簡単な機能ではありますが、API もフロントエンドも用意しなければならず、1〜2 週間ほど Issue にしたまま寝かせていました。
Devin 導入前の懸念
そんな折、Devin が 20 ドルのプランを出したと聞きました。ただ、ざっくり読んだ記事では「数件程度のタスクしか任せられない」とあり、成果が出る前に枠を使い切りそうだと感じていました。前評判としてタスク遂行能力があまり高くないという話もあり、契約せずにいました。
Devin を試したきっかけ
ところが、クラスメソッドさんの記事で「最近の Devin は改良され、タスク遂行能力も上がっている」と知り、「じゃあ試してみるか」と始めました。
Devinの設定
GitHub のモノレポ(自分のツールのリポジトリ)に対して権限を付与し、オンボーディング設定を軽く済ませました。普段からClineやCursorを使っているので、そのままclineruleに書いている内容を流用し、省エネ設定で開始しました。
GitHub・Slack・Devinで連携できるよう個人 Slack に権限を渡しておきました。
最初の小手試し
まずはフロントエンドの色を変える程度のとても簡単なタスクを任せてみたところ、わずか 0.3$ でやってくれました。
Issue に書いて、そのリンクを Slack に貼り付けてメンションすると、Issueのコメントを読んで理解し、進めてくれる感じです。
本命の機能追加
Devin の20$のプランで利用枠が 9 $分あるので、当初やりたかった「最近読んだ記事一覧」ページを作らせてみようと思いました。
前評判では「いきなり自由度高く任せると大量の ACU を消費した上に微妙な成果物になる」と聞いていたので、まずは自分が考えている機能の構想・要件を Markdown で言語化しました。Clineを使ってタスク分解も実施しました。
- API を作成し、このディレクトリにサービスを置き、このルートを追加する
- 次にフロントエンドにページを作る
といった ToDo リスト形式で書き、それを GitHub にプッシュしました。(ドキュメントもMarkdownでプロジェクトに含めるようにしています。)
以下のようなMarkdownを作りました
# 最近読んだ記事一覧ページ
## イメージ
- 直近3日間で読んだ記事をそれぞれのセクションに分けた形で表示する機能
- 3日あれば土日を挟んだとしても共有できる
- 専用のページを実装
## 利用シーン
- 最近読んだ記事の中から社内共有するパターン
- Xへの投稿へ
- お気に入り機能で代替していた、共有待ちの記事を移行して明確に
## APIの実装
- routeにエンドポイントを追加 `/recent`
- repositoryでデータを取得
- 日別で構造的なデータを返したい。日毎にセクションしたいため。
- serviceで組み立て
- 各自のテストコードをtests/unit以下に追記
## フロントエンドの実装
- `/recent`でページを追加
- Cardコンポーネントはそのまま利用する
- 日別で分割して表示する
- Headerにリンクを貼る
## 拡張機能
影響なし
## ドキュメント運用
- アプリケーション実装後に`docs/機能仕様`内に資料作成する
## 実装タスク
### 1. APIの実装 (基礎)
#### 1-1. データ取得の実装
- [ ] `api/src/repositories/bookmark.ts`にデータ取得メソッドを追加
- 直近3日間の記事を取得するSQLを実装
- 取得したデータを日付でグループ化
#### 1-2. サービス層の実装
- [ ] `api/src/services/bookmark.ts`にロジックを追加
- repositoryから取得したデータを整形
- 日付ごとのセクションデータ構造を定義
#### 1-3. APIエンドポイントの追加
- [ ] `api/src/routes/bookmarks.ts`に`/recent`エンドポイントを追加
- GETメソッドの実装
- serviceを呼び出してデータを返却
### 2. APIのテスト実装
#### 2-1. リポジトリのテスト
- [ ] `api/tests/unit/repositories/bookmark.test.ts`にテストを追加
- データ取得メソッドのテスト
- 日付によるグループ化のテスト
#### 2-2. サービスのテスト
- [ ] `api/tests/unit/services/bookmark.test.ts`にテストを追加
- データ整形ロジックのテスト
- エッジケース(データなし等)のテスト
#### 2-3. ルートのテスト
- [ ] `api/tests/unit/routes/bookmarks.test.ts`にテストを追加
- エンドポイントの動作テスト
- レスポンス形式のテスト
### 3. フロントエンドの実装
#### 3-1. ページの作成
- [ ] `frontend/src/app/recent/`ディレクトリを作成
- [ ] `page.tsx`を実装
- 基本的なページレイアウト
- データ取得ロジックの実装
#### 3-2. コンポーネントの再利用と実装
- [ ] 既存の`BookmarkCard`コンポーネントの再利用
- [ ] 日付セクションを表示するコンポーネントの作成
- セクションタイトル
- カード一覧の表示
#### 3-3. UIの改善
- [ ] `frontend/src/components/Header.tsx`に新規ページへのリンクを追加
- [ ] レスポンシブデザインの適用
- [ ] ローディング状態の実装
### 4. ドキュメントの作成
#### 4-1. 機能仕様書の作成
- [ ] `docs/機能仕様/最近読んだ記事一覧/`ディレクトリを作成
- [ ] 以下のドキュメントを作成:
- 01_概要.md
- 02_API仕様.md
- 03_フロントエンド仕様.md
Devin の作業プロセスとコミュニケーション
改めて実装用の Issue を切り、コメントに「ドキュメントのこのファイルに要件定義とタスクを書いてあるので、この通り進めてほしい」と書きました。そして Issue のリンクを Slack で Devin にメンション付きで投げました。
↓Devin向けに作成したIssue
↓SlackででIssueを伝えている様子です。
すると 15 分ほどで作業を進めてくれました。途中、不安になって「今どう?」と聞くと「問題なく進行中です」と返答。
しばらく待つとプルリクを作ってくれました。GitHub Actionsで API のテストを自動実行しているのですが、追加した分のテストは成功。後から足りなければ自分で手を入れればいいかな、というレベルでした。
↓Devinが自動的に作ってくれたプルリクエストです。
ただ、Lint は失敗していたので「npm run format
を実行してみて」とPRにコメントすると、Slack で反応し、そのままフォーマットを適用してくれました。レビューコメントを書いても自動的に拾い、Slack で回答したり修正してPR更新してくれました。
機能実装をまるっと任せて、こちらの苦労が要件の言語化程度だったのでかなりいけるなという感想です。
感想
実装に 15 分ほどかけている間、自分は並行して別タスクを進められ、とても都合が良かったです。定義した機能を 1 つの Issue で、API とフロントエンドを含む機能追加までやってくれるのは想像以上に「やるじゃん」という感じでした。消費したACUは5$分程度です。
ということで、思っていた以上にタスク処理能力が高いのかもしれない、というのが今回の感想です。参考になれば幸いです。
紹介リンク
Discussion