[ChatGPT Hack] 要件定義から設計・モデリング・プロトタイプ作成。そして Azure への Deploy までを。ChatGPT に作らせた

# はじめに
ChatGPT とは別に Codex にてコード生成の専用モデルが用意されています。それでも、対話で話を前に進められる ChatGPT でもコード生成の能力は相当高いです。
現状のモデルでも、プロトタイプの作成には十分機能します。

この Blog では、その可能性の一端を見てみます。

ChatGPT での Promptの結果を皆さんに共有します。私の試行錯誤の後が見えるかと😊:

https://chat.openai.com/share/53610739-0f10-43a5-95aa-6ed1e098de12

アプリとしての ChatGPT は、このチャットを広く多くの方に共有する機能がついているのがいいですねー。CDN をうまく使っていますよね。見習いたいところです。

Prompt のサンプル。皆さんが直ぐに始められるように:

https://github.com/dahatake/ChatGPT-Prompt-Sample-Japanese/blob/main/Software%20Enginner/%E6%97%85%E9%A4%A8%E3%81%AE%E5%BA%A7%E5%B8%AD%E4%BA%88%E7%B4%84%E3%82%A2%E3%83%97%E3%83%AA%E9%96%8B%E7%99%BA.md

# 注意
ChatGPT が生成したコードを、そのままプロダクション環境で使うのは避けてください。主に以下の理由からです。他にもあると思います。

:::note alert
- ChatGPT には**入力文字数**の制限があります。そのため、大規模システムに必要な100画面や200のテーブル作成などには、まだ対応できないと思います。試していませんが
- 既存の要件などを**そのま** Contents として、つまり、追加のデータとして入力するのは避けてください。OpenAI が学習に使う可能性があります。それを避けるためには APIで呼び出すか、別途 OpenAI の ChatGPT の画面で、学習に使わないという設定をする必要があります。もしくは、情報を抽象化・汎化して、ネットにさらしても問題の無いデータに変換します。
- ChatGPT で生成されるコードは、2021年9月が最終版のデータセットで学習したものです。**パフォーマンス**や**セキュリティ**などで、改善点は多々あると思います。
- **知財**の問題があります。皆さんの所属企業の法務のご担当の方と必ず相談をしてください。
:::

# 利用サービス
インターネット上に似たドキュメントなどがある可能性は低いです。そのため、今回は OpenAI の **ChatGPT をそのまま**使います。
Azure の **Azure OpenAI Service** も是非!

https://learn.microsoft.com/ja-jp/azure/cognitive-services/openai/overview

# 1. 要件定義

システムの要件定義は多岐にわたって本当に大変です。
今回は、ChatGPT の可能性を探るために、ここをサボります😊 今回は「役割」などの Meta Prompt もサボっていますが。精度を上げたい場合は、追加するなど試行錯誤してみてください。

**ユースケース** という言葉で一般的なシステムに必要とされる機能一覧を示します。

Prompt:
```cmd
旅館のお部屋の予約のシステムが必要です。どんなユースケースが考えられますか?
```

出力結果:
```cmd
旅館のお部屋の予約システムを開発する際に考慮すべきユースケースは以下のようになるでしょう：

1. **ユーザー登録**: 初回訪問者は新しいアカウントを作成し、アカウント情報（名前、メールアドレス、パスワードなど）を入力します。

2. **ユーザー認証**: ユーザーはアカウント情報（メールアドレス、パスワード）を使用してシステムにログインします。

3. **部屋の検索**: ユーザーは利用可能な部屋を検索します。これには、日付、人数、タイプの部屋（シングル、ダブル、スイートなど）などのフィルターが含まれる可能性があります。

4. **部屋の予約**: ユーザーは利用可能な部屋を選び、予約します。このプロセスでは、ユーザーは滞在期間、人数、その他の必要情報を提供します。

5. **予約確認**: システムは予約の詳細と合計料金をユーザーに表示します。ユーザーはこの情報を確認し、予約を確定します。

6. **支払い処理**: ユーザーは予約を確定するために支払いを行います。システムはクレジットカード情報を収集し、安全に処理します。

7. **予約確認メールの送信**: 予約が完了すると、システムは確認メールをユーザーに送信します。このメールには予約の詳細、チェックインとチェックアウトの時間、その他の重要な情報が含まれます。

8. **予約の変更とキャンセル**: ユーザーは予約の変更またはキャンセルを行うことができます。これには、滞在期間の変更、部屋タイプの変更、予約の完全なキャンセルなどが含まれます。

9. **フロントデスク用インターフェース**: フロントデスクのスタッフがチェックイン、チェックアウト、予約変更などを効率的に管理できるようにするためのインターフェース。

10. **レビューとフィードバック**: 宿泊が終了した後、ユーザーは宿泊体験についてのレビューを

残すことができます。また、フィードバックを通じてシステムの改善点を提案することもできます。

これらは基本的なユースケースですが、実際のシステムではこれらに加えて、プロモーションや割引の管理、忠誠度プログラムの統合、レポートと分析などの追加機能が必要になることがあります。
```

