ハッカソンでドキュメントを書く【Design Doc】

# はじめに
どうもKizukuです．
みなさんハッカソンの参加経験はありますか？
ハッカソンの時にドキュメント整備はしていますか？
チーム開発をする場合はハッカソンであってもドキュメントを書いておくほうが何かと便利だったりします．
そこで，この記事では**ハッカソンで使えるドキュメント整備術**について書きたいと思います．
今回はDesign Docの回です．
他のドキュメントに関しては，こちらを参照してください

https://qiita.com/K-Kizuku/items/dd79abcd4b9690026a99

(この記事内で出てくるハッカソンは2,3日程度の短期間のハッカソンのことを指します．1ヶ月以上の長期ハッカソンの場合は，もっとちゃんとしたドキュメントを書きましょう)

## 対読者
- ドキュメントをあまり書いたことがない人
- ハッカソン大好きな人
- チーム開発好きな人

# Design Docとは
Design Docは，日本語でいう「**設計書**」に相当します．
アプリケーションの具体的な定義をDesign Docに事前に記述しておくことで，開発フェーズに入った際に，開発者同士が最低限のコミュニケーションで効率的に開発に集中できます．このアプローチは，チームメンバー間の認識の違いによる作業の出戻りを防ぎ，効率的な開発を実現することができます．
また，プロジェクト全体の工数を把握しやすくなるため，時間制限のあるハッカソンのような環境では，残り時間で優先すべき機能や実装可能な機能の選定が容易になります．

# 記述すべき内容
Design Docの書き方には，いくつかの流派がありますが，一例を紹介します．
この例は，機能ごとにDesign Docを書いていく方法になります．
## タイトル
実装したい機能のDesign Docのタイトルを書きます．
## 概要
実装したい機能の概要を簡潔に書きます
## 詳細
実装したい機能の詳細を書きます．
機能が満たすべき具体的な要件や条件が明確になるように書いてください．
書くべき内容としては，正常系の処理のフロー，異常系の処理のフロー，その他の特記事項等です．
注意点としては，**何が何にどういう処理を行う**のかを明確に書くことです．
(日本語では，主語や目的語が省略されていても意味が通る文になることが多いので，意識して書く方がいいです．)
例：バックエンドは，正常にリクエストを処理できた場合にはステータスコード`200`とリクエストの内容をクライアントに返す．

