サービス設計について

# はじめに
オリジナルアプリを作成した時、「企画」や「要件定義」、「設計」をしっかり組み立てておく事により、
効率を上げていきたいので復習用として投稿します。
ちなみに内容は前回作成したオリジナルアプリのサービスでの設計になります。
フレームワークはRailsを使用しています。

# サービス設計の中身について
　

| 項目| 説明 | 組織内の主な担当 |
|:----------:|:-----------:|:------------:|
| 企画       | アプリケーションの内容を考案 | 企画部 |
| 要件定義     | アプリケーションの仕様・要件の洗い出し | 企画部、開発部 |
| 設計       | 開発に必要なデータベースの設計 | 開発部 |
| 開発        | プログラミング言語を使用して開発 | 開発部 |
| 保守・運用       |リリース後のバグや追加機能の実装を対処| 開発部 |

# 企画
「どのようなアプリケーションを作成するか？」から「開発をスタートさせる」までを考えることであり、
ターゲットを絞ったり、試作品（プロトタイプ）を作成するなど、色々な工程があります。

### ペルソナ

マーケティングの用語で、「サービスを使用するユーザー」のことです。
詳細に「サービスを使用するユーザー」を決めます。
年齢、職業、性別、現在の境遇などを決めることで、使用者の目線でサービスを作ることを目的とします。
以下のように考案していきます。

```
【性別】
思い出の建物や風景の写真を共有するアプリケーションを考えているので、「性別は男性」に設定します。

【年齢層】
写真を所有する人を対象とするため、「年齢は60代以降」とします。

【職業】
定年退職者を対象に、第二の人生の中で時間を有効に活用したいと考えています。

【趣味】
家に眠っている懐かしい写真などを投稿することです。1つにまとめて管理できたら便利だと思いました。
お気に入りの写真をシェアして、コメントし合えたら面白そうだと考えています。

```

### ユーザーストーリー
「ペルソナの課題に対して、どのような機能で解決していくのか」を明確にしたものです。

以下に課題を改めて見直します。

- 写真をChromeなどの「お気に入り」や「ブックマーク」では、シェアしにくい
- TwitterやFacebookなどのWebサービスは年代的に個人差がある
- お気に入りの写真をみたりコメントしたいが、そのようなサービスがないという課題

次に、課題を解決できる機能を考えます。

インターネット上で写真を共有し、それに対してユーザーがアカウントを持ち、
コメントができるアプリケーションにすれば解決できます。

また、共有された写真はいつでも検索できるようにしておけば写真の管理ができます。
まとめると下記のようになります。

- 写真の共有機能がある。（削除や編集機能もつける）
- ユーザーの管理機能がある
- 共有された写真に対して、コメントをつけられる。
- 共有された写真を検索できる

# 要件定義
ここではトップページに絞って詳細に書き出します。
　

```
【ボタン】
サインイン/ログインページへ遷移できるボタン
ログイン時は、ログアウトできるボタン
共有写真を追加するページへ遷移できるボタン
編集/削除ができるドロップダウン形式のボタン
共有された写真の詳細ページへ遷移できるボタン

【表示】
共有された写真を一覧で見れる
共有者のニックネームを見れる
```
以上がトップページの要件です。

# 設計
開発業務をよりスムーズにするために、設計をします。
今回は一般的な「要件定義」→「基本設計」→「詳細設計」の順で説明します。

### 基本設計（外部設計）
要件定義の内容を、開発に必要な内容へまとめることです。
アプリケーション制作に必須の要素となる「画面」や「画面遷移の流れ」をまとめていきます。
### 詳細設計
実際に書くべきコードを洗い出す作業です。
要件定義や基本設計の情報を元に、ユーザーが行う操作に対して行われる処理をすべて書き出します。
その上で、実際どのようなコードを書くかを当てはめていきます。
### 画面遷移図
どの画面でどんな操作をしたらどのページに移動するかを図で表記したものです。
紙に描いたり、専用のアプリを使ったりします。

# データベース設計
開発で使用するデータベースの表を設計することです。
具体的に考える項目としては、「テーブル」や「カラム」、「関連付け（アソシエーション）」などです。