相変わらず、強すぎますね。
正直、このユースケースだと漏れがあります。特に**決済**はやってほしいですよね。ユースケースとしては、ユーザー登録に含まれているのでしょうが、説明文に漏れがあります。文字として入っていないと、おそらく対象外となってしまうでしょう。

それでも、プロトタイプには十分ですので、これで進めましょう。

# 2. ドキュメント作成 - 特にダイアグラム

ChatGPT のお陰で **Mermaid Live Editor** を使う人も増えたのではないでしょうか? 私もその一人です😊

https://mermaid.js.org/#/

もし、あまりご存じでない方は、まずは、この [Sample Diagrams] を見て何が出来るかを確認してください。ChatGPT も [Sample] で学んだ方が早いです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108143/84c0d254-c985-dbc1-c73b-6822e1cd61b8.png)

## 2.1. データモデル

私はデータからアプリ開発を始める癖があります。画面からでもいいと思います。この画面とデータがアプリ開発の両輪で。その間をプロセスというか、フローというか、コードで埋めていきますよね。

まずは、先のユースケースから、**データモデル**を作成させましょう。

Propt:
```cmd
素晴らしい!
それでは、これらのユースケースをシステムとして実現するために、どの様なデータモデルが考えられますか? Mermaid live editor で表示できる書式で作成してください。
```

「素晴らしい!」は、無くてもいいんですけどね😅

出力:
Markdown 表記のため、一部補正しています。**close**を追記しています😅。これ以降の出力のPromptでも同様です。:
```cmd
旅館の予約システムのデータモデルを設計する際には、以下のようなエンティティとそれらのリレーションシップを考慮する必要があります。

1. **User**: 顧客情報を保持します。名前、メールアドレス、パスワードなどのフィールドが含まれます。

2. **Room**: 部屋の情報を保持します。部屋のタイプ、定員、価格などのフィールドが含まれます。

3. **Reservation**: 予約の情報を保持します。予約したユーザー、予約した部屋、予約期間、人数、支払い状況などのフィールドが含まれます。

4. **Payment**: 支払い情報を保持します。支払い額、支払い方法、支払い状況などのフィールドが含まれます。

5. **Review**: レビュー情報を保持します。レビューを書いたユーザー、レビューの内容、レビューの評価などのフィールドが含まれます。

これらのエンティティをMermaidで表現すると以下のようになります：

````mermaid
erDiagram
  User ||--o{ Reservation : makes
  User ||--o{ Review : writes
  Room ||--o{ Reservation : contains
  Reservation ||--o{ Payment : has
  Reservation }o--|| Review : has
````[close]

ここでは以下のリレーションシップを表現しています：

1. ユーザーは一つ以上の予約を作成する（User makes Reservations）。
2. ユーザーは一つ以上のレビューを書く（User writes Reviews）。
3. 一つの部屋は一つ以上の予約に含まれる（Room contains Reservations）。
4. 一つの予約は一つの支払い情報を持つ（Reservation has Payment）。
5. 一つの予約は一つのレビューを持つことができる（Reservation has Review）。

このモデルは基本的なもので、実際のシステムでは更に詳細なエンティティやリレーションシップを追加することがあります。例えば、割引コードの管理、忠誠度プログラム、スタッフの管理などの機能が必要になる場合があります。
```

Markdown だとその使い勝手が分かりづらいので、スクリーンショットの一部分を掲載します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108143/6c5c901e-e9aa-26f1-e6c8-6b41e2238834.png)

Mermeid の部分を Mermaid Live Editor に貼り付けると、以下の様なダイアグラムを作成してくれます。マジ素晴らしい!!!

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108143/b9bef7d6-24db-b17e-7d31-505a7b90576a.png)

## 2.2. サンプルデータ作成

データの大きな器は作りました。テーブルみたいなものですね。ここでは NoSQL でも話が通じるように **エンティティ** と表現されています。

勿論、漏れがありますが、このまま進みましょう。

Prompt:
```cmd
エンティティのデータの例を表形式で出力してください。
```

