チーム開発について

# チーム開発について
書籍『チーム開発実践入門』から、チーム開発で気を付けること、有益なツール類をメモした。
実際には、以前、社用に用意したものの張り直し。

## 一人での開発の場合
### メリット
**コミュニケーションコストがかからない**   
* 趣味でのアプリ開発や、自己学習など、極小規模のソフトウェア開発を個人で行っている場合には、基本的にコミュニケーションを必要としない。

**スピーディーな開発・リリースが可能**
* 対人間のコミュニケーションがない為、判断や調整を自己で完結することができ、スピーディな開発、リリースができる。

### デメリット
**一定規模の開発までしかできない**  
* フリーウェアや趣味のプログラミングでは問題ないが、有料のシェアウェアやそれ以上の水準のソフトウェアの開発をしようとした場合、どうしても一人では製品すべての管理をすることが難しくなり、品質を維持することができなくなる。
* スキルや物理的に可能な作業量が限定されるので、バグ対応に時間がかったり、ソフトウェア更新が滞ったりといったスケジュール上の問題が次第に発生してくる。

規模の大きな開発を考えた場合、複数のメンバーによる、チーム開発の体制を検討することが必然となる。


## チーム開発の利点
* メンバーを適切に配することで、製品の管理を効果的に行い、規模が大きくなっても品質を維持することができる。
* メンバーを増員することで、物理的にはどんな規模の開発業務であってもスケジュールの遅れなく対応することが可能になる。
* 様々なスキルのメンバーが集うことで、意見を集約し、新しい技術の導入も期待することができる。

## チーム開発の課題
チーム内のメンバーが増えれば増えるほど可能なことが増える反面、コミュニケーションをいかにスムーズにとるかが相対的に難しくなっていく。課題の共有、進捗、スケジュールの管理など、コミュニケーションを円滑にかつ、いかにコストをかけず進めるかがまず大きな課題である。  
また、複数人で作業をする様になったことで、ソースコード、ドキュメントの競合が発生する様になる。場合によっては、大きな手戻りや、バグの発生につながり、スケジュール進捗や品質に影響を及ぼしかねない。スピードを落とさずに、いかに品質を維持するかを考えることが重要である。加えて、品質の面では、開発環境の構築やテスト時に、各メンバーがそれぞれの手順で実施することにより発生しうる差異について、考えなければならない。  
**コミュニケーション**、**競合**、**差異**  
この三つをチーム開発の解決すべき重要な課題として、次項以降、解決するためのツール、メソッドを記述していく。

# チーム開発の為のツール、メソッド

## 理想的なプロジェクトのイメージ

ツール、メソッドを考える前に、今回、目標のイメージとして、以下の様な理想的プロジェクトを想定する。

* **チケット管理システムに課題が集約されている。**  
課題やタスクが一か所に集約し、優先度、重要度、ステータスがすぐにわかる状態になっている。
各環境のデプロイ状況、テスト結果も自動で抽出し、プロジェクトに関わる全員が効率的に情報共有することが可能。

* **バージョン管理システムが適切に利用されている。**  
ソースコードが適切に管理されているだけでなく、設計書等のドキュメントや設定ファイルなどのあらゆるファイルも整理されている。ブランチ、タグが適切に利用されていることで、バグ対応版、最新リリース版等がすばやく検索でき、設定ファイルを読み込むことで、環境毎にいつでも過去のリリースに戻すことが可能である。また、オフライン時にもローカル環境内でバージョン管理することができ、スピードが維持されている。

* **繰り返し再検証可能なシステムが用意されている。**  
CI(continuous integration : 継続的インテグレーション)システムが用意されており、常にすべてのリソースを統合的に管理している。
自動的にビルド、単体テストを実行し、チェックをすることで、コミット漏れや修正ミスにすぐに気付くことが可能で、ソフトウェアの品質向上に貢献している。

* **開発、テスト、リリース時、環境の差異が適切に管理されている。**  
環境によって異なる差異を管理し、設定ファイルやスクリプトに保存している。
バージョン管理システム、CIシステムとリンクすることで、開発、テスト環境、リリース前の検証環境など、自由にかつ、簡単に用意することができる。

## バージョン管理システム