## シーケンス図
処理の流れをシーケンス図を用いて記述します．
正常系の場合と異常系の場合を合わせて，記述します．
シーケンス図を記述するツールとしては[draw.io](https://www.drawio.com/)や[Astah](https://astah.change-vision.com/ja/)，[PlantUML](https://plantuml.com/ja/)などがあります．
僕のおすすめは，無料でWeb上で書くことができる[draw.io](https://www.drawio.com/)を用いてそのリンクを埋め込む方式か，Design Doc内に直接書くことができる[Mermaid](https://mermaid.js.org/)を使用してマークダウン内に直接コードブロックとして記述する方式です．以下の[サンプル](#サンプル)ではMermaidを用いて記述しています．

## ER図
この機能に関連するデータベースの定義をER図を用いて記述します．
エンティティ同士の関連等を明確にして記述します．
使用するツールに関しては，[シーケンス図](#シーケンス図)の時と同じような選択肢が挙げられるので省略します．


## スキーマ
リクエストやレスポンスの型とかを定義しておきます
スキーマの定義は[openAPI](https://swagger.io/specification/)や[protobuf](https://protobuf.dev/)などを用いて行うのが良いと思います．
個人的には，protobufで書くのがおすすめ．(yamlはあまり書きたくない...)
スキーマ駆動開発の時も，protobufは大活躍するので，ぜひお試しください．

# Tips
先ほど書いた記述するべき内容をテンプレート化して，自動生成すると楽です．
私は，scaffdogを用いた自動生成をよく使うのでその設定を残しておきます．

```markdown:.scaffog/DD.md
---
name: 'DD'
root: '.'
output: './docs/DesignDoc'
ignore: ['.']
questions:
  number: 'バージョン管理'
  fileName: '何の機能のDDか教えてね'

---

# `{{ inputs.number | rtrim }}_{{ inputs.fileName }}.md`

```markdown
# DesignDoc

## {{ inputs.fileName }}機能について

### 概要

### 詳細

### シーケンス図

### ER図

### スキーマ

執筆日：{{ date "YYYY/MM/DD HH:mm" }}

```(これは一例です)
```

また，生成時のコマンドもやや複雑になるためMakefileに記述しておくことをお勧めします
```makefile:Makefile
##### scaffing

DD_COUNT:=$(shell find docs/DesignDog -type f | wc -l | tr -d ' ') 
dd:
	npx scaffdog generate DD --output 'docs/DesignDog' --answer 'number:${DD_COUNT}'
```
`make dd`を実行することで，`{バージョン番号}_{機能名}.md`という形式でADRのファイルを生成することができます．
(この例では`docs/DesignDog`にファイルを生成することを前提としています．)

# サンプル
以下にTODOアプリのTODOの登録機能のDesign Docのサンプルを示します．
***
## TODO登録
### 概要
TODOを登録する機能

### 詳細
ログイン済みユーザーがTODOを登録する
登録する内容は以下の通りとする．
- TODOの内容
- 期限

ログイン時に発行されたJWTを`Authorization`ヘッダーに付与し，そこからユーザーIDを取得しユーザーを識別する．
バックエンドは，正常にリクエストを処理できた場合にはステータスコード`200`と登録した内容をクライアントに返す．
バックエンドは，リクエストが不正な場合にはステータスコード`400`をクライアントに返す．
バックエンドは，リクエストに認証情報がない場合やトークンの期限切れの場合にはステータスコード`401`をクライアントに返す．
クライアントは，リクエストを送りレスポンスのステータスコードが，
`400`だった場合はエラー表示，
`401`だった場合は「ログインしてください」の表示，
`200`の場合は「登録が完了しました」の表示を行う．


### シーケンス図
```mermaid
sequenceDiagram
    participant User as ユーザー(Webブラウザ)
    participant Backend as バックエンド
    participant DB as データベース

    User->>Backend: TODOの内容と期限を含むPOSTリクエスト
    alt 有効なJWTトークン
        Backend->>Backend: JWTトークンのデコード
        Backend->>DB: TODOの内容と期限の登録
        DB-->>Backend: 登録成功
        Backend-->>User: ステータスコード200(登録完了)
        User->>User: 「登録が完了しました」メッセージ表示
    else 不正なリクエスト
        Backend-->>User: ステータスコード400(不正なリクエスト)
    else 認証情報なしまたは期限切れ
        Backend-->>User: ステータスコード401(認証エラー)
        User->>User: 「ログインしてください」メッセージ表示
    end
    
```

### ER図
```mermaid
erDiagram
    USERS ||--o{ TODOS : has
    USERS {
        string user_id PK
        string name
        string password_hash
        string refresh_token
    }
    TODOS {
        string id PK
        string content
        bool is_done
        datetime expired_at
        string user_id FK
    }
```


### スキーマ
| エンドポイント  | メソッド    |認証| リクエストJSON                                        | レスポンスJSON                                    |
|---------------|---------|-|----------------------------------------------------|-------------------------------------------------|
| /todos/create | POST    |必要| message CreateTodoRequest {<br>    string content = 1;<br>    string expired_at = 2; <br>// ISO 8601形式の日付文字列を想定<br>}     | message CreateTodoResponse {<br>int32 id = 1;<br>string content = 2;<br>bool is_done = 3; <br>int32 user_id = 4;<br>string expired_at = 5; <br>// ISO 8601形式の日付文字列<br>} |


# おわりに
ここまで読んでいただきありがとうございます！
今回紹介したのは，チーム開発における最低限のドキュメントの書き方です．長期間のハッカソンや実際の業務の場合はもっと書くべきことは多くあると思います．
たかがハッカソン，されどハッカソン．
ドキュメントを整備して快適で効率的な開発になるようにしましょう！