出力:
```cmd
以下に各エンティティのデータの一例を表形式で示します：

1. **User**

| User ID | Name      | Email           | Password |
|---------|-----------|-----------------|----------|
| 1       | Yamada    | yamada@mail.com | ******** |
| 2       | Suzuki   | suzuki@mail.com | ******** |
| 3       | Tanaka   | tanaka@mail.com | ******** |

2. **Room**

| Room ID | Room Type | Capacity | Price per Night |
|---------|-----------|----------|-----------------|
| 1       | Single   | 1        | 8000 yen        |
| 2       | Double   | 2        | 15000 yen       |
| 3       | Suite    | 4        | 30000 yen       |

3. **Reservation**

| Reservation ID | User ID | Room ID | Start Date | End Date | Number of Guests |
|---------------|---------|---------|------------|----------|------------------|
| 1             | 1       | 2       | 2023-06-01 | 2023-06-03 | 2              |
| 2             | 2       | 3       | 2023-06-10 | 2023-06-15 | 4              |
| 3             | 3       | 1       | 2023-07-01 | 2023-07-05 | 1              |

4. **Payment**

| Payment ID | Reservation ID | Amount   | Payment Method | Payment Status |
|------------|----------------|----------|----------------|----------------|
| 1          | 1              | 30000 yen| Credit Card   | Paid           |
| 2          | 2              | 150000 yen| Debit Card    | Paid           |
| 3          | 3              | 32000 yen| Bank Transfer | Pending        |

5. **Review**

| Review ID | Reservation ID | User ID | Review Text                 | Rating |
|-----------|----------------|---------|-----------------------------|--------|
| 1         | 1              | 1       | Good service and clean room| 4      |
| 2         | 2              | 2       | Loved the room, great view | 5      |
| 3         | 3              | 3       | Room was a bit small       | 3      |

この表は一例であり、実際のデータベース設計では、より詳細なフィールド（例えば、ユーザーの住所や電話番号、部屋の詳細な説明や写真、予約の総料金など）が含まれることがあります。
```

エンティティに**アトリビュート**、つまり**列**が作成されて。かつ、3行ずつですが、**サンプルデータ**も作成されています。サンプルデータは、正直言えば何でもいいですよね。日本語にはしてもらいたいですけどね。それも Prompt で指示すれば動くかもしれません。

## 2.2.1. エンティティの修正
このサンプルだと、**パスワード**を自分たちで管理する必要があります。プロトタイプですから、それでもいいのかもしれません。ですが、プロトタイプの実施で外部の方に参加をお願いするのであれば、これは避けたいですね。一般の方に参加をお願いする場合、普段使いの大事なパスワードを選択してしまう方もいるかもしれません。それを管理するリスクは避けたいです。
ここでは、Facebook や Twitter などのアカウントでログイン出来るようにして、データモデルを変更しましょう。

Prompt:
```cmd
ログインは、自分たちでお客様のログイン情報を持ちたくありません。メールやソーシャル連携などで実現したいです。その際のユースケースやデータモデルでは、どんな変更をしたらしいですか?
```

出力:
```cmd
ログイン情報を自社で管理したくない場合、ソーシャルログイン（Facebook、Googleなど）やメール認証（Magic Link）などのサービスを使用することが一般的です。これらのサービスは、OAuthやOpenID Connectなどの認証プロトコルを使用してユーザーの認証を担当します。

**ユースケース**

1. **ソーシャルログイン**: ユーザーはFacebook、Googleなどのソーシャルアカウントを使ってログインできます。これらのサービスはユーザーを認証し、認証されたユーザー情報をシステムに提供します。

2. **メールログイン（Magic Link）**: ユーザーはメールアドレスを入力します。システムはそのアドレスに一時的なログインリンクを送信します。ユーザーはそのリンクをクリックすることでログインできます。

**データモデル**

ユーザーエンティティは以下のように変更されます：

| User ID | Name      | Email           | Provider      | Provider ID |
|---------|-----------|-----------------|---------------|-------------|
| 1       | Yamada    | yamada@mail.com | Google        | 123456      |
| 2       | Suzuki   | suzuki@mail.com | Magic Link    | N/A         |
| 3       | Tanaka   | tanaka@mail.com | Facebook      | 789012      |

ここで「Provider」は認証サービスを提供するエンティティ（Google、Facebook、Magic Linkなど）を指し、「Provider ID」はそのプロバイダーが提供する一意のユーザーIDを指します。Passwordフィールドはなくなります。

これにより、ログイン情報の管理が外部サービスに委ねられ、システム自体はユーザーの認証情報を保持せずに済むようになります。これはセキュリティを強化し、ユーザーのプライバシーを保護する上で有益です。

```

いいですね!
ソーシャルログインや、メールでのマジックリンクなど、認証を自分たちで持たない方法についても解説してくれています。そして、やりたかった、データモデルの変更をしてくれ。なおかつ、サンプルデータも変更してくれています。

変更結果とその影響が分かりやすいですね。

## 2.3. 画面作成

画面も作らせましょう。
文字出力が用意である Web 画面、つまり HTML を前提にします。確実に動きそうですからね。

Prompt:
```cmd
このシステムにはどんな画面が必要ですか? リストアップしてください。
```

