【開発プロセス】個人開発の流れ

# はじめに
この記事では個人でアプリ開発に挑戦する方に向けて、開発プロセスのV字モデルに沿って各フェーズ(要件定義、設計など)でやるべきことをまとめています。
なお、今回は個人で開発できる程度の**小規模なアプリ開発**を想定しています。

# 対象読者
- 効率の良い開発の進め方に悩んでいる方
- 各フェーズで作成する制作物に悩んでいる方
- 開発物の参考になる仕様書・設計書の記載事項に悩んでいる方

# V字モデルと主要な開発モデルについて
V字モデル、ウォーターフォールモデル、アジャイルについて説明します。
この辺りは業務での開発プロセスに近い話になります。

## 開発の基本「V字モデル」
一般的に下のような図をV字モデルと呼んでいます。

>![v_shaped_model.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/598279/7bd18ae9-1d4c-fda6-1faf-124cf54d24c0.png)
<span style="font-size: 80%">引用サイト：<a href="https://webrage.jp/techblog/v_shaped_mode/" target="_blank">webrage</a></span>

おおむねアプリ開発、システム開発はこの沿って進めていきます。
一般的に企画～要件定義までを上流工程、設計～テストまでを下流工程と呼びます。
上流工程で決定した事項に変更が加わると下流工程での修正が大変になるので、できる限り要件定義で実現する機能を明確にし、途中で変更することがないようによく**将来の構想を練っておきましょう。**

## 大規模開発に向く「ウォーターフォールモデル」
システムが満たすべき要件や機能がすべて明確に決まっていて、その決定に変更がないとされる**大規模なシステム**を開発する際に用いられます。
前の工程に戻ることがなく、滝の流れのように一方通行で開発が進むことから**ウォーターフォールモデル**と呼ばれます。

企画や要件定義での決定事項に変更がないことを前提に設計・実装をするため、上流で変更が加わると下流で大変な手戻りが発生します。そのため、**ユーザの反応を見ながら機能を追加・変更したいときは後述のアジャイルモデルを用います。 **  

## 変更に柔軟な「アジャイルモデル（スパイラルモデル）」
アプリやシステムの要件や機能が完全に決まっておらず、**将来に追加・変更する可能性が高い**ときに用います。
機能ごとに企画～テストを繰り返し、短い周期で開発を進めるため、途中で機能が追加・変更されても比較的柔軟に対応できます。 
そのため、ユーザの反応や自分の湧き上がるアイデアから機能拡張するような**アプリ開発**と相性が良いです。

要件が変更されることを前提にしているため、設計にかける時間は比較的少なく細部まで作り込むことはしませんが、将来のためできる限り**保守性を維持できるように設計することが重要**です。
補足：**アジャイルモデル**と**スパイラルモデル**は開発プロセスは似ていますが、異なるモデルということに触れておきます。興味ある方は<a href="https://blogs.techvan.co.jp/quality/spiral" target="_blank">こちら</a>

ウォータフォールモデルは1回の企画～テストの流れで開発が終了するのに対して、アジャイルモデルは企画～テストの一連の流れを複数回繰り返します。

# 開発プロセスの各フェーズのタスクと制作物
ここから私自身が各フェーズで行っていることと作成している制作物を示します。

私の場合は、はじめに実装したい機能を思い付くままにすべて書き出し、必要最低限な機能とあれば便利な機能に分けて、段階的に機能を拡張していきます。
はじめに今後実装する機能を想定しておくと保守性を維持しやすいですし、段階的に開発していくことでモチベーション維持にもつながります。

そのため、モデルとしては**アジャイルモデルの開発プロセスに近い**と思っています。はじめに初回の企画～要件定義で実装したい機能をできる限り考えておき、設計～テストを複数回まわして開発していくスタイルです。開発をしていて新たに追加したい機能などを閃いたら定期的に企画～要件定義を振り返ります。

## 日々のアイデアをまとめる「企画」
生活をしていく中で、ふと思いついた自分の「これがしたい」、「こうできるようにしたい」などのアイデアや想いをメモしておきましょう。
思いついたらすぐに開発が始められる状況だといいのですが、仕事や学校など様々な理由からそうできる方は多くないので、**思いついたら忘れないうちにメモ**を取っておきましょう。

