アジャイル開発について初学者が知っておきたい基礎知識

この記事を書いているのは、普段ウォータフォール型開発しかしていない1年目のエンジニアです。

アジャイル開発では短いタイムボックスで要件定義と実装を繰り返す、という程度の知識しかありません。

そこで

* 今の職場がウォータフォール型を採用していることのメリット
* アジャイル型の具体的な開発手法や専門用語

といったことを自分なりに整理することを本記事の目標としています。

間違っている箇所や説明不足の箇所がありましたら、ご指摘いただけるとありがたいです。

## アジャイルとは

アジャイルとは、**開発期間の短縮やコストの削減、仕様変更に対する柔軟な対応などを実現するために、プログラマなどの開発サイドから提唱されたソフトウェア開発手法**のこと、と私は理解しました。

アジャイル開発では、システムを機能単位に分割し、2〜3週間の短いスパンで「計画 => 要件定義 => 設計 => 実装 => テスト」といった工程を進めます。ひとつの機能をリリースすると、すぐに次の機能の「計画 => 要件定義 => 設計 => 実装 => テスト」の工程に移ります。

この**2〜3週間の短いサイクルをイテレートやスプリントと呼びます**。この両者は同じ意味と思っていいようです。

イテレートは、私はデザインパターンのIteratorパターンで知りましたが、「繰り返す」という意味です。

システム開発を小さく分割することにより、次のような効果が期待できると思います。

* **機能単位で動作することが常に保証された状態**で進めるため、顧客のフィードバックを早い段階で得られる
* 設計や要件定義を機能ごとに行うため、**顧客のニーズを開発に反映させやすい**
* 実装やテストの段階で不具合が発覚しても、次の機能の設計や要件はまだ確定していないため、**手戻りが少ない**

上記は、私が想像で書いているだけですので、間違いがありましたらご指摘いただけるとありがたいです。

### 手法ではなく価値観

アジャイルは具体的な開発の手法ではなく考え方だ、という説明をたくさん見ました。

アジャイルの始まりは、次の「アジャイルソフトウェア開発宣言」といわれているようです。