### バージョン管理システムとは  
プロジェクト内のソースコード、設計書、設定ファイル、または動画ファイルなどのコンテンツを種類を問わずに管理できる。その際、いつ、だれが、どのように変更したのかという履歴を漏らさず記録してくれることがバージョン管理システムのもっとも基本で重要な機能である。  
現在、チーム開発を行う場合には、なにかしらのバージョン開発システムを利用することが当たり前のこととなっており、チームの開発スタイルを決定づける最も重要な要素の一つである。

### バージョン管理を行うメリット
* 変更内容の履歴が残る。
* 変更内容の差分を簡単に確認できる。
* 他メンバーの変更を意図せずに上書きすることを防止する仕組みがある。
* 任意の時点まで巻き戻すことができる。
* 複数の派生(ブランチ)をつくることができ、ある時点の状態を保存することができる(タグ)。

### バージョン管理システムの種類
2016年現在、利用されている可能性のあるシステム、筆者が関わったことのあるバージョン管理システムについて、
特徴を踏まえて、いくつか以下に列挙する。  

*ロックモデル*  
* VSS(VisualSourceSafe)  
ファイルをチェックアウトする前に、作業者一人以外、ファイルをロックする。メインの作業者が編集後、コミットしてロックが解放されるまで、他の作業者はチェックアウトを行うことができず、基本的に競合(コンフリクト)は起こりえない。半面、複数の作業者が同時に一つのファイルを改修することは出来ない為、効率面で他のシステムよりも劣る。
中央リポジトリ形式をとっており、仮にリポジトリサーバーがダウンしていた場合、バージョン管理の各種機能を行うことができない。

※ 筆者の経験では、その特徴であるロック形式が大きくネックに感じられました。重要でかつ、頻繁に調整がはいる新規案件のメインモジュールなどでよく順番待ちが発生し、無理やりに個人コピーを用意し、マージしようとしたことを複数人が繰り返したことでモジュールが破壊寸前になるということもありました。

*マージモデル*
* CVS(Concurrent Version System)
複数の作業者が同時に対象ファイルをチェックアウト、編集ができる。ロックを取得しない為、コミット時に競合が発生しうるが、差分を明確に判断、吸収する機能がある為、ファイルを壊してしまう可能性は低い。競合箇所がない場合は、自動で内容のマージをしてくれる。ロック解除待ちがない為に効率よい開発ができる。VSSと同様、中央リポジトリ形式をとっており、サーバダウン時には、パージョン管理が行えない。  

* SVN(Subversion)
CVSの後継。CVSと同様、中央リポジトリ形式をとっている。基本的にはCVSの機能を継承しているが、CVSがファイル単位を管理をコンセプトにしていたのに対して、SVNでは、コミットに関連するファイルセットを管理単位にしていることで、ファイル名やディレクトクトリ名が変更削除されても追跡が可能になるなど、より柔軟な管理ができるようになっている。バージョン管理ツールとしては、現在最も普及している。

※筆者は最初の案件でCVSを経験し、次の案件で一度VSSを、以降はCSVとSVNを繰り返し経験してきました。堅牢性の面ではVSSは確かに一定の利点はあると感じましたが、効率性を考えるとやはりCVS、SVNが使いやすく、多くの案件で採用されていた理由だと思います。

*分散バージョン管理システム*
* Git  
理論上、中央リポジトリを持たず完全なｐ２ｐモデルで運用可能。メインリポジトリからローカルにクローンをコピーすることで、ネットワークを介さずにすべての操作が実行できる。ネットワークを介さない為、障害でメインリポジトリがダウンしている場合やオフラインでも、ローカルのリポジトリを使ってバージョン管理を行うことができ、検証やバグフィックス用のブランチを作ったりといったことも従来の中央リポジトリを利用した方法よりも簡単に行える。実際には、中央リポジトリの代わりとして、運用上のメインリポジトリを置くことが常識的になっており、幾度かコミットした結果、コード内容が固まったところで、メインリポジトリに**push**し、メンバーに共有するフローがとられる。分散バージョンの概念については、わかりづらい部分もあり、学習コストがやや高いといった側面もある。