出力
```cmd
旅館の予約システムには、以下のような画面が必要になるでしょう：

1. **ホームページ**: システムのメイン画面で、サービスの紹介、利用可能な部屋の一覧、お知らせなどが表示されます。

2. **ユーザー登録画面**: ユーザーが新規にアカウントを作成するための画面です。ユーザー名、メールアドレス、パスワードなどを入力します。

3. **ユーザーログイン画面**: ユーザーが既存のアカウントでログインするための画面です。メールアドレスとパスワード、またはソーシャルログインオプションを入力します。

4. **部屋検索画面**: ユーザーが利用可能な部屋を検索するための画面です。日付、人数、部屋のタイプなどを指定します。

5. **部屋詳細画面**: 選択した部屋の詳細情報（写真、設備、料金など）を表示する画面です。

6. **予約画面**: ユーザーが部屋を予約するための画面です。予約期間、人数、その他必要情報を入力します。

7. **予約確認画面**: 予約の詳細と合計料金を確認し、予約を確定する画面です。

8. **支払い画面**: 予約の支払いを行う画面です。クレジットカード情報などを入力します。

9. **予約完了画面**: 予約が成功したことをユーザーに通知する画面です。

10. **ユーザー予約一覧画面**: ユーザーが過去に行った予約の一覧を表示する画面です。

11. **予約詳細画面**: 各予約の詳細情報を表示する画面です。

12. **レビュー画面**: ユーザーが宿泊体験についてレビューを書く画面です。

13. **フロントデスク管理画面**: フロントデスクスタッフがチェックイン、チェックアウト、予約変更などを管理するための画面です。

これらの画面は基本的なもので、具体的な要件に応じて追加または変更されることがあります。
```

ステキ過ぎますね!😍

既に、この数になると、過不足の確認が直ぐには出来ませんね。普段から、お部屋や物品の予約・管理システムを作っている方であれば直ぐにわかるのかもしれませんが。私には無理です😅
こういう時には、やはり**図**が理解を助けてくれますよね。

Promopt:
```cmd
ユーザーが操作する画面の画面遷移図を Mermaid live editor で処理できる書式で作成してください。
```

出力:
```cmd
Mermaidを用いて作成したユーザー操作画面の画面遷移図は以下のようになります：

```mermaid
stateDiagram-v2
    [*] --> ホームページ: 開始
    ホームページ --> ユーザー登録画面: ユーザー登録
    ホームページ --> ユーザーログイン画面: ログイン
    ユーザー登録画面 --> ユーザーログイン画面: 登録後ログイン
    ユーザーログイン画面 --> ホームページ: ログイン後
    ホームページ --> 部屋検索画面: 部屋検索
    部屋検索画面 --> 部屋詳細画面: 部屋選択
    部屋詳細画面 --> 予約画面: 予約する
    予約画面 --> 予約確認画面: 予約確認
    予約確認画面 --> 支払い画面: 支払いへ
    支払い画面 --> 予約完了画面: 支払い完了
    予約完了画面 --> ホームページ: ホームに戻る
    ホームページ --> ユーザー予約一覧画面: 予約一覧を見る
    ユーザー予約一覧画面 --> 予約詳細画面: 予約詳細を見る
    予約詳細画面 --> レビュー画面: レビューを書く
    レビュー画面 --> ユーザー予約一覧画面: 完了後戻る
    ユーザー予約一覧画面 --> ホームページ: ホームに戻る
    ホームページ --> [*]: 終了
```[close]

この画面遷移図は、ユーザーがシステムを操作する際の主なフローを示しています。具体的な要件によっては、追加の画面や遷移が必要となる場合があります。
```

スクショがこちら。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108143/23604c36-611b-5de2-ad8b-a06f0327c885.png)

さ、これも Mermaid Live Editor にコピペして、作成されたダイアグラムの確認をしてみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108143/eb6dde1d-6456-bf2d-4b17-de8990fd8a15.png)

マジで、神です!😍
画面遷移図を作ってくれました。これはプロトタイプとしては十二分に大丈夫なのではないですかね!!!

# 3. プロトタイプ

画面の一覧が、画面遷移図で出来ました。データモデルも出来ました。これで、HTMLとデータの一覧は出来そうです。
それでは、プロトタイプの実装に入りましょう。

## 3.1. データの実装 - 構造化データとして。要はテーブルですな😊

今回はデータベースは Azure SQL Database を使います。多くの方が Relational Database であれば理解しやすいと思っているからです。

https://learn.microsoft.com/ja-jp/azure/azure-sql/database/sql-database-paas-overview?view=azuresql

ちなみに、私個人の強い推奨としては。Azure のアプリケーションが使うデータベースは Azure Cosmos DatabaseのSQL API を強く推奨します。

JAZUG の Azure 12周年イベントでお話させていただいたスライドです。

https://www.slideshare.net/dahatake/jazug12-azure-cosmos-db

Prompt:
```cmd
先ほどのデータモデルを Azure SQL Database に実装します。テーブル作成のSQL文と、サンプルのデータを登録するSQL文を作成してください。サンプルデータは3件以上作成してください。データは日本語でお願いします。
```

出力:
```cmd
以下に、Azure SQL Databaseにて使用するテーブル作成SQLとサンプルデータの登録SQLを示します。

まず、テーブル作成のSQL文です：

```sql
-- Userテーブル
CREATE TABLE User (
    UserID INT PRIMARY KEY,
    Name NVARCHAR(50),
    Email NVARCHAR(50),
    Provider NVARCHAR(50),
    ProviderID NVARCHAR(50)
);

