ソフトウェア設計とは何か

# はじめに
## 本稿の目的と構成
ソフトウェアの設計に悩んでいる駆け出しエンジニア〜中堅エンジニアを対象に、世の中にある様々な設計手法をまとめ、それらをどう活用したらよいかを伝えたいと思って書き始めましたが、思った以上に長文になってしまいました。
本稿は以下の構成となっています。

* 設計の定義
* 様々な設計モデル
* ジャストインタイムの設計活動
* 誰のための、何のための設計か
* 参考文献

長文はすっ飛ばして、参考文献に挙げた書籍やWebページの中で興味のあるものを読んで頂くのもよいです。いずれも良書ばかりです。

## 筆者のバックグラウンド
* いわゆるSIerに勤めています。
* 以前は中〜大規模の受託SI案件にアーキテクトとして参画し、アーキテクチャ設計や開発標準化などを主に担当していました。もちろんウォーターフォール開発です。
* 現在は自社パッケージ製品の開発をリードする立場です。アジャイル開発をベースとしています。

本稿はエンタープライズ向けの業務システム開発経験をもとに書いていますので、他の領域（Web系、組み込み系）では当てはまらない内容もあるかと思いますがご承知おきください。

## 改訂履歴
* 2020/6/29 新規投稿

# 設計の定義
## Vモデル
ソフトウェア開発プロセスにおける**Vモデル**（V字モデル）は皆さん目にしたことがあるかと思います。いくつかのバリエーションがありますが、よく見るのは以下の図のようなモデルです。

<img width="688" alt="Vモデル" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176589/d91a41b6-2aff-8ba3-f4ac-600561b15dfe.png">

Vの字の左側の基本設計と詳細設計を合わせたものが、設計プロセス全体になります。設計とは、ソフトウェアの要求仕様と、実装されるプログラムの間のギャップを埋めるための活動と言えます。

