連続記事#3 仕様から概要設計する

# 背景・目的
自社向けの勉強会でなにかテーマを決めて、ソフトウェア開発の上流工程から下流工程まで説明する連続講座を開催し、自分のスキルアップしたいと考えました。
講座参加者に学びになれば尚良、と考えました。この記事は講座資料を再掲・補足説明する位置づけにしたいと考えています。

現在予定している講座はつぎのとおりです。

 * 要求の理解　
 * 要求を仕様化する
 * 設計(概要設計) ★いまここ
 * 設計(詳細設計)
 * テスト
 * 実装

今回の講座の資料はこちらにアップロードしました。

[組み込みソフトウェア基礎_【連続講座 #3】仕様から概要設計する](https://www.docswell.com/s/juraruming/ZP78L5-2022-07-21-205358)

前回は[要求を仕様化する](https://qiita.com/juraruming/items/d0cb03798850c9d0b5d5)というタイトルで要求の仕様化について書きました。
今回は設計についての考察、概要設計について書きます。概要設計の意味合いについては後述します。

# テーマについて
テーマは**既存組込み製品(CQ EVカート)のマイコンを変更する**と決めました。
テーマ設定理由、EVカートについての説明は前回記事　**要求を仕様化する**の[こちらのリンク](https://qiita.com/juraruming/items/d0cb03798850c9d0b5d5#%E3%83%86%E3%83%BC%E3%83%9E%E3%81%AE%E8%AA%AC%E6%98%8E)を参照ください。 

# 設計とは?
設計について勉強会を開催するにあたり、設計について考えてみました。
私が考える設計(ソフトウェアの設計に限らず)はつぎです。

 * 目的に応じて抽象化・取捨選択して表現する(例、建物の模型)　≒　モデル化
 * 部品の構造を明確にする
 * 部品同士の関連、数を明確にする
 * 部品が持つ特徴を明確にする
 * 部品が持つ振る舞いを明確にする
 * その他

設計がどんなことを指すのかは自分の中で整理がつきました。次に自分が思ったのが**何故設計するのか?**　でした。つぎのことを考えました。

 1. 複数人で物・システムをつくる際の資料として使う
 1. 個人開発では未来の自分が過去の経緯を思い出せる資料として使う
 1. 複雑な物・システムを複数人で開発する際の資料として使う
 1. 拡張の際に変更点を特定するために使う
 1. その他

1は複数人で知見を共有するためと考えた。
３は複雑なもの・システムを分解し、役割分担で作業をすすめるためと考えた。
４は物・システムを拡張する際に変更点を特定し、変更点・他の部品への影響・作業量の見積りをするためと考えた。

## まとめ
設計について個人的な考えをまとめます。

 * 複雑・高度な物・システムをつくるうえで設計は必要な技術。
 * 複雑・高度な物・システムは一人ではつくれない。開発チームで認識合わせするためにも設計図は必要な技術。


# 良い設計事例
日常生活の中で良い設計と個人的に感じた事例を書きます。
ここでいう設計はソフトウェアの設計に限定しません。

## USBデバイス
USBメモリやその他のUSB機器です。
USBメモリは接続するPC(USBホスト)が変わっても問題なく使えます。
**USBの仕様に準拠していれば使える**という点が良い設計と感じます。
USBは訳すと汎用シリアルバスという意味合いになると思いますが、会話の文脈でUSBメモリを指すときにUSBメモリではなくUSBと言ったりすることがあると思います。
こういった点からも世の中に広く認知される**汎用的な設計**を実現している例と思いました。

## コンセント
コンセントに挿せば様々な機器が使えます。
コンセントは挿される機器を限定しません。機器側はコンセントから供給される電圧を意識してハードウェアの電源周りを設計すると思います。
当たり前ではありますが、コンセントと挿される機器の間は**疎結合**な関係があると感じました。
ソフトウェア設計をする際はこの構造を真似したいと思いました。


## テレビCM　アイフル　そこに愛はあるんか　シリーズ
良い設計は物質的なものだけに限りません。
良い設計をしているなと個人的に気になったCMは**アイフルさんのそこに愛はあるんかシリーズ**です。
　【そこに愛はあるんか】という汎用的・キャッチーなワードをベースにして様々なCMバリエーションを展開しています。
youtubeの再生リスト数を調べてみると21本の動画がアップロードされていました。

https://youtube.com/playlist?list=PLNEz4rfDju6Ir__ppoOsYTgP4i2jFPwdP

拡張性も抜群に良い!!!
その他、私が良い設計と思う理由を書きます。

 * そこに愛はあるんかというシンプルなインターフェースを持ち、拡張しやすい。
 * 女将さん(大地真央さん)・板前さん(今野浩喜さん)の責務が明確

現在のソフトウェア開発は派生開発が開発の大部分を占めると思いますので、シンプルで変更に強い構造を持つことはビジネス戦略的にも大事だと個人的に思います。


## OSI参照モデル
OSI参照モデルは**The設計のお手本**と思います。
OSI参照モデルを初めて学んだときはこのような階層化・役割分担をしている意味を理解できませんでした。
ある程度業務経験を積んでOSI参照モデルを見直すと設計とはこういうことなんだ、と感じられました。

つぎはOSI参照モデルから学べる設計の勘所だと思います。
 * 階層の構造。階層化する意味
 * 各階層でやるべきことが明確に決まっている。役割分担。
 * 抽象化と具体化のお手本のような設計

OSI参照モデルの説明図を引用させていただきますが見ているだけで良い設計だなぁ、と思います。

[引用) OSI参照モデルとは？TCP/IPとの違いを図解で解説](https://www.itmanage.co.jp/column/osi-reference-model/)

階層構造になっており各層で役割分担されています。
![OSI_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171866/8b57df18-7e3d-d645-a5e1-ee1e6b713142.png)

役割分担は構想ほど知識を持つ層で、低層は実現手段を持つ層になっています。
![OSI_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171866/b5802502-f178-fe20-72dc-d4faa89cc21b.png)

高層はユーザの目的を達成するための目的を知っており、低層は高層の目的を達成するための手段を知っています。
高層はなにをするか(Why)の視点をもっており、低層はどうするか(How)の視点を持っています。
TCP/IPのパケットが高層から低層に向かうにつれてデータが付加されていく様子がわかります(目的を達成するための手段の情報が付加されていく)。

![OSI_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171866/72c11986-2a21-85ae-68f0-bbf7525c5ee5.png)

## 良い設計事例のまとめ
良い設計のエッセンスをまとめてみました。

 * 適切な粒度になっている(大きすぎず小さすぎず)。→テストもしやすい
 * 拡張に開かれている(変更しやすい)→素早い開発スピードで競合に勝てる製品展開
 * わかりやすい抽象化→理解しやすい
 * OSI参照モデルの上の層はシステムが提供する目的、下の層は目的を達成する手段

このような設計を目指したいものです。


# 設計の手順
設計とは何か?は前の章まででなんとなく自分の中で整理がつきました。
では設計は**どんな手順で、具体的に何をすれば良いか?**　を整理したいと思います。

## 設計って具体的に何をすれば良いの?
本を読んだり、こうすると良い設計ができそうだなぁと思ったことを書きます。

【何をするのか(Why)】の視点と　【どうするのか(How)】の視点で開発対象の分析・設計図の検証を繰り返す。
顧客の要求を満たせればOK(その他の基準、例えば社内の設計標準などもある)。
設計に絶対解はなく、あるのは最適解。それが楽しい・難しいところ。

1 + 1の答えを求める教育を受けてくるとなかなか設計を学ぶマインドも身に付くことが難しい気もします。
xx + yy = 2のように回答2に行き着くまでの複数のプロセスの中から最適なものを選択することが設計だと思っています。

## 今回の【概要設計】の位置付け
今回のタイトル概要設計の概要ですが会社・組織によって意味合いが変わると思います。
今回はつぎのような意味合いで概要設計とします。

設計は【何をするのか(Why)】の視点と【どうするのか(How)】の視点で開発対象の分析・設計図の検証を繰り返す、と前の章で書きました。
今回は【何をするのか】の視点で設計(≒分析)をしていきます。
実際に【どうつくるのか】の視点での設計は次回講座　**【連続講座 #4】概要設計から詳細設計を行う** で話したいと考えてます。

## 設計手順
どのようなアプローチで概要設計しようと考えた時に**静と動**の観点で進めようと思いました。
静と動は次の意味合いです。

 * 静はソフトウェア部品の構造、部品同士の関係・数に注目する。
 * 動はソフトウェア部品の動き・振る舞いに注目する。

### 設計手法
どのような手法で設計していくのかもポイントかと思います。
有名で実用的な手法としてはつぎがあるかと思います。

 * 構造化手法による分析
 * UMLによる分析。オブジェクト指向言語(例. C++)と接続が良い。

今回は私がやってみたいので**UMLによる分析**で進めます。
静的な分析ではつぎのUMLの図を使い分析していることをよく見かけます。
　* クラス図
　* オブジェクト図

動的な分析ではつぎのUMLの図を使い分析していることをよく見かけます。
 * 状態遷移図
 * コミュニケーション図

### 【疑問】何故、概要設計では"何をつくるのか"の視点に注目するのか?
概要設計においては【何をつくるのか】の【目的】に注目し、【どのようにつくるのか】の【手段】は詳細設計で考えると書きました。設計本にも書いてあると思います。
これって何でだろう?とふと疑問に思ったので考えてみます。
ここを言語化できる・できないでは設計のアウトプットに違いが出てきそうです。

 1. 手段に注目して設計すると（階層構造を意識しないと）スパゲティなプログラムになりそう。
例) 階層を無視した無秩序な関数呼び出し。
 1. ソフトウェアの再利用がしにくいつくりになってしまいそう。該当プロジェクトだけでしか使えないソフトウェアになり、他社との競争で優位に立てない。せっかく開発したものが会社のソフトウェア資産にならない。
 1. その他

# 概要設計の具体例
勉強会の開発テーマはEVカートでした。今回はつぎの図を書きました。

 * オブジェクト図
 * 状態遷移図

UMLを使い図を書きましたが文法的に間違っているかもしれません。その際は赦してください。

## オブジェクト図
EVカートのオブジェクト(これ以上具体化できないと思う抽象度)同士の関係を整理して図にしてみました。
簡単に説明します。

![オブジェクト図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171866/f97850b9-865b-9b38-906a-ee2301cbf362.png)

 * ホールセンサ(N・S極を検出する)でモータの位置を検出する
 * モータ位置からFETの通電パターン(ON・OFF)を認識する
 * ２ms周期でアクセル開度を取得・設定する
 * アクセル開度によりFET　High側のON時間が決まる→結果、EVカートが走る


## 状態遷移図
EVカートの制御基板を電源ONしたときからの状態遷移図です。
電源ON時にアクセルを開けていると電源ONと同時にモータが駆動し危険なため、電源ON後にアクセルが閉じていることを確認しないとモータが駆動しないようにしています。
モータが駆動中になったら2ms間隔でアクセル開度を再設定します。

![状態遷移図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171866/957b487f-61a7-8f24-85cc-1e228ec4efe4.png)

今回はオブジェクト図、状態遷移図を書きました。
クラス図・コラボレーション図は必要かと個人的に考えています。
要求仕様を満たせるか、設計図同士で矛盾がないか、開発対象の本質(目的)を表しているか・手段になっていないか、などの観点で図を見直し設計を【洗練】していきます。


# 設計時に考慮すること
設計する時に考慮すると良いと思ったことはつぎのとおりです。

## 抽象化・具体化の視点で分析する
組込みシステムでは一番具体的なところ(低レイヤ)はデバイス(デバイスドライバ)になると思います。

 * このデバイスを動かす手段は?→このデバイスを動かす目的は?

のように低レイヤから上のレイヤを考えていく方法(ボトムアップ的な思考)もあると思います。逆に上のレイヤから下のレイヤを考えていく方法もあります。
組込みシステムはハードウェアが明確になっていることが多いと思うのでボトムアップで開発対象の目的を考えても良いのかなと思いました。
いずれにしても【抽象⇄具体の世界を行き来する視点】が重要だと考えます。

## 要求仕様を満たす最適解を時間と相談して考える
設計に絶対解はないと考えています。あるのは最適解だと考えています。
要求仕様満たしているなら時間と相談し設計を終えて次の工程に進むように気をつけたいと思いました。
そうしないと設計に時間をかけすぎてしまうと思ったからです(※)。

※設計に時間をかけるべきだと思いますが限られた開発スケジュールの中で【度】をこさないこと、という意味合いです。

# 次回予定
**仕様から概要設計する**は如何でしたでしょうか?
なにかお役にたてると嬉しいです。よければ感想などをコメントくださるとありがたく、猫のように喜びます。

次回の自社向け勉強会は8/25(木)に開催を予定しています。その頃にまた勉強会の内容を記事化したいと考えています。
勉強会の内容はつぎを考えています。

 * 要求仕様の理解
 * 要求を仕様化する　
 * 設計（概要設計） ★いまここ
 * 設計（詳細設計） ※次はこれ!!!
 * テスト
 * 実装

次回は今回の概要設計をベースに**詳細設計**をやってみようと考えています。
概要設計は【何をするのか(Why)】の視点でしたが、詳細設計では【どうするのか(How)】の視点で設計したいと考えています。

最後まで長文を読んでいただきありがとうございました。次回もよろしくおねがいします。