サーバーサイドの設計について学んでみた

# 本記事について

本記事では、とある企業の1dayインターンに参加し、サーバーサイドの設計周りについて学んだことをアウトプットしていきます。

## 内容

1グループ（3名）＋メンター（1名）の構成でグループメンバーと議論しながら、モブプロ形式で設計を進めていきます。

大まかな手順は以下の通りです。

- 要件の整理
- ER図の作成
- APIエンドポイントの設計

### 要件の整理

要件の内容は、飲食店の注文システムの構築です。

以下の観点を探りながら、要件を理解していきます。

- 利用シーン（飲食店の注文システム）
- どのユーザが利用するのか
- どのような機能が必要になるのか

要件の理解を深めた後、グループでいくつかの観点に対してキーワードを挙げて、**重要なキーワードを可視化**しました。

具体例には、以下の通りです。
![スクリーンショット 2021-12-08 7.36.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477704/c2a9b344-5c58-365b-4883-2da1d20cb3ba.png)

### ER図の作成

#### ER図の作成メリット

データベース構造を整理して、システム全体の構成を俯瞰することができるため、手戻りの発生を減少させることが可能です。

大規模になると、Table数が膨大になり、システム全体が複雑化します。
整理せずにデータを増やしていくと、徐々にデータの不整合が発生し、プロジェクトに大きな損害を与えてしまいます。

長期的にプロジェクトがスケールしていくことを想定すると、事前にER図を作ることは必要不可欠だと考えます。

> 所感：
iOS開発（どの領域でも同様）でも、全体把握やクラス間の関係性を可視化するため、クラス図を作成します。iOSなどのフロントエンドの開発だと、クラス図を作成する人が少ない印象ですが、DBの場合は必ず作成しないといけないと危機感を感じます。

#### ER図作成フロー

以下の手順で行いました。

- イベント系エンティティ
- リソース系エンティティ
- エンティティの項目
- リレーションの設定

[dbdiagram.io](https://dbdiagram.io/home)というツールを用いて可視化しました。

メンターさんにもレビューを受けながら、最終的に作成したER図は以下の通りです。

![スクリーンショット 2021-12-06 13.29.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477704/abd139f8-8ffb-da13-2151-e7631bee3684.png)


### APIエンドポイントの設計

概要、HTTPメソッド、エンドポイントの観点でエンドポイントを洗い出しました。（今回はREST APIにしています）

設計時に意識した点は以下の通りです。

- 人間がわかるURLすること

```
× http://fuyan.example.com/u/d
  → uとdは何を示しているかわからない
○ http://fuyan.example.com/users/details
```

- 冗長にせずシンプルに

```
× http://fuyan.example.com/fuyan/users
  → ドメインとパスが被っている
○ http://fuyan.example.com/users
```

- サーバの実装に依存しない

```
× http://fuyan.example.com/cgi-bin/users.php
  → セキュリティの観点から内部実装を知られてはいけない
○ http://fuyan.example.com/users
```

一通り洗い出した後、どのエンドポイントが必要なのか、不必要なのかといった観点でグループ議論を行いました。

![スクリーンショット 2021-12-06 13.46.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477704/fbe2d6c0-786f-ac5c-0967-d715fa854da7.png)

グループ議論の中でどのロジックをフロントエンドに任せるかという議論がありました。
そもそもフロントエンドは基本的にViewを表示するロジック（プレゼンテーションロジック）に責務を持ちます。特に今回はビジネスロジックに近い内容だったため、バックエンド側で持つべきだと判断しました。


## 学び

### ER図の学び

- 全体像の把握としてER図の作成は必須
- DB：データに責務、バックエンド：ビジネスロジック責務を持つ
- セキュリティ面や、ドメイン知識、利用シーンのイメージ力の必要性
- 大規模になるとモノリスや、マイクロサービスの話につながってくる
- データの不整合は間違ったロジックで実装された時に発生


### API設計の学び

- エンドポイントはフロントが理解できるレベルに落とし込むことが必要
- どこまでAPIとして実装するかは周りの環境やリソースに依存
- パラメータの設定基準
    - パスパラメータ　：特定のリソースを識別
    - クエリパラメータ：検索やフィルタなどの条件
    - リクエストボディ：追加・更新が発生するもの、上記のパラメータが増えていきそうな場合など

### 課題

ER図を作成する中で、エンティティ項目を洗い出し、リレーションの設定が非常に難しいと感じました。粒度や判断基準などは経験を積んで感覚を掴みたいです。

またAPI設計の際、ユースケースと機能の洗い出しから始めた方がスムーズだと思いました。

# 最後に

自分はサービス主体で開発を考える人間（いわゆるサービス志向）ですが、それはフロントエンドのみユーザとの距離が近いことが関係していると考えていました。しかし、実際にDBやAPI設計を行う中で、フロントエンド開発者の開発体験の考慮や、ユーザが安全に利用できる仕組みなどを考え、サービス志向で開発することができることを実感しました。

今後は実装に着手してパフォーマンス周り、キャッシュなど開発体験の向上につながる技術を学びたいと思います。
拙い文章でしたが、皆さんの参考になれば幸いです。

# 参考

- [楽々ERDレッスン](https://www.notion.so/08c0428e8bb348269acf08da5ae43b3b#be8bd352b2134d8190a35717d0c1133c)
- [REST APIとは？ざっくりと理解してみる【初心者向け】](https://tech.012grp.co.jp/entry/rest_api_basics)

ER図のコード

```

// Creating tables
Table orders {
  id int [pk, increment] // auto-increment
  table_id int [ref: > seats.table_id]
  is_served bool
}

Table orders_item {
  id int [pk, increment] // auto-increment
  orders_id int [ref: > orders.id]
  menu_id int [ref: > menu.id]
  menu_amount int
}

Table menu {
  id int [pk, increment] // auto-increment
  restaurant_id int [ref: > restaurants.id]
  name varchar
  price int
  image_url varchar
}

Table restaurants {
  id int [pk, increment] // auto-increment
  name varchar
}

Table tables {
  id int [pk, increment] // auto-increment
  restaurant_id int [ref: > restaurants.id]
}

Table seats {
  uuid int [pk, increment]
  table_id int [ref: > tables.id]
}

``