> 【アジャイルソフトウェア開発宣言】
>
> 私たちは、ソフトウェア開発の実践
> あるいは実践を手助けをする活動を通じて、
> よりよい開発方法を見つけだそうとしている。
> この活動を通して、私たちは以下の価値に至った。
>
> プロセスやツールよりも**個人と対話**を、
> 包括的なドキュメントよりも**動くソフトウェア**を、
> 契約交渉よりも**顧客との協調**を、
> 計画に従うことよりも**変化への対応**を、
> 価値とする。すなわち、左記のことがらに価値があることを
> 認めながらも、私たちは右記のことがらにより価値をおく。
>
> [アジャイルソフトウェア開発宣言](https://agilemanifesto.org/iso/ja/manifesto.html)

ここで宣言されているのは、具体的な手法ではなく**何に価値を置くか**なので、アジャイルとは哲学だといわれるのだと思います。

[アジャイルソフトウェア宣言の背後にある原則](https://agilemanifesto.org/iso/ja/principles.html)という文章も、アジャイルについて調べていると頻繁に引用されていました。

次のようなことが書かれていました。

* 顧客満足を最優先する
* 変更要求は開発後期でも歓迎する
* 動くソフトウェアを2-3週間から2-3ヶ月間隔でリリースする
* ビジネス側とエンジニア側の人間が一緒に働く
* 意欲に満ちたメンバでプロジェクトを構成する
* フェイス・トゥ・フェイスで情報を伝える
* 動くソフトウェアを進捗の尺度とする
* 一定の開発ペースを維持する
* 技術的卓越性と優れた設計に注意する
* シンプルさが本質である
* 最良のアーキテクチャ・要求・設計は自己組織的なチームから生まれる
* 効率を高めるために定期的に振り返る

個人的に面白いと思ったのは、これが作られたのは2001年ということでした。

「フェイス・トゥ・フェイスで情報を伝える」とありますが、現代はZoomやslackなどのコミュニケーションツールが充実しているので、フェイス・トゥ・フェイスに代替できる部分もあるのではないかと思います。また、当時は継続的インテグレーションといった概念も存在しなかったと思うので、「2-3週間から2-3ヶ月間隔」というサイクルも、今とは感覚が異なるのではないかと思いました。

### ウォータフォール型とアジャイル型の違い

ウォータフォール型とは、下記の工程をトップダウンで進める開発モデルです。

1. 要求定義
2. 外部設計（概要設計）
3. 内部設計（詳細設計）
4. 開発（プログラミング）
5. テスト
6. 運用

ウォータフォール型では、**原則として前工程が完了するまで次工程に進まない**、とありました。

上から下に一方行にしか進まない様子を滝（ウォータフォール）に喩えているようです。何度も要件定義や設計を繰り返し、変更の要求に柔軟なアジャイル型とは対称的です。

また、**ウォータフォール型では最初に要件を、アジャイル型では最初に期限と人員を決める**、というような説明も見ました。つまり、ウォータフォールでは要件を固定し、それに合わせて期限や人員を計算するのに対し、アジャイル型では期限と人員を固定し、その範囲で何が作れるかを考えるということのようです。

### スパイラル型とアジャイル型の違い

スパイラル型開発とは、設計・実装・テスト・評価といった一連の工程を何度も繰り返しながら完成度を高める開発手法、と説明されていました。これを読んだとき、アジャイル型と何が違うのかと疑問に感じたので、スパイラル型とアジャイル型の違いについて整理したいと思います。

結論からいうと、スパイラル型は動作確認できる程度の品質のプロトタイプから作り始めるのに対し、アジャイル型はいつでもリリースできる品質の機能をひとつずつ作っていく、という違いがあるようです。スパイラル型ではサイクルを回すごとに品質が向上していき、品質が保証された時点で一気にリリースしますが、アジャイルはひとつの機能ごとにリリースしていき、サイクルを回すごとに機能が増えていくイメージです。

## アジャイル開発の手法

次にアジャイル開発の具体的な手法について調べました。

実際にアジャイル型の開発を実践する場合、どんな流れになるのかをイメージできるようになることを目標としました。

### 手法の分類

アジャイル開発の手法としては、次の3つが有名なようです。

* スクラム：チームのコミュニケーションを重視した手法
* エクストリーム・プログラミング（XP）：事前に立てた計画よりも途中変更などの柔軟性を重視する開発手法
* ユーザ機能駆動開発（FDD）：顧客にとっての機能価値という観点で開発を進める手法

なかでもスクラムが有名で、**チームのコミュニケーションを重視した手法**と紹介されていました。

### スクラム開発の流れ

アジャイル開発の具体例として、スクラム開発の流れを簡単にまとめました。

1. 計画を立てて実施する（スプリントプランニング）
   * プロジェクトで必要となる機能の一覧（バックログ）から、今回のスプリントで実装する機能を選ぶ
   * 基本的には優先順位の高い機能から順番に開発していく
2. 毎日決まった時間に進捗報告を行う（デイリースクラム）
   * プロジェクトの進捗や今後の開発の課題になりそうな要素を共有する
   * スクラム開発はコミュニケーションを重視する手法であるため報告の機会が多い
3. 実装した機能の評価を行う（スプリントレビュー）
   * 実装した機能の評価をスプリントの最終日に行う
   * 最初に決定したバックログの基準を満たしているかを評価する
4. スプリントを振り返る（スプリントレトロスペクティブ）
   * 今回のスプリントの良かった点や次回の課題を洗い出す
   * チームがスプリント期間内でどの程度の開発ができたかを測定し、計画の精度を高める

### エクストリーム・プログラミングのプラクティス

アジャイル開発手法のひとつであるエクストリーム・プログラミング（XP）では、いくつかのプラクティスがあります。

プラクティスというのは、慣習となっている手法という意味だそうです。エクストリーム・プログラミングの特徴として、**テスト駆動開発**や**ペアプロプログラミング**、**継続的インテグレーション**などがよく紹介されていましたが、これらがプラクティスにあたります。

* テスト駆動開発
  * 実装よりも先にテストを作成する
  * 求められる機能を明確にしてシンプルな設計を実現する
* ペアプログラミング
  * 1台のPCを2人で使い開発する
  * 問題と解決策を即座に発見することを実現する
* 継続的インテグレーション
  * 開発中ソフトウェアのビルドやテストを自動的かつこまめに実行する
  * 問題の発生を即座に検知し手戻りを最小にすることを実現する
  * いつでもリリースできる状態を継続的に保つことを実現する

代表的なプラクティスとして上記が紹介されていました。

### アジャイル関連の用語

#### 役割

* プロダクトオーナー：実装する機能の優先順位を決め、プロダクトの価値に責任を持つ人
* スクラムマスター：プロダクトオーナーと開発チームが効果的に働けるよう支援する人
* 開発チーム：実際に実装する人
* ステークホルダー：プロダクト利用者や出資者などの利害関係者

#### 用語

* スプリント：ひとつの機能を実装するための通常4週間以下のタイムボックス
* プロダクトバックログ：プロダクトを作成するにあたっての要求事項を順番に並べたリスト
* スプリントバックログ：スプリントで実施する具体的なタスク
* インクリメンツ：完成の定義を満たしたリリース可能なプロダクト
* ベロシティ：開発チームの速度を表す指標
* ユーザストーリー：サイクルを回す上で手がかりとなる顧客の意図や要求の断片

###  DevOpsとアジャイル開発

DevOpsはアジャイル開発をさらに発展させた手法、と紹介されていました。

私の知識レベルとしては、DevOpsは開発（Development）と運用（Operation）の略、と知っている程度だったので、これがアジャイル開発とどう結びつくのかが想像できませんでした。DevOpsの概要とアジャイル開発との関係を整理してみます。

#### DevOpsとは

DevOpsとは、プロダクトの価値を高めるために**開発チームと運用チームが協力体制を取る開発モデル**のようです。

開発と運用を同じチームが担当することもありますが、開発チームと運用チームにそれぞれ分かれている場合のほうが多いようです。そして、本来は協力しあうべきの両チームですが、目標地点が違うために対立関係になってしまうことがよくあるそうです。

開発チームは新しい機能の追加を目標としますが、運用チームはシステムの安定稼働を目標としています。**開発チームが新しい機能を追加したくても、運用チームはシステムの安定稼働のため変更を加えたがらない**、ということらしいです。

#### DevOpsのベストプラクティス

**こちらの記事**では、次の内容がDevOpsのベストプラクティスとして紹介されていました。

* 継続的インテグレーション
  * 変更のたびにビルドとテストを自動的に実行する
  * バグの早期発見やシステムの品質の維持につながる
* 継続的デリバリー
  * すべての変更が本番環境にデプロイ可能である状態を保証する
  * 変更のたびに本番環境にデプロイするわけではないので継続的デプロイとは別物
* マイクロサービス
  * 個別に開発した小さなサービスを組み合わせてひとつのサービスを提供する
  * サービスごとに異なる技術を採用したり再利用しやすくなるなどの利点がある
* Infrastructure as Code
* モニタリングとロギング
* コミュニケーションと共同作業

#### DevOpsとアジャイルの関係

DevOpsは基本的にアジャイル開発モデルを採用するため、DevOpsとアジャイルが混同されることも多いようです。

これは個人的な感想ですが、アジャイル開発ではリリース可能な状態を保証しながら機能実装を進めるので、さきほどの「運用チームはシステムの安定稼働のため変更を加えたがらない」という問題をクリアできるため、相性が良いのではないかと思いました。

## アジャイル開発を採用する目的

### アジャイル開発のメリットとデメリット

アジャイル開発のメリットとデメリットを整理してみます。

**アジャイルのメリット**

* バグが発覚したときに手戻りの工数が最小化される
* あらかじめ仕様を固める必要がなくフィードバックを反映させられる
* ユーザが実際に動くソフトウェアを試せるので仕様間違いや要求漏れに早期に気付く

**アジャイルのデメリット**

* 計画段階では厳密な仕様が決まっていないため方向性がぶれやすい
* 全体の進捗状況やスケジュールを把握しにくい

ビジネス的には、実際に画面を操作しながら使用感を確かめたり、実際にユーザに使用してもらい収集したデータを次の機能開発に活用する、といったフィードバックが生かせる点がメリットといえそうです。バグや仕様間違いなどに早期に気づける、というのは開発者側の視点ですね。

### アジャイルが向くケースと向かないケース

どんな場合もアジャイル一択ではなく、開発対象ごとに使い分けることが大切という意見もあるようです。

アジャイル開発が向いているケースとそうでないケースについて、調べた内容や自分なりの考えをまとめました。

**アジャイル開発が向くケース**

* より早くプロダクトや新機能を提供したいとき
  * すべての完成を待つことなく、機能単位でリリースできる
* ユーザのフィードバックをプロダクトに反映させたいとき
  * 実際に機能が動作する状態が保証されている
* プロダクト全体の要求が明確でないとき
  * あらかじめ全ての要件を定義する必要がない
  * 仕様変更の場合も手戻りが比較的少ない

**アジャイル開発が向かないケース**

* 開発スケジュールや予算を厳密に見積もりたいとき
  * アジャイルはスプリントごとに計画を立てる
* すべての工程を担当できる開発者がいないとき
  * ウォータフォールなら工程ごとに担当者がいるので必要な技術の幅が小さい

競合よりも先にリリースしたいときや、ゲームのように明確な正解のないシステムの開発にはアジャイルが適するのではないか、と思いました。

また、アジャイルはフェイス・トゥ・フェイスのコミュニケーションに価値を置くため、大規模な開発では仕様の整合性や品質の均質性を保つためにコミュニケーションコストが高くなるため、大規模開発にアジャイルは向かない、という意見もあるようです。ウォータフォールでは要件や設計を文書化するので、それらを参照すればフェイス・トゥ・フェイスのコミュニケーションは最低限で済む、ということのようです。

## まとめ

アジャイルは、ソフトウェアを機能単位に分割し、スプリントと呼ばれる短い期間で要件定義や実装ややテストというサイクルを繰り返し回す開発方式のことでした。

ビジネス的には、早くリリースできること、使用感を確かめながら次の機能を決められること、などがアジャイルのメリットです。エンジニア的には、バグを早期発見できること、仕様変更の際に手戻りが少ないこと、などがメリットとして挙げられます。

関連する用語を調べていて、個人的にはDevとOpsの対立についての説明を読んだのが面白かったです。開発チームは新機能を追加することを目標にしているけれど、運用チームはシステムの安定稼働が目標なので、変更を加えたがらない、というものです。開発チームもシステムの安定稼働に対して責任を負うべきだし、運用チームも新機能の価値を理解するべきだと思いますが、わざわざDevOpsという言葉ができたというのは、その実現が難しいということでしょうか。