Vモデルにおける2つの設計の箱は、基本設計／詳細設計で分けることが多いですが、外部設計／内部設計で分けることもあります。あるいは、[ISO/IEC 12207](https://www.iso.org/standard/43447.html)をベースとした[共通フレーム2013](https://www.ipa.go.jp/sec/publish/tn12-006.html)の場合だとソフトウェア方式設計プロセス／ソフトウェア詳細設計プロセスに分けられています。

海外の場合だと、Architecture Design/Module Designという分け方や、High Level Design/Low Level Designといった分け方があるようです。

## 外部設計と内部設計
**外部設計**と**内部設計**という分け方は、視点の違いです。ソフトウェアをブラックボックスとして捉え、ユーザーの視点で観察可能な振る舞いが外部仕様であり、外部仕様を明らかにして文書に落とし込む活動が外部設計です。
一方、内部設計ではソフトウェアの内部に注目し、外部仕様を実現するのに必要なソフトウェアコンポーネントの洗い出しや、コンポーネント間の相互作用を設計します。

なお、エンドユーザーだけでなく、外部のシステムやサービスも当該ソフトウェアのアクターとして捉えるため、外部インタフェースの設計は外部設計ということになります。

<img width="531" alt="外部設計と内部設計" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176589/940fdc47-2d12-3de9-b104-3c25a1949f29.png">

## 基本設計と詳細設計
**基本設計**と**詳細設計**という用語は、文脈によってその意味するところが異なると筆者は考えています。

1. 外部設計/内部設計とほぼ同義
2. ハイレベルな設計と詳細な設計
3. 多重請負構造において一次請けが行う設計と、二次請け以降が行う設計

1と2の違いですが、例えばアプリケーションアーキテクチャの設計（レイヤーアーキテクチャなどのアーキテクチャパターンの決定や、主要コンポーネント間の相互作用パターンの決定など）は内部設計にあたりますが、抽象度は高くハイレベルの設計です。そのためアプリケーションアーキテクチャ設計は基本設計に含めるというのが2です。

2と3は実質ほぼ近しくなると思いますが、元請けベンダーによってはほとんど何も設計せずに丸投げという場合もあるでしょう(笑)。

## ソフトウェア方式設計とソフトウェア詳細設計
最後に共通フレームにおけるソフトウェア方式設計とソフトウェア詳細設計です。
共通フレーム2013ではソフトウェア方式設計プロセスのタスクは以下からなると記述されています（「2.4.3 ソフトウェア方式設計プロセス」より）。

* ソフトウェア構造とコンポーネントの方式設計
* 各インタフェースの方式設計
* データベースの最上位レベルの設計
* 利用者用文書（暫定版）の作成
* ソフトウェア結合のためのテスト要件の定義
* ソフトウェア方式設計の評価

また、ソフトウェア詳細設計プロセスのタスクは以下となっています（「2.4.4 ソフトウェア詳細設計プロセス」より）。

* ソフトウェアコンポーネントの詳細設計
* ソフトウェアインタフェースの詳細設計
* データベースの詳細設計
* 利用者用文書の更新
* ソフトウェアユニットのテスト要件の定義
* ソフトウェア結合のためのテスト要件の更新
* ソフトウェア詳細設計及びテスト要件の評価

いわゆるアーキテクチャ設計に該当する内容や、インタフェースやコンポーネントの概要レベルの設計を行うのがソフトウェア方式設計プロセスで、それらを詳細化するのがソフトウェア詳細設計プロセスであると読み取れます。
これは、前節で書いた「ハイレベルな設計と詳細な設計」という分け方とほぼ同じでしょう。

## 設計の分類
以上より、ソフトウェアの設計活動およびその成果物は以下の2つの軸で分類ができそうです。

* 外部仕様か、内部仕様か（設計の観点、視点）
* ハイレベルな設計か、詳細な設計か（設計の抽象度）

![設計の分類](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176589/63c28af4-3637-7c26-c359-baa55a2cd391.png)


次章では、上記分類を使って様々な設計モデルを見ていきたいと思います（分類に関しては、筆者の実経験には基づくものの、あくまで主観的な分類です）。

# 様々な設計モデル
筆者の経験に基づき、業務システム開発においてよく使われている、あるいは過去によく使われていた設計モデルを見ていきます。

## クラス図
![クラス図](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176589/29b2aecd-5937-d48e-e9ef-1c452f94413a.png)

UMLの**クラス図**は、クラスの静的な構造を表現したモデルであり内部設計にあたります。
抽象度はケースバイケースで変わります。コンポーネント間の関係を概略レベルで描くこともあれば、実際のソースコードと一対一に対応するような詳細なクラス図を描くことも場合によってはあるでしょう。

概略レベルで描く場合、わかりやすさのため、以下のように日本語で記述することも多いでしょう。属性やメソッドは全ては記述せずに、主要なものだけに絞ります。全体的なクラスの関係性や責務の割当てが妥当かどうかを見ることが主眼であり、細かい情報はノイズとなるからです。

<img width="499" alt="クラス図" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176589/aa4366ee-6bcc-9da6-f55a-8bef11f62e27.png">

## コミュニケーション図・シーケンス図
![コミュニケーション図・シーケンス図](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176589/7d06edc2-e99b-f96f-598f-6bd0d3eb19a3.png)

UMLの**コミュニケーション図**と**シーケンス図**はどちらもオブジェクト間の相互作用を表すものです。クラス図が静的な構造を表現するのに対し、これらの図は動的な振る舞いを表現するために使われます。
ある振る舞いを表現するのに、コミュニケーション図とシーケンス図のどちらも適用可能です。処理の順序性に注目したい場合はシーケンス図が、オブジェクト同士の関連性に注目したい場合はコミュニケーション図を採用するのがよいでしょう。
また、ループ処理や条件判断などはシーケンス図の方がわかりやすく表現できると思います。

<img width="488" alt="コミュニケーション図" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176589/bc656704-f74a-a037-2147-76f9a0098ead.png">

コミュニケーション図・シーケンス図も概略レベルで書くケースと詳細レベルで描くケースがあると思います。しかし、あまり詳細過ぎると描くのが大変ですし、見る方にとってもノイズが大きくなってしまいます。
レガシーシステムを分析する際にツールを使ってシーケンス図をリバース出力するようなことはありますが、それ以外で詳細なシーケンス図を作成する動機は少ないでしょう。

筆者の個人的な好みはコミュニケーション図の方です。オブジェクトの発見と責務の割当てという設計行為をインクリメンタルに進めやすいというのがその理由です。一方でシーケンス図は、すでに設計が完了した内容を図に起こすのに向いていると思います。
このような理由から、コミュニケーション図は後述するCRCの手法とも非常に相性がよいです。

## アクティビティ図
![アクティビティ図](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176589/7ff5a79b-af4e-0633-564e-e2e5d3cdfcd1.png)

UMLの**アクティビティ図**は、どちらかというと要求分析で利用されることが多いのではないでしょうか。業務フローの記法としてアクティビティ図を利用するプロジェクトも多いのではないかと思います。
設計用途だと、バッチ処理の大まかな処理フローを記述するのにアクティビティ図を使用している例を見たことはあります。この場合はフローチャートの代替ですね。ただし、その用途ではフローチャート図の方が表現力に富むと思います。

設計から少し話がずれますが、ソフトウェア開発プロセスにおいて、バグ改修フローなどのワークフローをアクティビティ図を使って表すことは多いですね。他にもBPMの記法なんかもアクティビティ図に近いものがありますし、**複数の登場人物が協調して処理を遂行するフロー**を表すのも適しているでしょう。

<img width="514" alt="アクティビティ図" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176589/58fc6e99-602c-d02a-e589-73b604abe880.png">

## ステートマシン図
![ステートマシン図](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176589/4bd208ff-4cab-8952-201d-706c2fd8c2d8.png)

UMLの**ステートマシン図**はアクティビティ図と表記が似ていますが、その名の通りオブジェクトの状態遷移を表すためのモデルなので、状態および遷移を明確に仕様化する記法が提供されています。
一般にオブジェクトの状態（ステート）はアプリケーションの振る舞いに影響を与えるため、外部仕様として記述してユーザーや業務エキスパートと合意を取るためにステートマシン図を使います。
もちろんユーザーには見えないシステム内部の状態遷移を表すのにも使用できますが、その用途ではそれほど使われていないように思います。

## データフロー図（DFD）
![DFD](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176589/f03bf1e8-60dd-754b-ea0e-cb8974ac301e.png)

**データフロー図(DFD)**は構造化分析・設計の手法で用いられる、古くから存在する記法です。筆者がエンジニアになりたての頃は、既存システムの設計書としてよく見ましたが、最近はあまり見かけなくなりました。
その名の通りデータの流れを示すことを主目的とした図ですが、間に介在する機能や外部アクターも表現されるため、全体を見渡しやすいという特徴があります。
DFDには複数の詳細度レベルがあって、レベル1だとシステムのアクター、ユースケース、主要エンティティといった感じの粒度となるため、システムの全体を俯瞰できる機能関連図としても使えそうです。

<img width="456" alt="DFD" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176589/b7ddbd5e-460d-ad08-4f44-845441b189c6.png">

DFDのレベルを下げるほど、内部設計寄り・詳細設計寄りになるでしょう。

## フローチャート
![フローチャート](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176589/5c65e362-f9d1-ca11-ecc8-cf0a76d8b3b8.png)

**フローチャート**も古くから存在する構造化手法の図です。データフロー図の主たる関心がデータの流れであったのに対し、フローチャートでは処理そのものに注目します。
概略レベルでも詳細レベルでも使用できますが、古くからプログラム設計（詳細設計）の中心的な設計書として利用されてきました。

![フローチャート](https://upload.wikimedia.org/wikipedia/commons/thumb/5/5b/Jis-flowchart-fixed.png/220px-Jis-flowchart-fixed.png)
（図は[Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%95%E3%83%AD%E3%83%BC%E3%83%81%E3%83%A3%E3%83%BC%E3%83%88)より拝借）

最近はフローチャートで書かれた詳細設計書を見ることはめっきり減りましたが、プログラミング初心者が処理の流れを把握するには、今でも有益な図だと思います。

## ER図
![ER図](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176589/20b122b1-e6ad-87ec-26ae-9068df6bbb62.png)

**ER図**には複数の記法があり、IDEF1X記法やIE記法などが有名です。業務系のエンジニアであればER図には慣れ親しんでいることでしょう。ER図は、概念ER図、論理ER図、物理ER図に分けられます。

概念ER図はシステム化対象領域の概念をモデル化したものですが、概念モデルの記述にはUMLのクラス図を使うことが最近では一般的でしょうか。

論理ER図は、概念モデルをインプットとして、RDBMSのテーブルに変換することを意識した中間モデルです。論理ER図ではテーブル名やカラム名は日本語で表記します。論理ER図は実際のテーブル構造と1対1に対応している必要はありません。むしろ、多対多の関係を関連テーブルに変換せずにそのままにしておくなど、モデルのわかりやすさを優先することがあります。

UMLで描いた概念モデルでは汎化関係が頻繁に登場しますが、RDBMSで汎化関係を直接実現することはできないので、パターンを使ってテーブル構造に変換をします。下の図はClass Table Inheritanceパターンを使って汎化関係をテーブルに変換した例です。

<img width="772" alt="class2erd.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176589/51547253-23ae-0f80-5eb7-ef8642ec9491.png">

物理ER図は、RDBMS上のテーブルと1対1に対応する詳細モデルです。カラムの型も対象とするRDBMSで扱える実際の型を指定します。ERモデリングツールで描いた物理ER図からは、テーブルや制約を生成するDDLを出力することが可能です。

ER図はシステム内部のデータストアの構造を表現したものなので内部設計に位置づけましたが、システムの保守をしていく上では重要な成果物であり、エンドユーザー企業へも納品されるのが通常です。また、データ分析用途でユーザーが利用するテーブル（またはビュー）や、他システムから読み書きが行われるインタフェーステーブルは外部仕様的な意味合いが強くなります。

関連する設計成果物として、

* テーブル一覧
* テーブル定義書

なども作成します（ツールで出力することが多いです）。これらも開発時だけでなく保守時にも必要な成果物です。

## アーキテクチャドキュメント
![アーキテクチャドキュメント](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176589/b0f96639-d949-a27c-6613-ed5e78e8da07.png)

アーキテクチャ設計は幅広いテーマなので、ここではどんな設計書を作成するかを簡単に記すのにとどめます。

概略レベルでは以下のようなドキュメントを作成します。

* アーキテクチャ設計書
* 方式設計書

非機能要件に基づくシステム全体の構成や、ソフトウェアモジュールの配置構成、アプリケーションアーキテクチャの概要、利用するテクノロジースタックといった、アーキテクチャに関わる決定事項をアーキテクチャ設計書にまとめます。
また、主に非機能要件に基づく技術的な課題に対してどのような方式で解決するかを設計したものが方式設計書になります。例えば、トランザクション制御方式、バッチ処理方式、権限制御方式、といった具合にテーマ単位にハイレベルな設計を行います。

詳細レベルでは以下のようなドキュメントを作成します。

* 実装ガイドライン
* 命名規約
* コーディング規約

これらは、詳細設計・実装工程に入っていくにあたり、開発者向けのガイダンスとなる資料です。

## UI設計
![画面設計書](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176589/fc3ad958-5397-2f5f-a619-25757e423d21.png)

UIは要求でしょうか。それとも設計でしょうか。

ユーザーが欲しいものはUIそのものではなく、UIを通じて達成される目的（業務システムであれば何らかの業務が遂行できること）ですから、その意味でUIは設計です。ただし、現代のシステム開発ではユーザー体験が重要視され、タッチポイントとなるUIの重要性は以前と比べ益々高まっています。また、開発規模を見積もる上でも重要な構成要素であるため、要求定義工程において以下のような成果物を作成することが多いです。

* 主要な画面遷移図
* 主要画面を対象としたUIモックやワイヤーフレーム
* UI設計方針

設計工程では以下のような外部仕様をまとめ、画面設計書として文書化します。

* 画面一覧
* 画面遷移図
* ワイヤーフレーム
* 画面項目定義
* 画面アクション定義

## ロバストネス図
![ロバストネス図](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176589/2b9bd0c1-af8d-1c58-b67c-efe4ad5a4500.png)

**ロバストネス図**はIvar Jacobsonによって生み出されたもので、書籍『ワークブック形式で学ぶ UMLオブジェクトモデリング』によると

> 「what（要求）」と「how（詳細）」のギャップを解消する

とあり、ユースケースモデルをインプットとして、シーケンス図やクラス図を記述するための予備設計として作成する図です。

ロバストネス図ではオブジェクトを以下の3つのいずれかに分類して専用のアイコンで表現します。

* 境界オブジェクト（バウンダリオブジェクト）
* 実体オブジェクト（エンティティオブジェクト）
* 制御オブジェクト（コントロールオブジェクト）

ユースケースをどう実現するかという観点で作成するモデルなので、システム全体ではなくユースケースの単位で作成します。そのユースケースに関わるアクターも登場させるのが特徴です。

<img width="733" alt="ロバストネス図" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176589/7cce41bd-b1f5-0362-449f-f7c14de5eda7.png">

## ポンチ絵
最後に、ポンチ絵です。フリーフォーマットで描く図全般を指します。

<img width="552" alt="ポンチ絵" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176589/63b9a2d0-5874-8973-c99e-0d191354c4f8.png">

ポンチ絵はオールマイティです。外部設計・内部設計・概要設計・詳細設計のどこでも使用できます。

外部設計で使用する場合、曖昧さを回避するために凡例を付けるようにしましょう。
ポンチ絵は、具体的なインスタンスレベルで記述するのがコツです。クラス図のようなタイプレベルで記述してしまうと、パッと見のわかりやすさというポンチ絵のメリットが半減してしまいます。

自然言語だけで書かれた仕様書は読みづらく、曖昧な記述によって誤解が生じることがあります。ポンチ絵やExcelの表をうまく使い、具体例を提示して仕様を補足すれば、誤解の発生余地も少なくなります。
なお、具体例によって仕様を記述しようという手法（Specification by Example）も存在します。

# ジャストインタイムの設計活動
アジャイル型開発プロセスでは内部設計・詳細設計を事前にしっかり行うことは稀で、通常はコードを書きながら同時に設計活動を行います。そのようなジャストインタイムの設計活動を支援する代表的なプラクティスを以下に挙げます。
（これらのプラクティスは、その発祥はアジャイル型開発プロセスですが、ウォーターフォール型開発プロセスでも活用することは可能です）。

## ペアプログラミング・モブプログラミング
**ペアプログラミング**はXP（エクストリーム・プログラミング）のプラクティスの１つで、二人一組でプログラミングを行うものです。キーボードを操作してコードを書く**ドライバー**と、指示を出す**ナビゲーター**の役割があります。これらの役割を比較的短い時間（10分〜30分程度）で交代しながら開発を進めていきます。

ペアプロの場合、ナビゲーター役が主に設計を担当します。
実装が難しい箇所の場合、ベテランがナビゲーター役を担当して実装をガイドするとよいでしょう（ここでいうベテランは単に年齢の話ではなく、対象領域における経験や知識が多い人を指します）。そうすることで、場面に適した設計パターンやその適用方法をドライバー役に共有することができます。

**モブプログラミング**はペアプロの拡張版で、複数人で集まってプログラミングを行います。キーボード操作を行う**タイピスト**と、それ以外の**モブ**とに分かれます。
ペアプロのドライバーと異なり、モブプロのタイピストは自分の意見を出してはならないというルールがあります（質問、問いかけはOK）。

モブプロの場合、より多くの人の知識や経験を引き出しながら、設計についてのコンセンサスを得ることができます。アーキテクチャ上重要な箇所や、複雑な業務ロジックの実装をモブプロで取り組むと効果があるでしょう。

#CRC
**CRC(Class Responsibillity Collaborator)モデル**は、インデックスカードを用いてオブジェクトの責務やオブジェクト間の相互作用をモデリングするツールです。
インデックスカードを以下のように三分割し、クラス名とその責務、協調するクラスを書き込んで行きます。

![CRC](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176589/7196f0de-e399-bc0c-02ad-55ae71318cce.png)

CRCは複数人でワークショップ形式で行うのに適しています。各々が担当するクラスを決めて、そのオブジェクトになりきってロールプレイングを行います。
ロバストネス分析と同様に、特定のユースケースを対象としてモデルを作成します。

## TDD
**TDD（テスト駆動開発）**もXPのプラクティスです。テストコードを書き、それを治具として活用することで**動作するきれいなコード**を作っていく開発の回し方です。

![TDDのサイクル.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176589/7f8acc14-a1a6-eb38-2d12-e5859c307204.png)
（図は [https://t-wada.hatenablog.jp/entry/clean-code-that-works](https://t-wada.hatenablog.jp/entry/clean-code-that-works) より拝借）

テストコードを書くこと自体は直接的な設計作業ではありません。テストを通る「動作する」コード（図の第4象限）から、リファクタリングによって**動作するきれいなコード**（図の第1象限）へ持っていく過程で設計を行います。
テストコードがあっても、それだけでは「きれいな」設計を生み出すことはできません。それを生み出すのは**パターン**や**パターンにつながるリファクタリング**です。ですから、様々なパターンに関する知識や過去にそれを使った経験を活用し、今目の前にある課題に適用できることが肝心です。
そもそも、第4象限から第1象限に向かわねばならないという動機は、**コードの不吉な匂い**を嗅ぎ取ることができるかどうか（パターン認識能力）に関わります。

経験値の低さを補う方法として、前述のペアプログラミングやモブプログラミングを活用するとよいでしょう。

## BDD
**BDD(振る舞い駆動開発)**もTDDの系譜を継ぐものですが、ユーザーから見たシステムの振る舞い（＝外部仕様）を受け入れ条件として記述することからスタートし、それを実現する内部のソフトウェアの構造や振る舞いをTDDで少しづず組み立てていくやり方です。

```gherkin
Feature: クレジットカードで購入

  Scenario:
    Given ジョンは『リファクタリング』をショッピングカートに追加する
    And 登録済みのクレジットカードを決済手段として選択する
    When 注文を確定する
    Then 購入が完了する
    And 登録済みのクレジットカードで決済される
```

ユーザーストーリーの受入条件を上記のような自然言語で記述し、ユーザーやドメイン専門家と合意を取ります。開発者はCucumberなどのBDDツールを利用して受入条件を実行可能なテストコードに対応付けます。その先はTDDによって内部のソフトウェアコンポーネントを実装していき、最終的に自動化した受入テストがパスするようになったら、ストーリーの実装完了となります。
（受入テストが外側にあり、ユニットテストが内側にあるBDD/TDDの開発サイクルを**TDDのダブルループ**と呼ぶことがあります）。

BDDと組み合わせて行うTDDでは、**モックオブジェクト**を多用して未だ存在しないオブジェクトとの相互作用をジャストインタイムで設計していく作法もあり、一般的なTDDと比べるとより直接的な詳細設計の側面があります。このあたりは詳しく書くと長くなるので別の機会としたいと思います。

# 誰のための、何のための設計か
設計という行為やその結果生み出される成果物は、ソフトウェアに関与する誰かしらのステークホルダーを対象とし、彼らに対して何らかの価値を提供するものであるはずです。その観点を意識して必要十分なだけの設計を行うことが重要です。

## ソフトウェアの振る舞いについてユーザーと合意する
ソフトウェアを利用するユーザーの要求を満たすため、ソフトウェアに期待される振る舞いを文書化して合意を取ります。合意を取るユーザーは、エンドユーザーのこともあれば発注元の代表者かもしれません。
ユーザー観点で見たソフトウェアの振る舞いなので、すなわちそれは外部仕様ということになります。

実際にどんな成果物を作るかは、開発プロセス（ウォーターフォール型／アジャイル型）や契約形態、業界・業種、企業文化などによって異なります。
ウォーターフォール型では画面設計書などの文書を作成し、かちっとしたレビュー承認プロセスを踏むことが多いでしょう。アジャイル型ではユーザーストーリーに記述した受入条件とUIモックをもとに合意を取って開発を進め、イテレーション内でユーザー自身が受入を行うことで、文書化やレビューを省力化する傾向があります。

## 開発者に仕様や方針を伝える
多重請負構造において外部設計を行う人（業務SE）と内部設計・実装を行う人（プログラマー）が分かれている場合、何を作るかを示す公式な文書が必要です。これには、ユーザーと合意を取った外部仕様をまとめた文書がそのまま使用できます。
外部仕様を実現する上での大まかな処理方針を付け加えることもあります（概略レベルの内部設計にあたる）。
これにシステム全体としての方針（アーキテクチャ設計書や方式設計書）を合わせ、それらを総称したものが一般にいう**基本設計書**のイメージでしょうか。

この場合に注意すべきなのは、What（外部仕様や概略、方針）を伝えるのに注力し、How（詳細な内部設計）に踏み込まないことです。外部仕様を満たし方針に沿っていさえすれば、どのように実装するかはプログラマーの裁量、というよりプログラマーの責務そのものです。
ソースコードを書けない（あるいは、現在は書いていない）SEが、擬似コードのような詳細処理フローを基本設計書に書いてしまうダメな例を、筆者は過去に何度も目撃しました。

## 自分が実装を進める上で必要な設計を行う
基本設計書を受け取ったウォーターフォール型開発のプログラマーであれ、ユーザーストーリーをもとに実装に入るアジャイル型開発のプログラマーであれ、いきなりソースコードを書き始められる人は少ないでしょう。具体的にどんなソフトウェアコンポーネントに分割し要件を割り当てるか、コンポーネント同士がどのように関わり合うか、を考えることが内部設計・詳細設計にあたります。

この場合の設計はコードを書いてしまえば不要となるものなので、余り手をかけず、ホワイトボードやノートにラフスケッチするようなやり方を筆者は推奨します（会社の開発プロセスや品質管理プロセスの規定、元請けとの納品物の取り決め等により公式な設計文書作成が求められるケースもあるでしょうが）。

# まとめ
設計とは何なのか、どんな技法があるのか、何の目的でやるものなのか、についてあれこれ書いてみました。
それぞれの技法について詳しく知りたいかたは、参考文献を読んで頂くとよいと思います（良書ばかりです）。
何か質問などあれば、本ページのコメントや[筆者のTwitterアカウント](https://twitter.com/tyonekubo)宛にでも連絡頂ければ可能な限り回答します。

# 参考文献
| 番号 | 書名・ページ名 | 著者・執筆者 | 出版社・メディア | 説明 |
|:----|:------------|:-----|:------|:---------|
| 1   |[共通フレーム2013](https://www.ipa.go.jp/sec/publish/tn12-006.html)||IPA SEC|「ソフトウェア、システム、サービスの構想から開発、運用、保守、廃棄に至るまでのライフサイクルを通じて必要な作業項目、役割等を包括的に規定した共通の枠組み」の解説書|
| 2   |[システム設計の謎を解く 強いSEになるための機能設計と入出力設計の極意](https://www.sbcr.jp/product/4797393514/)|高安厚思|SB Creative|設計にフォーカスした書籍です。実際に業務システム開発の現場で行われる設計作業が一通り解説されており、サンプルも豊富です。設計を一から勉強したい人にお薦めです。|
| 3  |[UMLモデリングのエッセンス 第3版](https://www.shoeisha.co.jp/book/detail/9784798107950)|Martin Fowler|翔泳社|UMLの定番本といえばこれ。|
| 4  |[ワークブック形式で学ぶＵＭＬオブジェクトモデリング](https://www.sbcr.jp/product/4797320192/)|Doug Rosenberg, Kendall Scott|SB Creative|ユースケース駆動の開発プロセスであるICONIXプロセスの概略を学ぶための本。第５章でロバストネス分析が取り上げられています。|
| 5  |[エンタープライズアプリケーションアーキテクチャパターン](https://www.shoeisha.co.jp/book/detail/9784798105536)|Martin Fowler|翔泳社|エンタープライズアプリケーションの開発でしばしば起こる問題を解決するパターンを集めた本です。十数年前に出版された本なので最近注目されているヘキサゴナルアーキテクチャやクリーンアーキテクチャなどはカバーされませんが、今だに色褪せない名著です。通称PoEAA。|
| 6   |[モブプログラミング・ベストプラクティス ソフトウェアの品質と生産性をチームで高める](https://shop.nikkeibp.co.jp/front/commodity/0000/P89640/)|Mark Pearl|日経BP|モブプログラミングの始め方や適用のポイントが書かれた本です。|
| 7   |[アジャイルモデリング公式サイト CRCモデル](https://www.ogis-ri.co.jp/otc/swec/process/am-res/am/artifacts/crcModel.html)| |オージス総研 |Scott Amblerの書籍『アジャイルモデリング』の公式サイト（翻訳版）にCRCについての説明があります。 |
| 8   |[テスト駆動開発](https://shop.ohmsha.co.jp/shopdetail/000000004967/)|Kent Beck|オーム社|XPの考案者であるKent Beck氏によるテスト駆動開発の解説書。訳者の和田卓人氏による「付録C」では、TDDの歴史や本書の読み方、TDDとの向き合い方などがまとめられています。|
| 9   |[動作するきれいなコード: SeleniumConf Tokyo 2019 基調講演文字起こし+α](https://t-wada.hatenablog.jp/entry/clean-code-that-works)|和田卓人|ブログ |「動作するきれいなコード」とはどういう状態なのか、どうやってそこに至るのかが非常にわかりやすく説明されています。|
| 10  |[リファクタリング 既存のコードを安全に改善する（第2版）](https://www.ohmsha.co.jp/book/9784274224546/)|Martin Fowler|オーム社|リファクタリングについて網羅された名著です。|
| 11  |パターン指向リファクタリング入門~ソフトウエア設計を改善する27の作法|Joshua Kerievsky|日経BP|早い段階からデザインパターンを決め打つのではなく、リファクタリングを通してコードを改良しながらデザインパターンを適用していく、という趣旨の本です。残念ながら絶版となっているようです。|
| 12  |[いまさら聞けないTDD/BDD超入門](https://www.atmarkit.co.jp/ait/series/1431/)|井芹洋輝,きょん,STAR（テスト自動化研究会）|atmarkIT|TDD/BDDの基礎から実践上のポイントまで全４回の記事にまとめられています。|
| 13  |[実践テスト駆動開発 テストに導かれてオブジェクト指向ソフトウェアを育てる](https://www.shoeisha.co.jp/book/detail/9784798124582)| Steve Freeman, Nat Pryce|翔泳社|モックオブジェクトを使って外側から実装を進めているスタイルのTDDに関する書籍。サンプルコードがJavaのSwingなので少し読みづらいかもしれません。|
| 14 |[増補改訂版Ｊａｖａ言語で学ぶデザインパターン入門](https://www.sbcr.jp/product/4797327030/)|結城浩|SB Creative|結城浩さんによる、GoFのデザインパターンの入門書です。そのわかりやすさに定評があります。|