【考察】開発を効率化する進め方をしたい

サービス開発の進め方は、複数あります。
アジャイル開発、ウォーターフォール開発、スクラム開発…といった手法は、定例会議を含む全体の流れに関して決められているものかと思います。実際に様々な業務やプロジェクトに参画するとその流れに乗ることになりますが、その後の開発の進め方に関しても複数の種類があり、プロジェクトによって異なります。
人によって経験年数やスキルが異なるため、「この進め方が絶対に良い！」という定石は見つけられていません。しかし、肝心な開発部分の進め方がそのチームやプロジェクトに合致していないと、効率的に進められないのも事実です。
ある程度開発を進めている状態ですと、その習慣からの脱却や癖を直すのは難しく、そのための軌道修正・リカバリーの時間も必要になると思います。
ですので、最初から手を打つために、考察していきたいと思います。


# 触れない内容
* アジャイル開発、ウォーターフォール開発、スクラム開発 などの手法
* TDDやBDD などの手法

# 開発としてやること
効率的に進めるためには、サービス開発でやるべき作業を把握する必要があるかと思います。参画しているプロジェクトによっては、やる必要がない作業もあるかもしれませんが、一通り挙げてみたいと思います。

1. 要件定義
1. サービスとしてのアーキテクチャー決定
1. ソフトウェアアーキテクチャー決定
1. 開発言語の決定
1. 開発言語で利用するフレームワークの決定
1. 開発言語で利用するモジュール・ライブラリの決定
1. 開発時のルール策定
1. テストの観点・ルール策定
1. ログのルール策定
1. 開発環境の整備（ソースコードの管理場所、ローカル環境など）
1. 動作環境や既存(外部)サービスとの連携部分の開発・構築
1. 動作するアプリケーション環境の開発・構築
1. 画面デザインの開発（コンセプト、UIなども含む）
1. 画面モック（処理を含まない操作感を確認するためのもの）の開発
1. 処理の文書化（設計作成）
1. 共通処理の開発
1. 機能ごとの開発
1. マスターデータ（アプリケーション内で変更されないデータ）の投入
1. テストの開発
1. テストケースの作成
1. テストの実施
1. リリース計画
1. リリース準備
1. リリース作業
1. リファクタリング

## 前提
多くの場合、複数人で作業をする状況がほとんどかと思いますので、複数人での効率化を考えていきます。
※ 一人で作業をし、進捗を報告する義務がない場合は、その時に気が向いたものを進めることが多いです。

## 注意点
作業には依存関係があり、完了していないとできない作業もあります。それに加え、複数人でできない作業というのも存在します。
「作業全体でこのぐらいかかります」を見積もる場合、「複数人で着手できない作業」もこの中に含まれている状態になりますので、単純な時間の合算にはならないので、注意が必要かと思います。


# 作業最小限の開発

スタンダードな進め方は、下記かと思います。

1. 要件定義
1. 設計
1. 開発
1. テスト

もしもテスト駆動(=TDD)であれば、テストの方が先になるかもしれないですし、プロジェクトによっては設計がないかもしれませんが、これを文章で表現すると、

1. 「何を作りたいのか」をまずは決めて、
1. 作りたいものの「再現方法や詳細を決めて」共有し、
1. 実際に「動くものを作り」、
1. 要件通りか、問題がないか「確認」をする

となります。しかし、下記の問題が影を潜めています。

* 「何を作りたいのか」が変わる可能性がある
* 「再現方法」が、実際に作ってみたら無理だった… という可能性がある
* 「詳細」が、実際に作ってみたらちょっと違う感じでしか作れなかった… という可能性がある 

前提が崩れる場面もありますし、初めて触れるものであれば、事前にお試しする時間がなければ上手くいかない…というのもよくあります（公式ドキュメントに騙される場面も…）。

もしも作りたい内容が変わった場合、作っていたものを変えれば良いだけです。しかし、その作業に時間を使ってしまうのも事実です。やるべき作業が想定よりも増えてしまった…という現象ですね。