手順として、まずは保存する項目を洗い出します。
そして、どのようなテーブルがあれば管理しやすいかを考慮しつつ、その中でテーブル同士の関連付けを考えていきます。

まず、サービスで扱われる情報を整理します。サービスで扱われる情報のことを、エンティティと呼びます。

### エンティティ
サービスで扱われるデータ自体のことです。
エンティティを洗い出し、そしてそれらをどの様に紐付けるのかを考えます。
エンティティはテーブルと等しい粒度で決める必要があるため、なるべく「異なるジャンルの情報」は混合させないようにします。
たとえば、「ユーザー管理に関する情報」と「共有する写真に関する情報」を混合させるようなエンティティにすることは避けるようにします。

次に、抽出したエンティティを関連性も含め具体化していきます。

### モデリング
エンティティの分類や関連付けなどを行い、模型のように表すことです。
具体的にはエンティティ自体を見直し、さらにエンティティ同士の関係性を考え、図などに表記したりすることです。

このあとは、正規化を行い、データベースの構造を効率的でシンプルな形にすることです。

### 正規化
正規化は段階で分かれており、下記の表のような内容が存在します。

| 正規化の段階| 説明 |
|:----------:|:-----------:|
| 非正規形　    | 何もしていない状態 |
| 第一正規形   | 重複する値やカラムを分離する |
| 第二正規形  | 情報が混在するエンティティを分離する |
次に、データベースにおいてカラムに設定できるようにするため、制約を設けます。

### 制約
データを扱う際に制限をかけることです。バリデーションの仕組みと似ています。
制約はデータベースへ直接設定するので、後に変更すると非常に手間のかかる可能性があります。

### NOT NULL制約
テーブルの属性値にNULL（空の値）が入らないように制限する制約です。

たとえば、usersテーブルの「name」カラムにNOT NULL制約を設定すると、
nameカラムが空のレコードだと保存できなくなります。
この制約は、t.string :nameに`null: false`と記述することで、設定できます。

```ruby:db/migrate/2020XXXXXXXX_create_users.rb
class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :name, null: false
      t.timestamps null: false
    end
  end
end
```
指定したカラムが、データベースに空のままの状態で保存するのを防ぎます。
カラム名の後にこれを記述します。書き方は、以下のように記述します。
 
```ruby
t.型 :カラム名, null: false
```

### 一意性制約
一意性制約は、テーブル内で重複するデータを禁止する制約です。
emailカラムに対して一意性制約を設定すると、同じemailのレコードは保存できなくなります。

### 主キー制約
主キー制約は、そのデータが空になることがなく、かつ重複していないことを保証する制約です。
主キーに対して、NOT NULL制約と一意性制約を両方設定するのと同義になります。

また、Railsでテーブルを作成する際、主キー制約はidカラムとして自動で作成されます。

### 外部キー制約
外部キー制約とは、外部キーの対応するデータが必ず存在しなくてはいけないという制約です。
この制約は、t.references :user_idに`foreign_key: true`と記述することで、設定できます。

```ruby:db/migrate/2020XXXXXXXX_create_tweets.rb
class CreateTweets < ActiveRecord::Migration[6.0]
  def change
    create_table :tweets do |t|
      t.string :name
      t.string :text
      t.text :image
      t.references :user_id, foreign_key: true
      t.timestamps
    end
  end
end
```

上記の例のコードでuser_idのカラムに`references`という型を使用していますが、
これは他テーブルから情報を参照する際に用いる型です。

### チェック制約
チェック制約は、値が保存される際に条件を満たしているかチェックできる制約です。
例えば、userのニックネームが6文字以下になるような条件を加えれば、それ以上のニックネームが保存されることはありません。
正規化や制約を記述した後は、ER図を使いわかりやすく表記します。

### ER（Entity Relationship）図
データベースのテーブルなどを図で表記したものです。
特徴は、表で記述するよりも関連付けがイメージしやすいことです。

# おわりに
自分以外の人にもアプリケーションの設計を伝える上で非常に有効な手段だということがわかりました。
実際に開発をする上では必須知識とのことなので、ER図からテーブル間の関係を読み解けるように意識しようと思います。
間違いなどございましたら、お手数ですがコメントいただけると幸いです。
よろしくお願いします。