* github  
Gitシステムで管理されているプロジェクトについて、WEB上でホスティングするサービス。
WEB上で気軽に履歴管理を行え、そのまま課題管理も行うことができる。
他の大きな特徴としては、fork(フォーク)とpullrequest(プルリクエスト)がある。
前者は、他人のgithubプロジェクトで気に入ったソフトウェア、コンテンツがあったら、気軽にクローン(fork)し閲覧したり、修正することのできる機能である。
後者は、チェックアウトやforkしたファイルを修正した後に、元のプロジェクトの担当者に対して、取り込みの依頼を送信する機能である。その気軽さから、当初オープンソースサイトで利用されてきたが、最近では大手Webサービス企業でも利用するケースが増えてきている。

※筆者は、国内大手の某ECサイトのプロジェクトに着任した際に初めて、Gitおよびgithubを利用することになりました。
当初は、ローカルリポジトリとリモートリポジトリの位置関係がうまく把握できず苦労しましたが、慣れてくるとその使い勝手がなかなか心地よいものでした。そちらの案件では、githubのpullrequest機能をレビュー依頼に応用しており、自動可の為、別途メールで連絡するなどの必要がありませんでした。指定箇所の変更履歴やステータス管理もそのままgithubで確認できたので、従来に比べ、スピーディな開発を行うことができたと感じています。

### バージョン管理システムのトレンド
ロックモデルからマージモデルへ、また中央リポジトリ型から分散バージョン管理型へと変化してきています。それぞれに特性があり、一概に優劣は決められませんが、スピード重視や多角的サービスの検証が求められる昨今、現在最もスタンダードなSVN(中央リポジトリ型)から、Git(分散バージョン管理型)へとトレンドがシフトしていくと考えられます。

## チケット管理システム

### チケット管理システムの導入メリット
**タスク管理をするための基本機能がある**  
* 『何をしなければいけないのか』というタスクの定義  
* 『誰がするのか』という担当者のアサイン
* 『いつまでにするのか』という期限の管理
* 『今どうなっているのか』というステータスの管理

** 一覧性、検索性が高い**

** 情報の一元管理と共有が可能である**

** レポートの出力が可能**　　

** 他システムとの連携が可能で、拡張性がある。**

### 主なチケット管理システム

* Trac
* redmine
* bugzillra
* Mantis
* jira
* Backlog
* GitHub

## CI(continuous integration : 継続的インテグレーション)
### インテグレーションとは
各人が作業した成果物を一か所に集めて、インテグレーション(集合)し、システムが動作、テストできる形となって初めて、各人の開発作業は意味を成し、最終的に商品版として扱える。
インテグレーションとは具体的に以下のようなビルドとテストを行うプロセスを指す。
* すべてのソースコードを一か所に集める。
* 依存するライブラリなどにパスを通す。
* 必要な場合はコンパイルする、
* データベースの構築とデータのロードを行う。
* 必要に応じてミドルウェアの設定や起動を行う。
* 単体テストと結合テスト、ユーザ受け入れテストなどを実施する。

### CIとは
インテグレーションプロセスを継続的に、常時いつでも行うことが、CI(continuous integration : 継続的インテグレーション)である。
常時、インテグレーションを繰り返し、ビルドやテスト結果のチェックを行っておくことで、開発開始からリリース後まで製品の品質を効果的に担保することが可能になる。

### CIに必要なもの
* バージョン管理システム
* ビルドツール
* テストコード
* CIツール

### jenkinsとは
CIツールのデフォクトスタンダード。世界中のプロジェクトで利用されている。
以下のプロセスを自動的に行うことができる。
* ソースコードをチェックアウト
* 自動でビルドおよびテストを実行
* 結果を集計しレポーティング
* 通知

## デプロイ自動化ツール
### vagrantとは
仮想環境を自動で何度も構築することができる。作成と消去を簡単に行え、設定ファイル通りに毎回同じ内容で作れる為、個人が新たに環境を用意するより、はるかに楽に検証環境を構築できる。

### chefとは
サーバ構築の手順書を書いた定義ファイルを用意することで、記述してある通りにサーバへのパッケージのインストールやミドルウェアの設定が可能。
前述のvagrantやjenkins、seleniumと組み合わせることで、様々な環境、ケースでの検証が簡単にかつ自動で実施することが可能。

## テスト自動化ツール
### ~~テスト自動化のメリット~~
### ~~seleniumとは~