-- Roomテーブル
CREATE TABLE Room (
    RoomID INT PRIMARY KEY,
    RoomType NVARCHAR(50),
    RoomDescription NVARCHAR(200),
    Price DECIMAL(10, 2)
);

-- Reservationテーブル
CREATE TABLE Reservation (
    ReservationID INT PRIMARY KEY,
    UserID INT,
    RoomID INT,
    CheckInDate DATE,
    CheckOutDate DATE,
    NumberOfGuests INT,
    FOREIGN KEY (UserID) REFERENCES User(UserID),
    FOREIGN KEY (RoomID) REFERENCES Room(RoomID)
);
```[Close]

次に、サンプルデータを登録するSQL文です：

```sql
-- Userテーブルにサンプルデータを追加
INSERT INTO User (UserID, Name, Email, Provider, ProviderID) VALUES (1, N'山田', 'yamada@mail.com', 'Google', '123456');
INSERT INTO User (UserID, Name, Email, Provider, ProviderID) VALUES (2, N'鈴木', 'suzuki@mail.com', 'Magic Link', NULL);
INSERT INTO User (UserID, Name, Email, Provider, ProviderID) VALUES (3, N'田中', 'tanaka@mail.com', 'Facebook', '789012');

-- Roomテーブルにサンプルデータを追加
INSERT INTO Room (RoomID, RoomType, RoomDescription, Price) VALUES (1, N'シングル', N'シングルベッド1台', 8000.00);
INSERT INTO Room (RoomID, RoomType, RoomDescription, Price) VALUES (2, N'ダブル', N'ダブルベッド1台', 12000.00);
INSERT INTO Room (RoomID, RoomType, RoomDescription, Price) VALUES (3, N'ツイン', N'シングルベッド2台', 15000.00);

-- Reservationテーブルにサンプルデータを追加
INSERT INTO Reservation (ReservationID, UserID, RoomID, CheckInDate, CheckOutDate, NumberOfGuests) VALUES (1, 1, 2, '2023-06-01', '2023-06-03', 2);
INSERT INTO Reservation (ReservationID, UserID, RoomID, CheckInDate, CheckOutDate, NumberOfGuests) VALUES (2, 2, 3, '2023-06-04', '2023-06-06', 2);
INSERT INTO Reservation (ReservationID, UserID, RoomID, CheckInDate, CheckOutDate, NumberOfGuests) VALUES (3, 3, 1, '2023-06-07', '2023-06-09', 1);
```close

このSQLは一例であり、実際の適用には要件に応じた改変が必要になります。また、データベースの設計には正規化、インデックス設定、パフォーマンスチューニングなど、さまざまな要素が考慮されます。
```

サンプルデータ登録用の SQL文も追加してくれるのが便利ですよね! Prompt の中で、作らせた方がいいんですよ。

Entity Framework を使っている人は少ないかもしれませんが... そういうライブラリ・パッケージも活用できますよね。

## 3.2. 画面の作成

さ、次に画面を作りましょう。画面は HTML で作成します。

Prompt:
```cmd
アプリケーションは SPAのWebアプリケーションにします。Webクライアント側は、Reactを使います。Webサーバーは C# で実装します。
先ほどのユースケースの以下の画面のコードを書いてください。
- ユーザー登録画面
```

出力:
```cmd
ReactとC#を用いたユーザー登録画面の実装について解説します。

まず、React側の実装を行います。このコードは一例であり、CSSスタイルやバリデーション、エラーハンドリングなどは省略しています。

```jsx
// UserRegistration.js
import React, { useState } from 'react';
import axios from 'axios';

const UserRegistration = () => {
    const [email, setEmail] = useState('');

    const handleSubmit = async (event) => {
        event.preventDefault();
        try {
            const response = await axios.post('/api/user/register', { email });
            // 登録成功時の処理
            console.log(response);
        } catch (error) {
            // エラーハンドリング
            console.error(error);
        }
    };

    return (
        <div>
            <h1>ユーザー登録</h1>
            <form onSubmit={handleSubmit}>
                <label>
                    Email:
                    <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} required />
                </label>
                <button type="submit">登録</button>
            </form>
        </div>
    );
};

export default UserRegistration;
```[close]

続いて、C#側のコードを実装します。こちらも一例であり、データベースへの接続やエラーハンドリングは省略しています。

```csharp
// UserController.cs
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;