つまり、「開発を効率良く進める」ということは、「完成までにかかる時間や作業量を最小限にすること」だと思います。ここには、 **個人のスキルは含まれません**。チームによって得意・不得意がありますし、スキルは向上します。スキルに関しては、チームの工夫として別途取り組むべき課題だな・・と考えるようになりました。

## ①要件定義
まず前提として、「要件・要求」が変わった場合はどうしようもありません。作ろうとしているものが変わったら、一からやり直し、もしくは途中からやり直しになります。
ですので、一番最初にやるべき作業は「要件定義」になります。

では、どこを工夫すれば良いのかですが、「どの部分をどの順番でどうやって作っていくのか」しかないかと思います。
新規サービスなのか、新規アプリケーションなのか、新規機能の開発なのか、既存機能の改修なのか…、
その時々によって異なりますが、一番やるべき作業が多い状態を踏まえつつ考えていきます。

## ②サービス設計
新規サービスの場合、まずは大枠を決める必要があります。全員がバラバラなことをしないように、方針や、全体的なルールを決めます。

1. アーキテクチャー
    * 多層 or モノリシック or マイクロサービス
    * アプリケーションごとの疎通関係や全体像
    * ソフトウェア(レイヤード, ヘキサゴナル, ModelViewController など…)
1. 開発言語や動作環境(AWS? Azure? Power Apps? など…)
1. 動作環境や外部サービスとの連携部分の開発・構築
1. 開発時のルール策定
    * 命名規則(ローカル変数, グローバル変数, 関数, テスト…など)
    * ソフトウェアアーキテクチャーの原則に沿った依存関係


## ③基盤開発
新規アプリケーションの場合、何もない状態です。ゼロの状態から、この後の開発が少しでも早く進められるようにしていきます。

1. 成果物の管理場所の確保と設定
1. エラーなく起動するアプリケーションの開発
1. 動作するアプリケーション環境の開発・構築
1. 基盤機能開発
    * 「1～2ヶ月後に対応すると作業量が今と比べて膨れ上がるもの」だけ対応

## ④要件開発

新しい機能開発をする場合、使用感を確認ができる必要最低限だけ作成すると良いと思います。
実際に触ってみて、その意見を取り入れやすくするためです。具体的には、下記の作業が対象になると思います。

1. 画面があればその操作が一通り触れる
    * バリデーションエラーがある場合は、そのバリデーション処理も含む
1. アプリケーションごとの連携がある場合は、実際にやり取りができる状態にする
1. 外部サービス(DBなど)がある場合は、その中身処理を Stub化 した状態で作る

既に存在する機能を改修する場合、その規模によって内容が異なりますが、あまりにも少ない内容であれば、「要件開発」は飛ばして良いと思います。

### 気を付けたいこと①
この後を見据えた進め方をすることです。ここで変な作り方をすると、後々に響きます。

具体的には、「複数人で作業をすることによるコンフリクトを未然に防ぐ」ことや、「作業分担をするうえで粒度が細かくできるような整備」など、分担して複数人で作り上げていくための工夫が必要かと思います。

### 気を付けたいこと②
この時点で、「要件」を満たしてることが確認できる(つまり、正常系の)自動化テスト は作りましょう。
自動化テストは、早い段階で導入しないといけません。理由は、後回しにされてしまうからです。

自動化テストは、持続可能な開発を進めるための大事な命綱です。適切な粒度で、すぐに問題がないかを確認ができる状態を維持し続ける必要があると思います(UTである必要はなく、FTやIT でも良いと思います)。


### 気を付けたいこと③
「設計」を作らないといけない場面もあると思います。ですが、その作業は後回し(詳細開発での実施)にすることです。
実際に触ってもらって意見をもらった後、内容が変わる可能性があります。また、実際に設計から先に作ってみたとしても、思った通りにいかない…という可能性もあります。
設計を最初に作ることで、誰でも作業ができるようになる。というメリットもありますが、本来不要だった「設計の修正」というコストをわざわざ増やす必要はないと思います。