メモの取り方は自分が分かりやすいように自由に書くのが良いでしょう。
私の場合は

- PCで作業を行う際に毎回たくさんのファイルを開くのが面倒なので自動化したい
- PrimeVideoは制作年代でソートできないので、ソート機能を開発したい
- Twitterのタグ数やタグリツイート数、YoutubeのPV視聴数などから今後盛り上がりそうなアニメを予測したい

というように非常に簡潔に書いています。

できるできないはひとまず置いておいて、**ふとした閃きは大事にしていきましょう！**

## アイデアをアプリの機能として結び付ける「要件定義」
ここから実際に開発を進めるための準備をしていきます。
要件定義の語義を確認しておきます。
> 要件定義とは、システムやソフトウェアの開発において、実装すべき機能や満たすべき性能などのを明確にしていく作業のこと。いわゆる上流工程の一部で、実際の開発・実装作業を始める前に行う作業の一つである。
<span style="font-size: 80%">参考サイト：<a href="http://e-words.jp/w/%E8%A6%81%E4%BB%B6%E5%AE%9A%E7%BE%A9.html" target="_blank">IT用語辞典</a></span>

要件定義では**メモしたアイデアをどのような機能を持ったアプリで実現するか**を考えます。
具体的には、現時点で考えうる必要な機能やあれば便利な機能を書き出します。  
開発途中で思い付いた追加機能などあれば書き出しておきましょう。

例えば、電卓アプリを開発したいと考えた時には次のように機能を書き出します。
![ラフ設計.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/598279/7bcdca27-fb6b-2c23-38c8-81c5d4f90a03.jpeg)

小さすぎず大きすぎない粒度で、思い付いたままに書き出します。
次に、アプリに必要最低限な機能とあれば便利な機能に分けます。あれば便利な機能は実装する優先順位をつけておくとなお良いです。
そして、このバージョンで拡張したい機能を選ぶと良いでしょう。

GooglePlayStoreやAppStoreを通して、他人にも使ってもらうことも考えている場合は以下も考えます。

- アプリ名
- アプリ概要文
- プレスリリース
- ユーザ像と解決する課題
- ユーザが使い続けてもらえるような仕組み（達成感や楽しさなどを感じられる仕組み）

上記のような項目を記載した文書を「要件定義書」と呼び、要件定義フェーズでは要件定義書の完成を目指します。

## 機能の実現方法を考える「設計」
要件定義を実際に開発（コーディング）できるように、**実装する機能をクラスや関数に割り当てます。**
大きい機能の場合は、その機能を複数のクラス・関数に分割して実装し、それらを組み合わせて機能を実現します。
またこのフェーズで、フレームワークやAPIの利用も検討します。

設計の語義を確認しておきます。
> 設計とは、これから作るものの構成や構造、各部の詳細、作り方などを決め、文書や図面などに記すこと。
<span style="font-size: 80%">参考サイト：<a href="http://e-words.jp/w/%E8%A8%AD%E8%A8%88.html" target="_blank">IT用語辞典</a></span>

設計は「外部設計」と「内部設計」に分かれます。

### ユーザからの外見を設計する「外部設計」
外部設計では次のことを考えます。

- 画面レイアウト
- 画面遷移
- ユーザからの入力データ
- ユーザへの出力データ

**画面レイアウト**は、ラベルやボタンなどの画面コンポーネントの配置を考えます。
最近ではレスポンシブ対応デザインにするためにグリッドデザインを採用したフレームワーク「Bootstrap」が人気です。

**ユーザからの入力データ**は、ユーザから受け取るデータ、必要なデータを決定します。
ユーザは常に適切なデータを入力するとは限らないので適切なデータと不適切なデータを決めておき、不適切な入力データを受け取った場合の**例外処理**も考えておくとよいでしょう。

### アプリの内部を論理的に設計する「内部設計」
内部設計では次のことを考えます。

- クラス設計とフローチャート
- イベント設計
- データフロー
- データベース設計