namespace YourApp.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class UserController : ControllerBase
    {
        // ユーザー登録
        [HttpPost("register")]
        public async Task<ActionResult> RegisterUser([FromBody] UserRegisterModel model)
        {
            // ユーザー登録のロジックを書く
            // 例えば、データベースにユーザー情報を保存するなど

            return Ok();
        }
    }

    // モデルクラス
    public class UserRegisterModel
    {
        public string Email { get; set; }
    }
}
```[close]

上記のコードは、ユーザーからの入力（ここではメールアドレス）を受け取り、サーバー側にデータを送信し、サーバー側でそのデータを処理するという基本的な流れを表しています。ただし、このコードは最小限のものであり、実際のアプリケーションでは、入力バリデーション、エラーハンドリング、セキュリティ対策など、さらに多くの要素を考慮する必要があります。
```
Ractと、それとやり取りをする サーバー側のコードのサンプルが出来ましたね!
よく見ると ToDo 的な漏れがご丁寧にコメントアウトされていますね。

その前に。
画面が無いと操作が面倒なので。HTML 部分を作らせましょう。

Prompt:
```cmd
ユーザー登録画面の HTML コードを書いてください。先ほどの Reactのファイルを参照してください。
```

出力:
Markdown 表記のため、一部補正しています。```**close**を追記しています😅:
```cmd

先ほどのReactコードを参考に、以下にユーザー登録画面のHTMLコードを記述します。ただし、Reactで実装した非同期処理やステート管理はHTMLとJavaScriptだけでは直接表現できないため、ここではHTMLと基本的なJavaScriptを用いたサンプルを提示します。具体的な非同期処理の実装は、サーバーサイドとの通信方法や使用するライブラリ等によります。

```html
<!DOCTYPE html>
<html>
<head>
    <title>ユーザー登録</title>
</head>
<body>
    <h1>ユーザー登録</h1>
    <form id="registerForm">
        <label>
            Email:
            <input type="email" id="email" required />
        </label>
        <button type="submit">登録</button>
    </form>

    <script>
        document.getElementById('registerForm').addEventListener('submit', function(event) {
            event.preventDefault();
            var email = document.getElementById('email').value;
            
            // TODO: 非同期処理（サーバーへのPOSTリクエスト）を実装する
            // fetchやaxios等のライブラリを用いる
        });
    </script>
</body>
</html>
```[close]

このコードでは、ユーザーがフォームを送信したときに発火する`submit`イベントをJavaScriptで捕捉しています。その際に`event.preventDefault()`を呼び出すことで、フォーム送信によるページ遷移を防ぎ、代わりに自前の非同期処理を実行します。具体的な非同期処理の内容はTODOコメントとして記述していますが、通常はここでfetch APIやaxios等のライブラリを用いてサーバーへのPOSTリクエストを行います。


```

コメントアウトしている ToDo の部分も作らせちゃいましょう!

Prompt:
```cmd
素晴らしい!
先ほど作成したユーザー画面に、その前に作成した、React のコードを呼び出す部分を追加してください。
```

出力:
Markdown 表記のため、一部補正しています。```**close**を追記しています😅:
```cmd
HTML内でReactコードを使うためには、Reactとその依存関係（Babel、React-DOMなど）をCDNから読み込み、BabelによってJSXを変換する必要があります。以下に示すコードは先程のユーザー登録画面をReactとJSXで書き直したものです。

しかし、実際のプロダクション環境では、このようにCDNからライブラリを読み込む代わりに、WebpackやCreate React Appなどのツールを使用してコードをバンドルし、ビルドされたファイルをサーバーから提供することが一般的です。また、このコードでは非同期通信部分は未実装であることに注意してください。

```html
<!DOCTYPE html>
<html>
<head>
    <title>ユーザー登録</title>
    <script src="https://unpkg.com/react@17/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
    <div id="root"></div>

    <script type="text/babel">
        class UserRegistration extends React.Component {
            constructor(props) {
                super(props);
                this.state = {email: ''};

                this.handleChange = this.handleChange.bind(this);
                this.handleSubmit = this.handleSubmit.bind(this);
            }

            handleChange(event) {
                this.setState({email: event.target.value});
            }

            handleSubmit(event) {
                alert('A email was submitted: ' + this.state.email);
                event.preventDefault();
            }

            render() {
                return (
                    <div>
                        <h1>ユーザー登録</h1>
                        <form onSubmit={this.handleSubmit}>
                            <label>
                                Email:
                                <input type="email" value={this.state.email} onChange={this.handleChange} required />
                            </label>
                            <button type="submit">登録</button>
                        </form>
                    </div>
                );
            }
        }

        ReactDOM.render(
            <UserRegistration />,
            document.getElementById('root')
        );
    </script>
</body>
</html>
````[close]

