🙆

ChatGPTのみでFlutterアプリ作ってみる

2023/03/26に公開

結論

最初に結論を述べますが、ChatGPTのみでアプリを作るのは諦めました。
進めていくうちに不整合が発生したりするので、普通にデバッグは必要になります。(当たり前)
プロンプトの精度をあげればあげるほど、デバッグ作業は減ると思われるので、そこが肝になるという考えに至っています。

具体的にどのレベル感のものだと、どの程度の出力が出てくるかの指標になればなと思います(´・ω・`)
※最下部の追記にも記載しましたが、機能面という意味ではほぼ問題ないものが生成されていました。バリデーションの類をGitHub Copilotをなどで補完してあげればそれなりのものが出来ますね。

概要

前々から家族からお願いされたことを忘れまくってしまうので、GPT-4メインでネイティブアプリ作れるかやってみる。
プロンプトデザインとかよくわかっていない段階で試してみて、理想とのギャップをまずは把握する。

アプリについて

家族間で利用するものを想定しています。リリースするかも未定。
経緯としては、嫁に怒られないために自分用に作るというものが目的です(´・ω・`)

  • ユーザーグループ内で、特定のユーザーに対してタスクとリマインド間隔を送信する。
  • 受信側のユーザーには特定指定されたリマインド間隔でPUSH通知を飛ばす。
  • FlutterとFirebaseでやってみる。(両方業務で使ったことない)

プロンプト

※どういうプロンプトを投げるのが最適なのかについて情報収集はあまりしていません。
しっかりと設計せず、頭で思いついた順番でフローをGPTちゃんに食べさせてあげました。

