こんにちは、HCB Advent Calendar 2021の5日目を担当する、take-2405です。
HCB Advent Calendar 2021
ハッカソンの記事を書く予定でしたが、急遽変更してしまいました。ごめんなさい🥺
今回は、TDD、DDDを書籍で学んだのちに、実際にコードを書きながら理解を深めた過程を書きたいと思います。
この記事について
この記事は、「TDDとDDDについて学んだから実践してみたい」ということでゆめみさんが公開している模試問題に取り組んでいます。
TDDの開発サイクルとオニオンアーキテクチャを意識して問題に解答しました。
取り組んだ問題
今回取り組んだ問題は、ゆめみさんが公開している模試問題です。
内容は、とあるゲームのスコアログをソートし、上位10位のスコアに概要するプレイヤー一覧を表示するという問題です。
詳細は下記ページをご確認ください。
https://www.yumemi.co.jp/serverside_recruit
本題
TDDのマントラに従うならば、最初にすべきことは必要なテストを洗い出し、失敗する自動テストを用意することです。一方で、DDDはドメインへの理解を深めモデルを作成する(改善し続ける)ことが最初に必要です。
TDDのマントラ
- レッド
- グリーン
- リファクタリング
これら(テストの用意、モデル作成)の優先順位はケースバイケースだと思いますが、今回はテスト項目を洗い出し、失敗する自動テストを用意することで必要なモデルへの理解を深め、モデル作成しました。
問題を呼んで洗い出したテスト項目
- 引数をきちんと受け取れている
- ログファイル(csv)をきちんと開けている
- ログファイル(csv)のヘッダー、列数を確認する(対象のログかどうか)
- ログファイル(csv)の中身をパースする
- ログファイル(csv)のスコアなどの型を適したものにする
- プレイヤーごとの合計得点、プレイ回数を計算する
- プレイヤーごとの平均得点を計算する
- 平均点ごとにプレイヤーをソートする
- 平均点を高い順に1-10位まで出力する(同じ得点の場合は同じ順位として出力し、10位まで出す)
最初に作成したモデル
type playData struct{
Count int `csv:"player_id"`
Score int `csv:"score"`
}
type PlayDatas struct{
Datas map[string] playData
}
type RankingDatas struct{
Datas map[int] string
}
もちろん上記のテスト項目から増えたもの、減ったものがありました。(初めてということもあり、項目の洗い出しは悩みました。)
最初に作成したモデルも、後々無駄な処理が必要になると感じる部分が度々あり、変更しました。
テスト項目を洗い出し、モデルを作成した後はのサイクルは至ってシンプルでした。
1. TDDのマントラに従い、テスト項目の中から1つを選択し、テストを作成、機能を実装、テストを通す。
2. 必要があればモデルを修正する。
の繰り返しです。
以下が最終的なアウトプットになります。
この記事ではアーキテクチャに関してほとんど触れられていないので、リポジトリを見ていただけると幸いです。
感想
TDD、DDDともに学ぶ前の敷居は高く感じられましたが、実践するうちにそれぞれのメリットが感じられました。
テストの粒度などを意識しすると、メソッドの分け方が洗練られた気がします。また、オニオンアーキテクチャを採用したことで普段よりも依存性に意識してコードを書くことができたと思います。
参考記事
- https://zenn.dev/foxtail88/articles/a9243dd25acd98
- https://zenn.dev/foolishell/articles/589536ec741ddd
おわりに
明日のAddvent calenderは @QT21-004-6_HCB が記事を書くので、是非そちらも見てください。