『はじめての設計をやり抜くための本』をざっくり読み抜く（その3）

## はじめに
こんにちは！
[『はじめての設計をやり抜くための本』](https://www.shoeisha.co.jp/book/detail/9784798153766)の社内向け輪読会の資料です。

以下の記事の続きになります！

https://qiita.com/mori_yuk/private/8520ec80ab7944898609

## 第3章 外部設計の手法 後編
後編は以下の内容について解説をまとめてます！  

 - 外部システムI/F設計
 - バッチ設計
 - 帳票設計
 - データベース論理設計
 - NoSQLデータベース設計
 - 非機能要件定義とシステム設計
 - システムインフラ設計と配置設計

各設計の定義や必要な要素をまとめていきます！

### 外部システムI/F設計
#### 外部システムI/Fとは？
外部システムI/F（インターフェース）とは、異なるシステム間でデータや命令をやり取りするための接点や規約のことです。簡単に言うと、異なるシステムや機器が互いに通信するための「言語」や「ルール」のようなものです。
APIが異なるソフトウェア間で情報を交換するための一般的な方法で外部システムI/Fの代表例にあたります。


例
ECサイトのシステムが注文データを生成し、それを会計システムに転送して処理する場合、そのデータ交換を可能にするのが外部システムI/Fです。

#### 外部システムI/F設計で必要な検討事項
次の6つの事項を検討します。
 - 接続先
     - どのシステムやサービスに接続するかを決める
 - プロトコル・手段
     - 通信に使用するプロトコルや手段を選択する(HTTP、TCP/IP、REST、SOAPなどがある)
 - タイミング
     - システム間のデータ交換のタイミングを決める(同期通信や、バッチ処理等の非同期通信がある)
 - インターフェース項目使用
     - 交換するデータの具体的な内容
 - 認証・セキュリティ
     - 通信のセキュリティを保証するための手段を決める(SL/TLSによる暗号化、APIキー、OAuthトークンなどの認証方法がある)
 - 例外処理
     - 障害発生時などの対策を決める

また、外部システムI/F設計に取る組むうえで意識することは、

接続相手先の都合で変更される恐れがあるため、設計するうえでは外部システムI/Fに依存した処理を共通化するべきということです。

「ネットワークに接続するクラス」「シーケンスを制御するクラス」「受送信データを読み書きするクラス」「例外処理を行うクラス」くらいに共通化して設計するようにします。

RestfulAPIの設計について詳しく解説してくれている記事もここで紹介する（記事自体は古い記事になるが、ここで書いていることを具体的に解説してくれている）

https://qiita.com/NagaokaKenichi/items/89c09354f08fc8d7387f

### バッチ設計
#### バッチとは？
サーバープログラムのように常駐しておらず、ある時間が来るか手動での起動によって実行されるプログラムです。

バッチを使う例として、大量のデータを扱う場合に、他の処理と被らない深夜の時間帯に実行させることでサーバーの負荷を軽減されることができます。

#### バッチ設計で必要な検討事項
 - 実行タイミング
     - システムの負荷、他のプロセスとの競合などを考慮しながらバッチを実行するタイミングを決める
 - 実行制御、ジョブ制御
     - 複数のバッチプログラムの実行順序や依存関係を決めて制御する
 - トランザクション
     - トランザクションスコープ（データベースやその他のリソースに対する一連の操作が一つの単位として扱われる範囲）の大きさを決める
 - リカバリー
     - バッチ処理中にエラーや障害が発生した場合の対策を決める

また、バッチ設計に取り組むうえで意識することは、

決められた時間の中で、大量のデータを処理する必要があるので、パフォーマンスが重要になるということです。

特にデータベース処理はSQLの書き方次第でパフォーマンスが大きく変わります。

バッチ設計についてメルカリさんのエンジニアブログにまとまっていたので貼っておきます。

（ブログの下の方に実際のバッチ処理の事例のブログリンクが載っているのでそこまで見てみると面白いかもです）

https://engineering.mercari.com/blog/entry/2019-02-27-112650/

 
### 帳票設計
帳票とは、ビジネスや組織において、データや情報を整理し、まとめて表示するための文書やファイルのことです。

帳票をどのように作成し、どのような形式で出力するのかを考えます。

### データベース論理設計
#### データベース論理設計の目的
概念モデルで表現されたモデルをリレーショナルデータベースで扱える形式に書き換えることを目的としています。

#### リレーションの正規化
データを効率的で整合性のある方法で格納するためのプロセスです。
正規化の目的は、データの冗長性を減らし、データベース内のデータの整合性を高めることです。
正規化は、通常、以下の「正規形」に従って行われます。

 - 第一正規形
     - テーブルのすべてのカラムがこれ以上分割できないカラムで構成されているテーブルの、すべてのカラムがスカラ値（分割不可能な値）を持つようにする。つまり、各カラムには繰り返しグループや複数の値が含まれないようにする。
 - 第二正規形
     - テーブルが第一正規形であり、なおかつすべての非キーカラムが、テーブルの候補キー全体に対して完全に依存しているようにする。
 - 第三正規形
     - テーブルが第二正規形であり、なおかつすべての非キー属性がすべての候補キーに非推移的に依存するようにする。非推移的な依存とは、あるカラムが主キーではない別のカラムに間接的に依存していない状態を指す。

https://breezegroup.co.jp/202005/database-normalization/

#### 論理ER図の作成
データベース論理設計では、概念モデルを基に論理ER図を作成します。

##### 論理ER図とは？

論理ER図（Entity-Relationship Diagram）とは、データベースの構造を視覚的に表現するための図です。
ER図は、エンティティ（実体）、エンティティ間の関係、およびそれらに関連する属性を図式化したものです。

##### 論理ER図を作成する際の注意点
 - 主キーを決める
 - 関連を外部キーにする
 - 多対多の関連を関連テーブルにする
 - 継承をリレーショナルで実現する

この4つの注意点を解説していきます。
###### 主キーを決める
まずは、概念モデル化を見ながら論理ER図を作成します。
それぞれの概念を論理ER図のテーブルとして作成していきます。ここでは例として、注文という概念を取り上げます。
![スクリーンショット (378).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3515830/0a55b2ab-3c30-c564-58e2-f80fc57b7d10.png)

このように1つのテーブルが完成したら、主キーを決定します。

主キーとは、データベースのテーブル内で各レコードを一意に識別するために使用されるカラムです。

主キーには人工キーと自然キーがあります。
人口キー：シーケンスなどの連番をシステムが自動的に採番して主キーとするもの
自然キー：注文の注文番号のように実際にそのテーブルに存在するカラムを組み合わせて主キーとするもの

今回は人口キーを採用し、主キーとなる注文IDを定義します。
![スクリーンショット (378).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3515830/05a7d93a-6cf7-8a31-5036-8d4239bbcd90.png)

##### 関連を外部キーにする
概念モデルの概念の間には関連があります。
![スクリーンショット (379).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3515830/3e6229de-41d8-bdc2-4cc9-d47a258676ea.png)
この概念モデルには、注文と会員、注文と注文明細、注文明細と商品の間に関連があります。
その関連は論理ER図の外部キー(FK)として表現されます。
外部キーとは、参照先のテーブルに主キーを持っています。
![スクリーンショット (385).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3515830/495f1618-5761-d0d6-7c3e-06edeaacbabf.png)

##### 多対多の関連を関連テーブルにする
概念モデルでは、多対多の関連を簡単に記述できてしまいます。
そうなった場合一旦その関連が本当に必要か考えてみてください。
概念モデルの関連は1対多が望ましいです。

リレーショナルデータベースでは関連テーブルを作成することで多対多の関連を実現しています。
下の図のように、両方の主キーをすべて持つ関連テーブルのテーブルABを作成することで多対多の関連を表現します。
![スクリーンショット (386).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3515830/f5f76c5f-9e77-1ea9-3626-458d446f9580.png)

##### 継承をリレーショナルで実現する
継承をリレーショナルデータベースで実現するには以下の3つの方法があります。
 - 抽象クラスと具象クラスごとにテーブルを作る
継承をテーブル間のリレーションで置き換える方法です。

抽象クラスとは、具体的なインスタンスを持たないクラスです。下の図では、注文決済のテーブルです。

具象クラスとは、抽象クラスを継承し、具体的なインスタンスを作成できるクラスです。下の図ではクレジットカード決済テーブルと銀行決済テーブルです。

![スクリーンショット (388).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3515830/fd7713f4-eeb8-e01b-7e0d-703dddeb7677.png)

共通の属性（注文決済ID・決済日時）は「注文決済テーブル」に格納され、各具象クラスの特有の属性（カード種別や銀行名、番号等）は各自のテーブルに格納されます。これにより、関係がリレーショナルデータベースで表現されます。

 - 具象クラスごとにテーブルを作る
継承の考え方を捨て、具象クラスごとに中小クラスのデータを含めてテーブルを作成する方法です。

![スクリーンショット (382).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3515830/baf9cc7b-65d8-ba53-5ee7-5fb8ddcee4ba.png)

1つの具象クラスが1つのテーブルに対応付けられてるので非常に簡単です。

 - クラス階層ごとに汎用テーブルを作り、さらに型を表すカラムを用意する
継承のクラス階層を1つのテーブルで表現する方法です。
![スクリーンショット (383).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3515830/7a810d0e-3718-da7b-17f0-1bb1f1e19c4f.png)
この方法では、どの苦笑クラスをテーブルのレコードを表すのかを表現するために、sっゆ別のカラムが必要になります。

ポリモフィズムやパフォーマンスの観点からどの方法を選ぶかを決めましょう。

今回はクラス階層ごとに汎用テーブルを作り。さらに型を表すカラムを用意するを採用します。
そして概念モデルを基にER図を作成すると以下のようになります。

![スクリーンショット (384).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3515830/89c4f182-da78-498f-3d14-4593c9930376.png)

https://itsakura.com/sql-er#s3

今回は本書に合わせてER図をIDEF1X記法で書きましたが、IE記法の方が見かけるよという方は上のページからそれぞれの記法を比べてみるといいと思います！


### NoSQLデータベース設計


https://www.slideshare.net/AmazonWebServicesJapan/db-20190905

NoSQLのデータベースについては深くは触れていなかったので、AWSのNoSQLデータベースであるDynamoDBの設計方法について公式がまとめた資料を載せておきます。

### 非機能要件定義とシステム設計
#### 非機能要件とは
非機能要件とは、システム利用者が機能を利用するときに補助的に必要な品質や性能のことです。
非機能要件の基準として『ISO/IEC9126』というシステムの品質特性を網羅的に定義したものがあります。
その中では6つの品質特性というものが定義されている。ここではそれらの定義をまとめておく。

##### 機能性
定義：指定の条件下でソフトウェアを使用したとき、明示的及び目次的ニーズを満たす機能を果たすソフトウェア製品の能力

##### 信頼性
定義：指定された条件下で使用したとき、指定のパフォーマンスレベルを維持するソフトウェア製品の能力

##### 使用性
定義：指定の条件下で使用したとき、ユーザーに理解され。学習され、魅力的なものとなるソフトウェア製品の能力

##### 効率
定義：指定の条件下で、使用する資源の量に関して適切なパフォーマンスを提供するソフトウェア製品の能力

##### 保守性
定義：修正に応じられるソフトウェア製品の能力

##### 可搬性
定義：ある環境から別の環境に移植可能となるソフトウェア製品の能力



### システムインフラ設計と配置設計
システムインフラ設計とは、システムを実現するためにネットワークやハードウェアを構成することです。
そこで、重要になるものが非機能要件を踏まえた、セキュリティや信頼性、効率です。

https://wa.aws.amazon.com/index.ja.html

近年のインフラ設計ではクラウドを使うことも多いと思うのでAWSのインフラ設計における設計原則とベストプラクティスがまとまっているAWS Well-Architected フレームワークを載せておきます。

## おわりに
今回は外部設計編の後編、外部システム設計I/F設計やデータベース設計について学びました！
次回はいよいよ内部設計編です！お楽しみに！

### 参考文献
この記事は以下の情報を参考にして執筆しました。
[『はじめての設計をやり抜くための本』](https://www.shoeisha.co.jp/book/detail/9784798153766)