「ソフトウェア工学の基礎」，という本を読んだ

こんにちは


今は亡き経営工学科(通称i科)の2015年卒のgangunです．

友人(明日の投稿者のkatsuyukiさんです)に誘われこのアドベントカレンダーに参加してもう3年目．

**枯れ木も山の賑わい**といいますか，とにかく今年もまた馳せ参じました．

ちなみに前回，前々回はこんなこと書いてました↓

2017年 [機械学習を仕事として遂行していく中で知っておくといいんじゃないかなっていうTips](https://qiita.com/gangun/items/ae95b53d229e990b7b12)
2018年 [集合をゼロからやり直そう](https://qiita.com/gangun/items/3c5c6f06a92700f67a79)

現在は渋谷勤務，直近ではとあるサービスの開発に携わっており，フロントエンドもバックエンドも両方進めている状態です．

まだまだ知らないことばかりで脳みそに汗をかきつつ仕事に励んでおります．


今回はタイトルの通り，[ソフトウェア工学の基礎](https://www.amazon.co.jp/%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E5%B7%A5%E5%AD%A6%E3%81%AE%E5%9F%BA%E7%A4%8E-%E5%B2%A9%E6%B3%A2%E3%82%AA%E3%83%B3%E3%83%87%E3%83%9E%E3%83%B3%E3%83%89%E3%83%96%E3%83%83%E3%82%AF%E3%82%B9-%E7%8E%89%E4%BA%95-%E5%93%B2%E9%9B%84/dp/4007304572/ref=dp_ob_title_bk)という書籍の内容の，序盤のほんのさわりについて書きます．

一周読んでみたのですがやはり相当に濃い内容でしたので，学生さん含め開発に携わる方々の関心を惹きそうな部分に絞って言及してみようかと思います．

書籍の内容に興味を持った方は是非購入して読んでみて欲しい．



### ソフトウェアとソフトウェア工学

#### ソフトウェアとは？

今の時代，「ソフトウェア」と言う言葉を聞いたことがない人はほぼいないでしょう．

しかし，「ソフトウェアとは一体何か？」と言う問いに，正確に答えられる人はそんなに多くないと思います．この点については独断と偏見です．

それもそのはずで，「ソフトウェア」という言葉を最初に使い始めたのが誰か，ということがまず明らかになっていません．(書籍内では諸説挙げられています)

なので，「ソフトウェアは一体何をするものなのか？」という点に主眼をおいて考えてみます．

書籍内の言葉を借りると，

「プログラミング言語という人工言語で書かれた抽象的な記述でありながら，コンピュータを通して実世界に直接働きかけることができるもの」

ということになります．

つまりソフトウェアは

「言語表現による創作結果という意味で小説や論文などの作品と類似する面を持ち」
「実世界への直接的な作用という機能から実利的な工業製品として生産される」

ような不思議な性質を持っています．

上記は，ソフトウェア開発を始めるときに

「言語による表現行為」(各プログラミング言語のお作法に則って処理を記述していく)
「人工物の設計開発」(全体の設計を考えて組み上げていく)

の二面を行っている点からも合点がいくのではないでしょうか．


### ソフトウェアプロセス

ソフトウェア工学が扱う対象の基本的な構成要素は，大きく分けて2つ．

- プロダクト(product) 
→エンジニアリングの過程で生成される中間製品や文書を含めた全ての生産物

- プロセス(process) 
→プロダクトを生み出す工程

「ソフトウェア開発のプロセス自身を方法論的な考察の対象にすることは重要である．」

#### ライフサイクルモデル

ソフトウェア工学の初期に「ライフサイクル」という概念が提唱されます．
この概念は，ソフトウェアの「開発計画」「設計開発」「運用」「保守」「最終的な廃棄」に至る過程を標準的なモデルとして表しています．
現在，企業などの開発組織における標準工程はなんらかのライフサイクルモデルに準拠して作られており，つまりは既存の工学におけるプロセスモデルを援用したものにほかならないということです．

ライフサイクルモデルはソフトウェア開発のあるべき姿・規範を示したものとみることもできます，
開発において，そのようなモデルを考える目的には以下のようなものがあります．

- 標準的なソフトウェア開発手順を定め，実際の開発担当者の作業をガイドする    
- 開発プロジェクトを管理するのに準拠する管理モデルとして用いる
- 開発の方法論，使用するツールと開発環境，標準文書体系などを標準的に定めるための基盤としての役割を果たす

このようなソフトウェアプロセスのモデルは，標準的なものをベースとしつつも，開発組織ごと，さらには個々ののプロジェクトごとに最適なものが設計される必要があります．

#### 落水型モデル

ソフトウェアのライフサイクルモデルのうち，最も古くからあり，現在も多くの企業で開発工程のベースとなっているモデルです．
(「ウォーターフォール型」という表記の方が馴染みが深い方も多いでしょうか．)

<img width="862" alt="スクリーンショット 2019-12-09 13.51.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122082/4315773b-53b4-5794-dd39-bffa9e1f27c7.png">

この図は典型的なものです．各ブロックで示される工程単位を「フェーズ」といいます．
また，テストフェーズを分解して

- プログラムに対するテスト -> 単体テスト
- 設計に対するテスト -> 統合テスト
- 仕様要求に対するテスト -> 受け入れテスト

とし，それぞれを対応するフェーズに合わせV字型のライフサイクルモデルとして描かれることもあります．
(受入テスト完了後に運用・保守のフェーズに進んでいきます)

<img width="976" alt="スクリーンショット 2019-12-09 13.52.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122082/e6c759b5-891b-f27d-6605-56061e818ddd.png">

「○○テスト」という言葉は，説明している文書などによって表記揺れがバンバン存在するので，「そういう感じなんだな」，って思ってもらう程度で十分です．職場・現場での語法に従う方が無難ではあります．

この落水型モデルにおいては，以下の2点が強調されています．

1. フェーズ間に明確な区切りを置くとともに，その間はきちんと形式化された文書で受け渡す．
2. フェーズの手戻りを極力なくす．

実際に開発業務に携わったことのある方も実感したことがあると思いますが，上記の要請には無理があり，落水型モデルそのものに問題があるという批判も少なくありません．
(ちょっと前の時期には界隈では「アジャイル」なんてワードもなかなかバズっておりましたでしょう．)


#### 落水型に代わるライフサイクルモデル


落水型のモデルには以下のような限界があるという指摘がなされてきました．

(特に)初期のフェーズの要求分析において，

- 「要求が定まらない」
- 「曖昧さが残る」
- 「プロセス進行の過程において変化する」

上記のようなケースは多々見られます．
そのようなときに，要求の確定->仕様としての文書化がなされていない状態で設計フェーズに進むことが許されないと，プロジェクト全体の進行に支障をきたすことになります．
また，開発の規模が大きくなるにつれて各フェーズ内の部分部分の進捗もバラ付きやすくなるのが自然であり，プロジェクト全体としてフェーズを同時に切り替えていくのはほぼ不可能です．
(一部機能の設計が未完了の状態で開発フェーズに進んでいく，など)

また，フェーズの手戻りの発生を無視したモデルと言うのも現実的ではありません．(手戻りを最小限に抑えると言う目標は理解できますが．．．)

以上より，落水型モデルは硬直的で現実にそぐわないということがわかってきます．
これまでのような批判・指摘を受け，落水型に代わるモデルとして以下のようなモデルが提案されています．


##### プロトタイピング型モデル

「プロトタイピング」とは，最終的なソフトウェアシステムを作る前に，「実験的に」，かつ「実際に動く」ようなシステムを作り，それを評価するプロセスのことをいいます．
このモデルでは，プロトタイピングの目的を「ユーザーの要求を明確にする」ことに絞って考えることが多いです．
プロトタイピングモデルとは，上記の意味合いを持ったプロトタイピングプロセスを要求分析フェーズに組み入れたライフサイクルモデルのことを指します．
要求仕様を確定させる目的のため，プロトタイプは繰り返し手直しされることになります．
ある程度の時点で仕様を固定し，以降は落水型モデルと同様のプロセスに沿って開発を進めます．
<img width="813" alt="スクリーンショット 2019-12-10 9.57.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122082/5a5584d0-904b-9298-dfb6-8aeb76068f76.png">

##### 逐次進化型モデル

要求分析~実装までの開発プロセスをただ一度だけ実行して運用システムを構築するのではなく，初めに小さな機能範囲のシステムを実現し，それを改良していくプロセスを繰り返すことにより，利用者の要求範囲の拡大や変動に対処しながら柔軟にシステムの完成度を上げていくというライフサイクルモデルです．

<img width="832" alt="スクリーンショット 2019-12-11 9.32.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122082/b1ee174c-413e-4fa2-c2c7-12b99203ac68.png">

「実際に動くシステムを利用者に早く提供する」という点で，上記2つのモデルは類似しているとも言えます．

しかし，プロトタイピングモデルは利用者の要求が曖昧な部分を優先的に取り上げてプロトタイプを作り，その要求仕様を詰めることを主眼においています．
逆に，逐次進化型モデルでは機能が明確であり，設計技術上不確定な点が少ない物を優先的に開発し，徐々に新しい機能を付加していくというアプローチをとります．

逐次進化型を極端に押し進めた開発プロセスが「極端プログラミング(extreme programming, XPと略称されます)」と言うものです．
オブジェクト指向に基づくソフトウェア開発の方法論で，以下のような方法が提唱されています．

- ソフトウェアの公開の計画をまず決めて，それに基づいて開発計画を定める．
- ソフトウェアの公開は小さい範囲で頻繁に行う．
- 開発プロジェクトを小さい単位の作業の繰り返しとして分割する．
- 開発に際し，まずテストケースを作成し，それを満たすコードを書いていく．テストケースが仕様を兼ねる．
- システムの再構成(refactor)を可能な限り追求する．

ここまでに挙げた手法により，非常に短いサイクルでの逐次進化と利用者への提供が実現されます．
その結果としてシステム全体がつぎはぎだらけになることを，頻繁な再構成によって防止します．
このようなソフトウェアプロセスを軽快プロセス(agile process)などと呼ばれます．


### 開発計画

これまでに，ソフトウェア開発のプロセスについて書いてきました．しかし，その開発そのものも「始めるかどうか」の意思決定があってこそです．
実際には「何を作るか」「なぜ作るか」について明らかにした上で，

- そのソフトウェアを開発すべきか
- あるいは，「開発すべきかどうか」を検討すべきか

が検討される必要があります．

開発にかかる様々なコスト，開発されたソフトウェアによって期待される価値などなど，様々な側面で検討が行われます．
ざっくりと言えば，ここら辺の意思決定には人間的要素による影響が非常に大きいのです．経営学・心理学・市場分析・一般問題発見とのその解決手法などが様々に交錯し，なかなか一筋縄では行かないのです．


##### 実際的な開発標準工程における初期フェーズ

開発計画を進める際に考慮すべき要因として，要求分析の結果以外に以下のようなものが挙げられます．

- 効果・利益
- コスト
- 期間・スケジュール
- 資源
- 経営，組織，市場，制度，社会などによる制約

したがってシステム開発の当初にすべきは，以上の要因を踏まえて「プロジェクトを実施するか否か」の意思決定を行うことです．
特に日本では，このフェーズが開発に係る関係者(経営者・開発者・関わりの深いユーザなど)による合意形成プロセスとして捉えられることが多いです．

システム化計画の出力としては，標準的に以下のような項目が記述されます．

- 背景
- 開発目的
- 対象領域
- 業務の現状
- すでにシステム化されている部分の現状
- 新たに開発すべきシステムの概要
- 効果
- 制約条件
- 開発・導入計画
- 開発費用の見積もり
- 必要とする資源

以上の作業のための作法やガイドラインをまとめたものが多くの企業でマニュアル化され，使われています．

##### コスト見積もり

開発費用の見積もりについては，「この方法にのっとれば完璧」というような決定的な方法がありません．
通常取られている方法としては

1. 開発するソフトウェアの規模を何らかの方法で見積もる
2. ソフトウェアの規模から，何らかの見積もり式で必要工数を算出する
3. 工数から，開発期間と投入要員数を決める

と言うものがあります．

まず，最初の壁はソフトウェアの規模を見積もることです．規模を何で測るかと言う点についてもいろいろご議論を呼ぶところではありますが，
最も一般的なものとしては原始プログラムの行数を尺度とするものです．
しかし，この時点ではまだソフトウェアは一切作られていないので，何らかの方法で予測しなければなりません．
そこで，機能点(function point)を数えると言う方法が実践されています．その数え方には流儀がありますが，

- 入力データの種類
- 出力データの種類
- ユーザ要求にシステムが応答する処理の種類
- アクセスするファイルの種類
- 考慮すべき他のシステムのインターフェース数

などのデータに重み付けを行って算出すると言うのが一般的です．
この機能点数とプログラム行数が比例関係にあるものと仮定して，その比例定数を過去のプロジェクトから推定して原始プログラムの行数を見積もります．
ソフトウェアの規模から必要工数を算出する式ですが，この関係は線形ではなく，必要工数Eとプログラム規模Sは

```math
E=aS^k
```

という指数関係にあることが経験的に知られています．(k >= 1)
この定数a, kを過去のプロジェクトから推定することになります．
必要工数Eの単位は人日や人月という要員の数に時間を乗じた値になりますが，この工数は「同じ仕事に対して，要員を増やせば比例して開発期間が短くなる」という暗黙の仮定があります．
しかしそれが実態に合わないことは古くから指摘されており，実際の開発(ある程度の規模であるとなお顕著である)に関わったことのある方なら深く納得いただけることかと思います．

実際には要員を増やすことで，その教育コストであったり，コミュニケーションのオーバーヘッドによって開発期間が延びてしまうというのがF.P.Brooks, Jr.という人物の主張です．
ここらへんの話は，「[人月の神話](https://www.amazon.co.jp/%E4%BA%BA%E6%9C%88%E3%81%AE%E7%A5%9E%E8%A9%B1%E3%80%90%E6%96%B0%E8%A3%85%E7%89%88%E3%80%91-Jr-FrederickP-Brooks/dp/4621066080/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=%E4%BA%BA%E6%9C%88%E3%81%AE%E7%A5%9E%E8%A9%B1&qid=1576112442&sr=8-1)」という書籍が詳しく書いているので一読されることをお勧めします．



#### 終わりに

ここまでつらつら書いてきましたが，(本の見た目の遊びのなさの割には)しっかりと現実のソフトウェア開発に即した内容であることがおわかりいただけたかと思います．

書籍ではこのあと，要求分析の手法や仕様について，そして対象領域のモデル化やデータ・制御フローの表現などなど，ソフトウェア開発に必要な内容が記されています．

現実世界の事象を用いた例題なんかもあるので，イメージがしやすいのではないかと思います．

エンジニアになると決めた人がいきなりこの本に取り掛かるのはキツイ思います(先に読むべき本はたくさんあります)が，一周流し読みするくらいでも十分な知識が得られるのではないかと思います．

「人気のプログラミング言語」や「フレームワーク」，はたまた弊社でも得意としている「機械学習」など**華やかなジャンル**というのは誰しもが注目するものです．

しかし，今回取り上げたような言わば**低レイヤー**な範囲の知識というものは，地味ではありつつも，時代が進んでいっても普遍的に使えるので，少しずつ身につけていくとより**筋肉質な**エンジニアを目指せるのではないでしょうか．

それでは，ごきげんよう．



-------------------
#### (以下宣伝)

弊社株式会社Nucoでは，プログラミング家庭教師サービスを立ち上げました．概要は下部に記しています．
今後ともどうぞご期待ください．

-------------------
2020年度から必修化されるプログラミング、学校側の制度や体制、環境は充分に整っているとは正直言いきれません。
国や学校は大きな組織ですので、環境が整備されるまではまだまだ時間がかかるでしょう。

しかし、現代はIT全盛の時代で、情報技術なしで成り立つ産業などありません。
これからの時代に生きる子どもたちは皆等しく情報技術に通じ、社会を変えていく力を身につけるべきです。

私どもは微力ながら、今の時代、これからの時代を生きる子どもたちの情報リテラシー向上に努めて参りたいと思います。

☑オンラインでのプログラミング指導
☑子供向けの学習用コンピュータ ラズベリーパイの販売
☑プログラミング学習に関する情報発信
☑学習塾向けプログラミング学習コンサルティング

プログラミング家庭教師サービスProsense
https://prosense.me/

プログラミング家庭教師サービスProsenseのTwitterアカウント
https://twitter.com/Prosense_nuco

プログラミング家庭教師サービスProsenseのLINE公式アカウント
https://lin.ee/oKN5sWr

プログラミング教育情報発信メディア キッズプログラミング
https://stemed.tk/