## ⑤詳細開発
「この形で作りましょう！」となった時に、複数人で完成形にしていきます。
アクセス制限 や 足りていないバリデーション、ログ出力、外部サービスとの連携、設計(=文書化)…。

まだまだやるべきことはたくさんあります。

### やっておきたいこと
この時点で、 自動化テストの開発、もしくは、テストケースの作成。難しいようであれば、テストケースを作成するための観点などまとめておいた方が良いと思います。
理由は「開発」と「テスト」の期間が空いてしまう可能性があるからです。

詳細開発の際に、ほとんどのテストパターンを自動化できることが望ましいですが、全て自動化できないのが現実です。
（私の中での あるある なのですが、）複数の機能を開発していると、細部まで覚えてられないことがあります。テストケースを作成する際に思い出す作業が発生します。

その時間を極力短くできれば、少しは効率的に進められるのではないか…と思っています。


## ⑥リファクタリング開発
既に作成したものを、より良くするための作業です。
具体的には、「改善点の洗い出し」と「複数人で分担して、一つずつ改善点を解消していく」といった作業になります。

この作業は、開発者向けの利点しかありません。どちらかというと、投資に近いものになります。
スキルが向上したり、業務知識が蓄積されていくにつれて、「ここは共通化した方が良かった」や「この書き方は良くなかった」といった部分が気になってきます。
また、「スキルを持っている人」が全てのレビューに入れるわけではありませんし、レビューで全ての改善点を指摘するということもないと思います（期限が短いと尚更です）。

そういった「技術的な負債の解消」と「チームとしてのスキルの底上げ」を目的とした取り組みができるのが理想です。
（残念ながら、開発手法としてそういった概念が取り入れられていても、その時間が確保されないプロジェクトも存在します。この作業ができるプロジェクトは、貴重ですね・・。）

# まとめ
* 完成までにかかる時間や作業量を最小限にする工夫 が大事
    - 作業をなくすのではなく、新たに発生しそうな作業を抑制する
* 下記の流れで進めることで、複数人が同時に作業がしやすい(チームとしての利点が活かせる)状態を早く整える
    1. （要件定義）
    1. （サービス設計）
    1. （基盤開発）
    1. 要件開発
    1. 詳細開発
    1. （リファクタリング開発）
* チーム全員が、完成までの道のりを把握する必要がある
    - 作業を分担する場合、「この作業やった・・？」に陥る可能性がある
    - 各作業の完了条件・作業内容 を明確にしておく必要がある


# 最後に
アジャイル開発の考え方が色濃くなった結論になってしまいました…。しかし、少しずつ作っていき、手戻りを少なくするための考えはまとめられたかな…と思います。それぞれの開発にTDDやBDDを組み合わせをしても良いかもしれません。

リファクタリング開発は、できるならやりたいと常々思います…。
勉強会をしよう！となっても、実際に手を動かして、自分で動作確認をして、実感してみないと、定着し辛いです。もしも、興味があって質問を積極的にできるぐらいの集中モードで参加していれば話は違うのでしょうが、時間の無駄になる可能性が高いのであれば、少しでも有益な形の取り組みをした方が良いと考えています。

今回まとめた内容は、新規プロジェクト、既に進めているプロジェクトであっても、取り組むことはできると思います。
しかし、今までと全く違う進み方をすると拒否感が生まれる可能性があります。ですが、その取り組みをすることによるメリット、現時点のデメリットを分析し、しっかりと説明をすることで受け入れてもらえるかもしれません。
もしも 「ダメ！」って言われたとしても、今の進め方を踏まえて「ここは取り入れてみよう」といった前向きな話ができると良いですね。

今やっている進め方に疑問を抱き始めた方、チーム開発で奮闘している方の、少しでも力になれば幸いです。