ChatGPTをパートナーにしてDDD、TDDを取り入れた開発をする

## はじめに

　[ソフトウェア開発にChatGPTは使えるのか？](https://www.amazon.co.jp/dp/B0C9L3DH5S)という本がとても勉強になったので、この本の読んで自分なりに実践した内容を記事にしたいと思います。

https://www.amazon.co.jp/dp/B0C9L3DH5S

　この本の中で私がとても参考になったのは「第5章 各種開発手法の提案」で、この中で「5-1 DDDによる設計と実装」「5-2 TDDによるテストからの実装」が語られているので、それを取り入れた手法で開発をしてみたいと思います。

## DDDとTDDについて

　ちなみに私はDDD(ドメイン駆動設計)については、書籍で読んでなんとなくやることはわかっているけど、実践はしていないレベル。TDD(テスト駆動開発)についても書籍で読んである程度実践はしたけど、最近は仕事でコードを書いていないので、詳細部分を忘れそうになっているレベルです。

　なので、それぞれChatGPTに説明してもらいましょう。(はじめにこれをやっておくとChatGPTの方もこれらを意識してくれそうな気がします。。。)

　まずはDDDについて

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350321/2431a509-3867-939b-6983-76b12cb94e0c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350321/73a4b5b5-11d9-1008-a576-2d8cb061ed5a.png)

　次はTDDについて

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350321/554dd7b7-a273-1dc5-5fe9-cc06120f9231.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350321/d9f63aec-5d42-a78d-cdd7-586660e4efcd.png)


## DDDで設計

　それでは早速DDDを用いた設計に入っていきましょう。ここでChatGPTと一緒に作る開発対象は簡単な日記投稿Webアプリとします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350321/c008bf2b-77b8-3ec3-c2d5-4cfaa374136a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350321/0fdd70fc-d8fc-eee9-9303-c6524400e28f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350321/63107ce3-9954-dcc7-9aad-c0122d315424.png)

　それらしい回答が来たので、いったんクラス図にまとめてもらいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350321/7d6f2fe8-295c-df58-95e6-b3a5e83a7bc8.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350321/fa150682-c8a2-1b2a-ab82-cf797776f158.png)

```
classDiagram
    class User {
        +id: int
        +username: string
        +password_hash: string
        +verify_password(plaintext_password): bool
    }

    class Diary {
        +id: int
        +user_id: int
        +title: string
        +content: string
        +date_posted: datetime
    }

    class AuthController {
        +login(username, password): User?
        +register(username, password): User
    }

    class DiaryController {
        +post_diary(user_id, title, content): Diary
        +view_diary(user_id): Diary[]
    }

    class UserRepository {
        +find_by_username(username): User?
        +save(user): void
    }

    class DiaryRepository {
        +find_by_user_id(user_id): Diary[]
        +save(diary): void
    }

    AuthController --> UserRepository : uses
    DiaryController --> UserRepository : uses
    DiaryController --> DiaryRepository : uses

    User "1" --o "0..*" Diary : has

```


これを[Mermaid Live Editor](https://mermaid.live)などで表示すると以下のようになります。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350321/fc49e27a-eaec-7215-379b-52c8c10705ed.png)

　特に問題なさそうなので、実装に移って行きたいと思います。

## TDDで実装

　DDDでの設計もある程度できたので、ここからはTDDで実装していきたいと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350321/2a79ebf5-da39-e5b3-11c8-8a242f38f078.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350321/45edc3dd-ec70-aeab-a97e-12144fb3c6b5.png)

エンティティのテストコード

```Python
# tests/test_user.py
import pytest
from models.user import User

def test_user_creation():
    user = User(username="testuser", password_hash="hashedpassword")
    assert user.username == "testuser"
    assert user.password_hash == "hashedpassword"

def test_password_verification():
    user = User(username="testuser", password_hash="hashedpassword")
    assert user.verify_password("plaintextpassword") == False # この例では、ハッシュ関数は実装していないため、失敗するはずです。

```

```Python
# tests/test_diary.py
import pytest
from models.diary import Diary
from datetime import datetime

def test_diary_creation():
    date = datetime.now()
    diary = Diary(user_id=1, title="Test Title", content="Test Content", date_posted=date)
    assert diary.user_id == 1
    assert diary.title == "Test Title"
    assert diary.content == "Test Content"
    assert diary.date_posted == date

```

エンティティのコード

```Python
# models/user.py

class User:
    def __init__(self, id=None, username="", password_hash=""):
        self.id = id
        self.username = username
        self.password_hash = password_hash

    def verify_password(self, plaintext_password):
        # TODO: 実際のパスワードハッシュと比較するロジックを後で実装する
        return False
```

```Python
# models/diary.py
from datetime import datetime

class Diary:
    def __init__(self, id=None, user_id=None, title="", content="", date_posted=None):
        self.id = id
        self.user_id = user_id
        self.title = title
        self.content = content
        self.date_posted = date_posted or datetime.now()
```

　このコードを自分の環境でpytestを実行すると今回は両方ともパスしました。エラーが出た場合はChatGPTにエラー内容を貼り付けて修正を頼めばコードを修正してくれます。

　こんな感じで進めていけば、おそらく無事完成までたどり着けるでしょう。

## おわりに

　[ソフトウェア開発にChatGPTは使えるのか？](https://www.amazon.co.jp/dp/B0C9L3DH5S)には他にもたくさん使える内容があるので、気になった方はぜひ手に取ってみてください。