**クラス設計**は実装する機能を担当するクラスを決定します。どのクラスがどの機能に関わり、どんな役割を果たすのか決めておきます。
各クラスでテスト（単体テスト、結合テスト）を行いやすくするために、**クラスと役割は1対1**で結び付けます。
可能ならば、クラスのメンバ変数とメソッドも決めておくと良いです。
また、ユーザの入力データをデータベースに保存する際には、**バリデーションチェック**も考えておくと良いです。
最後に、すべての機能がすべてのクラスに対応しているか確認しておきましょう。

**イベント設計**は、**画面遷移**をもとに必要なイベント処理とそのイベント名を考えます。
例えば、特定のボタンをクリックすることで別画面に遷移する場合は、そのクリックイベント名とそのイベント処理（画面インスタンスを作成するなど）を決めます。

**データフロー**はユーザの入力データがどこで処理され利用するかを決めます。
入力データがどこで処理され利用されているのかを把握しておくことで、欠陥修正がやりやすくなります。
地味な作業ですが規模が大きくなってくると、データがどこに行ったか行方不明になったりどこから来たデータなのか分からなくなることがあるので欠陥修正の観点から大切です。

**データベース設計**はデータベース名、テーブル名、テーブル構成、カラム名、制約（主キー制約、外部キー制約）を決めます。
制約を使ってデータベースに保存されているデータに整合性や保守性が保たれるようにします。

上記のような項目を記載した文書を**設計書**と呼び、設計フェーズでは設計書（外部設計書と内部設計書）の完成を目指します。

## 実装
作成した設計書に沿ってコーディングを行います。
個人的に開発の中でも実際に「もの」ができていくという感覚があり、最も楽しいと感じるフェーズです。

設計書に従ってコーディングしていくため、特に注意することはないかと思います。
ソースコードの保守性を維持するため、重複したコードは１つの関数にまとめることを意識します。設計書に記載していない関数を作ることに抵抗があるかもしれませんが、保守性維持の観点から大切なので作っていきます。

実装上、分からないことなどがあれば**とにかくググる**ことが大切なので諦めず粘り強く開発を続けましょう。
個人的には実装しながら動作テストも行います。

## テスト
機能、もしくはクラス・関数が完成したら、それが規定通りに動作するか様々なデータを入力して確認します。
想定される入力パターンをできる限り書き出し、そのすべてのパターンで既定の動作を決定します。
そして、そのいずれのパターンでも想定どおり動作するか確認します。
また、**不適切な入力が行われた際にしっかり例外処理を行われていることも確認します。**

アプリが一通り完成したら、要件定義書の「アプリ概要」や「ユーザ像と解決する課題」などの項目と実装した機能にずれがないか確認します。
開発していたら余計な機能をつけすぎたり長期の開発によって方向性を見失たりして、当初のアプリ構想からずれていたということもありますので、要件定義書をしっかり確認しましょう。

個人的には実装フェーズで実行しながら欠陥も探すため、テストフェーズは実装フェーズの一部分のようになっています。
よく確認する事項としては、上記にもあげた通り、ユーザの様々な入力パターンを予測して不適切な入力があった場合にも、例外処理（処理回避、エラーメッセージ表示）をして**アプリが動作し続けられるか確認します。**

# まとめ
以上が私の個人的な開発プロセスです。

個人開発では開発の自由度が高いので、開発をしていてプロセスを変更したいことがあったら自分に合うように柔軟に変更していきましょう。
**プロセスを修正していくことが自分に合ったものにしていくこと**が、効率的な開発に必要なことの一つだと思います。

最後に私が思う個人開発の魅力を少しだけ。。。
個人開発の魅力は、自分で自由にプロセスを改変したり、気になる技術を導入したり、機能を拡張してみたりすることが気軽にできることだと思います。
アプリで収益をあげたいなどの目的がある場合はある程度制限はされますが、それでも自分で考えたアイデアで試行錯誤しながら開発していくことが楽しいですよね。

長くなりましたが、この辺で終わりたいと思います。
最後までご精読ありがとうございました。