- [Goal]:
- 複数ユーザー間で選択した相手に対し、定期的にPUSH通知するアプリを作成する。
- ユーザー1がユーザー2に対して連絡したい内容を入力。PUSH通知の頻度も併せて設定してリクエストを送信する。データベース上に情報を格納する。
- ユーザー2はリマインダー頻度に合わせてPUSH通知を受け取る。
- ユーザー2はアプリケーション上で内容を確認。対応が完了したら対応済みとしてアプリケーション上で完了を選択する。
- 使用する技術はFlutter。状態管理はRiverpod。プラットフォームはFirebase。データベースはFireStore。PUSH通知はFirebase Cloud Messaging。
- データベースの特定カラムを監視し、特定カラムがfalse(フラグが立っていない)であれば、Cloud Function for Firebaseを起点としてPUSH通知を送信する。
- 生成したファイルすべてに対し、ソースコードのサンプルを出力する
- Command
- [C1]:
- Goalを選成するために必要なことをStep by Stepで1つづつ実行していけるように手順:[P#]に分解して下さい。
- [Output style] :
[P1]=
....
[P#]=
....
[P(END}]=

GPTちゃんの返事

しゅごい...どういう順番で何をすればいいのかを教えてくれる...(´・ω・`)
雑に投げてもかなりいい感じに整理してくれるのすごいんだけど...(´・ω・`)

[Output style]:

[P1]= プロジェクトのセットアップ: Flutterプロジェクトを作成し、必要なライブラリを追加します。
[P2]= データベース設計: Firestoreのデータ構造を設計します。ユーザーデータ、リマインダーデータ、およびフラグ情報を含めます。
[P3]= 認証機能の実装: Firebase Authenticationを使用して、ユーザー登録・ログイン機能を実装します。
[P4]= ユーザー情報の登録・取得機能の実装: Firestoreを使用して、ユーザー情報を保存・取得する機能を実装します。
[P5]= リマインダー設定画面の実装: ユーザーがリマインダー内容と頻度を設定できる画面を実装します。
[P6]= リマインダーリクエストの送信・保存機能の実装: ユーザー1がリマインダーリクエストをユーザー2に送信し、Firestoreに保存する

pu purupuru
続き
機能を実装します。
[P7]= リマインダー表示画面の実装: ユーザー2がリマインダー内容を確認できる画面を実装します。
[P8]= リマインダー対応済み機能の実装: ユーザー2がリマインダー対応を完了した際に、Firestore上のフラグ情報を更新する機能を実装します。
[P9]= Firestoreの特定カラムの監視: Firestore上のフラグ情報を監視するCloud Functionを実装します。
[P10]= PUSH通知の送信機能の実装: Cloud Functionでフラグ情報がfalseの場合に、Firebase Cloud Messagingを使用してPUSH通知を送信する機能を実装します。
[P11]= PUSH通知の受信機能の実装: Flutterアプリ側でPUSH通知を受信する機能を実装し、リマインダー内容を表示します。
[P12]= 状態管理の実装: Riverpodを使用して、アプリケーションの状態管理を行います。
[P13]= アプリケーションのテスト: 実装した機能の動作

pu purupuru
続き
を確認するためのテストを実施します。
[P14]= UI/UXの最適化: ユーザーインターフェイスとユーザーエクスペリエンスを最適化します。
[P15]= アプリケーションのデバッグ: 不具合やエラーを修正し、パフォーマンスを向上させます。
[P16]= ドキュメント作成: アプリケーションの使用方法や開発に関するドキュメントを作成します。
[P17]= ソースコードのサンプル出力: 生成されたファイルすべてに対して、ソースコードのサンプルを出力します。
[P(END)]= アプリケーションのデプロイ: 完成したアプリケーションを適切なプラットフォームにデプロイし、ユーザーに公開

pu purupuru
続き
します。

これで、複数ユーザー間で選択した相手に対し、定期的にPUSH通知を送るアプリの開発手順が完成しました。これらの手順に従って、アプリケーションを一つずつ実装し、テストしていくことで、目標を達成できます。

NoSQLの設計について聞いてみる

NoSQLの設計したことないからよくわからんのよなあ...聞いてみるか。

pu purupuru
P2の具体的な設計について教えてください。
P2のデータベース設計について具体的な説明をします。

Firestoreのデータ構造では、コレクションとドキュメントを使用してデータを保存します。このアプリケーションでは、以下のコレクションとドキュメントを設計します。

usersコレクション: ユーザー情報を格納します。

ドキュメントID: 各ユーザーの一意なID (Firebase Authenticationで生成されるUIDを使用)
Fields:
displayName (string): ユーザーの表示名
email (string): ユーザーのメールアドレス
createdAt (timestamp): ユーザー登録日時
remindersコレクション: リマインダー情報を格納します。

ドキュメントID: 各リマインダー

pu purupuru
続き
の一意なID (Firestoreで自動生成されるドキュメントIDを使用)

Fields:
senderId (string): 送信者ユーザーの一意なID (Firebase AuthenticationのUID)
receiverId (string): 受信者ユーザーの一意なID (Firebase AuthenticationのUID)
content (string): リマインダーの内容
frequency (string): 通知の頻度 (例: "daily", "weekly", "monthly" など)
nextNotificationAt (timestamp): 次回の通知日時
isCompleted (boolean): リマインダーが対応済みかどうかを示すフラグ (true: 対応済み, false: 未対応)
createdAt (timestamp): リマインダー作成日時
この設計に従って、usersコレクションにはユーザー情報が

pu purupuru
続き
格納され、remindersコレクションにはリマインダー情報が格納されます。リマインダー情報は送信者と受信者のユーザーIDを含むことで、誰が誰に対してリマインダーを送信したかを特定できます。また、リマインダーの内容、通知の頻度、次回の通知日時、対応済みフラグ、および作成日時も保持されます。

このデータ構造を使用して、アプリケーションはリマインダーを作成、送信、表示、更新できます。また、Cloud Functionで特定のドキュメント(リマインダー)のisCompletedフラグを監視し、falseの場合にPUSH通知を送信することができます。

優秀すぎませんかねこの子(´・ω・`)
ちなみにですが、Pxxのソースコードを出力してくださいとお願いすると、対応するファイルを出力してくれます。
※載せると冗長になるので割愛します。

ログイン周り

それっぽい画面は出てきました。(registerへの遷移が無かったのでボタンを手動で追加)
Firebase側での設定ができていれば大丈夫でした。個人的に触ったことなかったので、ちょこちょこした部分は自分で調べました。(GPTちゃんに聞いても微妙な回答が返ってきたので)
ちゃんと画面設計をして、ルーティング関連も指示してあげれば一発でログイン、登録フォームは出力されそうですな。

でもいまどきSNSでの認証ないのださいよねということでGoogle認証の導入方法を聞いてみたんですが、
PaaS側の設定作業など、アップデートが激しいものに関してはちゃんと取捨選択をした方が良さそうですね。
普通に?記事を探して対応しました。

ただ、Google認証のサンプルコードください。に対して返答されたコードは問題なく動いたので、そういう使い分けするのがいいかも(´・ω・`)

ユーザーデータ周り

FIrestore設定

さっき出力してもらった設計通りにコレクション作っていきます。(NoSQLってこんな感じなんだというお気持ち)
通知の頻度はdailyなどではなく、xx時間単位やxx分単位を想定していたので、型をstringではなく、numberにしておきたいなと思った。
なので以下のように問い合わせ。

ここで問題発生

reminder_model.dart、add_edit_reminder_page.dartは今までのフロー中で出力されていないファイルです。
ただ、類似ファイルであろうものは出力しているので、いったんスルーしようと思います。
どういう経緯でこうなってしまったかは定かではないですが、一連の流れのものを完全に記憶させるには今のやり方だと不適切なんだと思われます。(この辺りは色んな情報を漁りたいところです)

home_page.dart中にはfrequencyの記載がなかったり、段々雲行きが怪しくなってきました。

いざ再ログイン

Authenticationには無事登録されたのでログイン試してみたらデータ無いよっていうエラー出てきた。

ソース確認するとFIrestoreのusersを確認してからコンテンツ表示決定してそうなので、そこのソース書いてもらうことにする。
そうすると、*repository.dartが生成されたので、最初にどういった設計パターンでアプリケーションを構成していくかは定義してあげないとダメそう。
※*service.dartというファイルがいくつか出力されているのだが、そこから直接firestoreを叩きにいっているファイルがある。いまいちっすよねえ。

以前作成した記事で、設計パターンを指定してあげた際にはそれっぽいものを出力してくれたので大丈夫なはず。

user_repository.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';

class UserRepository {
  final FirebaseFirestore _firestore;

  UserRepository({FirebaseFirestore? firestore})
      : _firestore = firestore ?? FirebaseFirestore.instance;

  Future<void> saveUser(User user) async {
    await _firestore.collection('users').doc(user.uid).set({
      'displayName': user.displayName,
      'email': user.email,
      'photoURL': user.photoURL,
    });
  }

  Future<DocumentSnapshot> getUser(String uid) async {
    return _firestore.collection('users').doc(uid).get();
  }
}

いきなり総括

この辺りで色々と不整合が起きてきたので全部を担ってもらうことを諦めました(´・ω・`)
いちいちこの辺を指示していくのは不毛なので(´・ω・`)

  • 過去に出力したファイルとそもそも内容が違う。
  • インターフェースの定義が異なっている。

とはいえ、ある程度のプロンプトさえ準備すればそこそこ使える大枠は作ってくれることはわかったので、新しい技術を導入するときとかには使えそうですね。(copilotの言語変換と組み合わせてどこまでいけるかは試してみたい)

将来的にはこの辺りもライブラリとかプラグインとかでラップされるような気はするけど、細かいユースケースに対応するには自分で学習しておかないといけないですしね。

今回の検証で作ったものについては、ちょこちょこデバッグすれば動くものにはなりそうなので、個人学習として進めていこうかなと思います。

必要な要素が段々見えてきたのでもう少し精度を上げていきたいところです。

0327追記

  • AuthenticationとFirestoreの繋ぎ込みはFirestoreのセキュリティポリシーで解決
  • reminderを作成する箇所については特に問題なく動作。
    • サービス設計の詳細をプロンプトに渡していないので、フィールド自体はおかしいが、プロンプト次第かなと思う。
  • Firestoreのフィールドの修正と、Cloud Functionsの設定さえ終われば動きそうかなという印象。
    • 機能面はほぼ問題なし。
  • iOSもandroidのデベロッパーではないので、一旦検証はここまでにします(´・ω・`)

Discussion