このコードは、ユーザーがフォームを送信すると現在のメールアドレスをアラートとして表示します。本来はここで非同期通信を行い、サーバー側にメールアドレスを送信すべきです。具体的な非同期通信の実装方法は、使用するライブラリ（例えばaxiosやfetch APIなど）によります。
```

元々の jsxファイルで設定した**UserRegistration**クラスを使っていますね! そのファイルへの参照設定が欠けているように見えますが。それでも、軽微な修正で動くようになりそうです。

DBへの登録部分が不足していましたからね。それも作らせちゃいましょ!

Prompt:
```cmd
C#のコードに、ユーザー登録のロジックを追加します。
先ほど作成した Azure SQL Databaseの User テーブルにデータを登録するコードを追加してください。
```

「C#のコード」という聞き方は具体的じゃないですね。クラスが定義されていたら、そのクラス名で指定したいところ。ま、いいでしょー今回は。

出力:
Markdown 表記のため、一部補正しています。```**close**を追記しています😅:
```cmd
まず、ADO.NET を使って SQL Server に接続し、データを登録する基本的なコードを以下に示します。ここでは `SqlConnection` と `SqlCommand` クラスを使用して SQL Server に接続し、INSERT文を実行します。

このコードを Azure Functions の HttpTrigger 関数内に組み込むことで、HTTPリクエストを受け取った際にデータの登録を行うようにします。HttpTrigger 関数は特定のHTTPリクエスト（GET、POSTなど）をトリガーとして動作し、ここではPOSTリクエストを受け取ってユーザーデータの登録を行うようにします。

```csharp
using System;
using System.Data.SqlClient;
using System.Net;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;

public class UserRegistrationFunction
{
    [Function("UserRegistration")]
    public static HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req, FunctionContext executionContext)
    {
        var logger = executionContext.GetLogger("UserRegistrationFunction");

        string email = req.ReadAsString(); // assume the request body contains the email
        
        var connectionString = Environment.GetEnvironmentVariable("SqlConnectionString");

        try
        {
            using (SqlConnection conn = new SqlConnection(connectionString))
            {
                conn.Open();

                string insertQuery = "INSERT INTO User (Email, CreatedAt, UpdatedAt) VALUES (@Email, @CreatedAt, @UpdatedAt)";

                using (SqlCommand cmd = new SqlCommand(insertQuery, conn))
                {
                    cmd.Parameters.AddWithValue("@Email", email);
                    cmd.Parameters.AddWithValue("@CreatedAt", DateTime.UtcNow);
                    cmd.Parameters.AddWithValue("@UpdatedAt", DateTime.UtcNow);

                    int rowsAffected = cmd.ExecuteNonQuery();

                    logger.LogInformation($"Rows affected: {rowsAffected}");
                }
            }

            var response = req.CreateResponse(HttpStatusCode.OK);
            response.WriteString("Success");
            return response;
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "An error occurred while inserting the data.");

            var response = req.CreateResponse(HttpStatusCode.InternalServerError);
            response.WriteString("An error occurred.");
            return response;
        }
    }
}
```[close]

このコードでは `SqlConnection` を使用してデータベースに接続し、`SqlCommand` を用いてSQLクエリを実行しています。`SqlCommand.Parameters.AddWithValue` メソッドを使用してSQLクエリのパラメータに値を設定しています。これにより、SQLインジェクション攻撃を防ぐことができます。

なお、本番環境で使用する際には、接続文字列やSQLクエリ、エラーハンドリングなどについて、セキュリティやパフォーマンスなどの観点から適切に検討・実装する必要があります。
```

いい感じじゃないですか!

ここではやっていませんが、UIとサーバー。そして DBのメッセージフロー図を作成させてもいいかもしれません。
と、書いてみたので、やってみました。

Promot:
```cmd
ユーザー登録画面の、各コンポーネントのメッセージフローを作成してください、画面 (HTML) とReact、Server側のコード (ASP.NET)、データベースをコンポーネントとして含めてください。
```

出力:
```cmd
以下に、ユーザー登録画面のメッセージフローを Mermaid.js の図表として表現します。これは、ブラウザ上のフロントエンド部分（HTMLとReact）、サーバー側のAPI（ASP.NET）、およびデータベースとの間で行われる一連のコミュニケーションを表しています。

```mermaid
sequenceDiagram
    participant Browser as Browser (HTML/React)
    participant Server as Server (ASP.NET)
    participant Database as Database (Azure SQL)

    Browser->>+Server: POST /api/register (email)
    Server->>+Database: INSERT INTO User (Email, CreatedAt, UpdatedAt)
    Database-->>-Server: Success/Failure response
    Server-->>-Browser: HTTP 200 (success) / HTTP 500 (error)
```[close]

このフローは以下のように進行します：

1. ユーザーがブラウザ上でメールアドレスを入力し、登録ボタンをクリックします。
2. Reactコードがユーザー入力を取得し、サーバーのAPIエンドポイント（ここでは `/api/register` と仮定）に対してPOSTリクエストを送信します。このリクエストにはメールアドレスが含まれます。
3. サーバー側のASP.NETコードがこのリクエストを受け取り、受け取ったメールアドレスをデータベースに登録します。
4. データベースがこの操作の成功または失敗をサーバーに通知します。
5. サーバーがこの結果をブラウザに返します。成功した場合はHTTPステータスコード200を、何らかのエラーが発生した場合はHTTPステータスコード500を返します。

なお、実際の運用環境で使用する際には、各エンドポイントの設定やエラーハンドリング、セキュリティ対策などについて検討する必要があります。また、APIの設計やHTTPステータスコードの選択も、RESTfulな設計原則に従うことが一般的です。
```

スクショを。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108143/aa5eee5c-c84a-8d37-c6f1-cb70398d4762.png)


そして、Mermaid Live Editor にコピペして作成した図を。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108143/9c114389-3c2b-d920-25a4-3eeec198fb9c.png)

いいですね!
簡単なシーケンス図ですが。それでもだいぶ、全体が見えてきて、自分がいまどの部分のコードを書いているのか? どこが接続部分なのか、の整理にだいぶ役に立ちますね。


# 4. コードのデプロイ

これで

- 画面
- 画面からの処理を受け取るコード。コードの中にはDB登録用の処理が欠けていますけどね😅 ここもやらせたら出来ちゃうかも。
- そして、データを受け取るデータベースのテーブル作成文。DDL文と、3件分のDML文

が作成できました。

今度はそれらを Microsoft Azure に展開するために CLI から実行させます。今は Bicep かなーと思い。Bicep のYAMLを作成します。

bicep:
https://learn.microsoft.com/ja-jp/azure/azure-resource-manager/bicep/overview?tabs=bicep

Prompt:
```cmd
素晴らしい!
これらのアプリケーションのコードをホスティングするのに Azure Functions を使います。Azure Functions のインスタンスの作成用の bicep のコードを作成してください。
```

出力:
```cmd
Azure BicepはAzureリソースのデプロイメントを簡素化し、人間に読みやすい言語を提供するためのDomain Specific Language（DSL）です。以下は、Azure Functionsを作成するための簡単なBicepスクリプトの例です。

まず、以下のコードではストレージアカウント、サーバーファーム（App Service Plan）、およびFunction Appの3つのリソースを作成しています。

```bicep
param location string = resourceGroup().location
param functionAppName string
param storageAccountName string
param serverFarmName string

resource sa 'Microsoft.Storage/storageAccounts@2021-04-01' = {
  name: storageAccountName
  location: location
  sku: {
    name: 'Standard_LRS'
  }
  kind: 'StorageV2'
  properties: {
    supportsHttpsTrafficOnly: true
  }
}

resource serverFarm 'Microsoft.Web/serverfarms@2021-01-01' = {
  name: serverFarmName
  location: location
  sku: {
    name: 'Y1'
    tier: 'Dynamic'
    size: 'Y1'
    family: 'Y'
    capacity: 0
  }
  kind: 'functionapp'
  properties: {
    reserved: false
  }
}

resource functionApp 'Microsoft.Web/sites@2021-01-01' = {
  name: functionAppName
  location: location
  kind: 'functionapp'
  properties: {
    serverFarmId: serverFarm.id
    clientAffinityEnabled: true
    httpsOnly: true
    siteConfig: {
      appSettings: [
        {
          name: 'AzureWebJobsStorage'
          value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccountName};EndpointSuffix=${environment().suffixes.storage}'
        }
        {
          name: 'FUNCTIONS_WORKER_RUNTIME'
          value: 'dotnet'
        }
        {
          name: 'WEBSITE_NODE_DEFAULT_VERSION'
          value: '~14'
        }
        {
          name: 'FUNCTIONS_EXTENSION_VERSION'
          value: '~3'
        }
        {
          name: 'WEBSITE_RUN_FROM_PACKAGE'
          value: '1'
        }
      ]
    }
  }
}
```[close]

上記のスクリプトでは、Azure Functionsのランタイムを.NETに設定しています。また、`WEBSITE_RUN_FROM_PACKAGE`を`1`に設定していますので、FunctionsはZIPデプロイモードで動作します。

リソースの名前はパラメータを通じて指定しますので、このテンプレートをデプロイする際には各リソースの名前を指定する必要があります。

なお、本スクリプトはサンプルであり、実際の運用環境では、リソースの設定値や構成について詳細な調査と検討が必要となります。

```

これすげぇですね。

# まとめ
凄く緩い要件定義からで、なんと、CREATE TABLEとINSERT文。HTMLに加えて JavaScript のコード。そしてサーバー側は、ASP.NET C#。デプロイ用に bicep の yamlと。
同じコンテキストで話が継続できる ChatGPT だからこそ。**ものすごい短い時間**で、プロトタイプのひな型が出来ました。

私の ChatGPT 上の Prompt を見ていただけるとご理解いただけると思いますが。必ずしもこの順番で実行する必要は無いですね。後から「あ、あれやっておけばよかった」を追加で行えることが大事です。
ここが「チャット」の良さですし。なんなら ChatGPT でチャット履歴を保存しておけば。私はそうしていますが。**明日以降で気づいた時に追加**できます。

マジで、すげぇ便利😊

今回は作成されたコードを動かすところは、また次回以降で。

Visual Studio Code + GitHub Copilot + Azure CLI があれば。すげぇ短い時間でプロトタイプが作れる可能性しか感じません。