チーム開発実践入門を読んで重要なポイントをまとめてみた



![Qiita](http://ecx.images-amazon.com/images/I/51b5E5DpK1L._SL500_AA300_.jpg "チーム開発実践入門")
[チーム開発実践入門](http://gihyo.jp/book/2014/978-4-7741-6428-1 "チーム開発実践入門")  
以下に引用しながら私の体験を交えた感想を記載して参ります。
※先に引用して書いているので、感想がない部分がございますがご了承願います。


## 理想的なプロジェクト
>
* チケット管理システムに課題・障害などを集約し優先度と重要度が分かるようにする
* できる限り（正しく）バージョン管理システムを利用する
* 繰り返し再検証可能なCIシステムを用意する
* 環境の影響を最小限にとどめ、常にリリース可能にしておく
* すべてを記録して追跡可能にする


これまで客先常駐ばかり経験しているので、このような内容を網羅しているプロジェクトには参加したことはありません。
チケット管理やバージョン管理やリリースに関してはルールはありましたが、CIは使用したことがなく名前しか聞いたことがない状態でした。

## 分散バージョン管理システムを使うべき5つの理由
>
* リポジトリの完全なコピーをローカルマシンに持つことが出来る
* 動作が早い
* 一時的な作業の履歴管理が容易である
* ブランチ、マージが気軽にできる
* 場所を選ばないコラボレーションが可能

CVSやSVNの集中バージョン管理が根強く残っているプロジェクトがまだまだ（特に地方）多いと思います。
正直なとこは、この５つでは「じゃあGit使おう！」とはならない現実はありますよね。

## 分散バージョン管理システムのデメリット
>
* 真の意味では最新バージョンはシステム上存在しない（中央リポジトリを運用上決める）
* 真の意味ではリビジョン番号はない（チェンジセットを利用する）
* ワークフローが柔軟に設定出来過ぎるため混乱しやすい（GitHubを利用するのが一番容易）
* 考え方に慣れるのに時間がかかる（学習コストは高いが払う価値はある）



## バージョン管理で管理するべきもの
>
* ソースコード（テストコード含む）
* 要件書、設計書などのドキュメント
* データベーススキーマ、データ
* ミドルウェアなどの設定ファイル
* ライブラリなどの依存関係の定義

テストコードやドキュメント、設定ファイル、依存関係の定義ってあたり非常に同感です。
以前classファイルまで管理に入れているプロジェクトがあって、「それはいらんやろ！」って突っ込みました。「何を管理するべきか」ってことを事前に決めておく必要があると思います。

## github-flow
>
* masterのものはすべてリリース可能
* 作成したブランチはローカルマシンにコミットして、リモートリポジトリにも同じ名前のブランチとして定期的にpushする
* 開発が完了したらmasterへPull Requestを送る
* Pull Requestがレビューされたらmasterにマージし、その場で本番環境にリリースする

この考え方はすごくしっくりきました。以前読んだ「[GitHub実践入門](http://gihyo.jp/book/2014/978-4-7741-6366-6?ard=1397866409 "GitHub実践入門")」にもこのような記述がありました。プロジェクトによってgit-flowかgithub-flowにするかは問わないが、フィットするフロー作りをプロジェクト開始時には決めておく必要があるのではないかと思いました。


## データベーススキーマをどのように管理すればよいか
### バージョン管理に必要な要件
>
* どのような環境でも同じ手順でデータベース構築が可能なこと
* 繰り返し再実行が可能なこと
* テキストファイルであること

## 依存関係解決システム
>
* 共通ライブラリを管理するリポジトリ
* ライブラリへの依存関係を定義するファイル
* それらを使って実際に依存関係を解決するスクリプト

### JVM系言語
>
* Apache Ant
* Maven
* sbt
* Gradle

#### Mavenリポジトリ
>
* Mavenセントラルリポジトリ
* Sonatype

### スクリプト系言語
>
* CPAN
* PyPl
* RubyGems
* npm

## プロジェクトがうまく回らない理由
>
* 目標が間違っている
* 見積が不正確で納期が以上に短く、要員が不足している
* プロジェクトの終わりが定義されていない
* メンバーのモチベーションが上がらず進捗しない
* プロジェクトの見える化ができていない
* タスクの整理、進捗の管理、情報の共有などができていない

上記の通りだと思います。加えて「強力な社内政治が存在する」って項目を追加したいですね。
以前体験した出来事として、クライアントの要望を何でもかんでも受け入れすぎてしまうプロジェクトリーダーに苦しめられたことがありました。それは上記の６つの内容がきちんと認識できていない方だったんだろうなと思います。（性格によるものという部分はここでは置いておきます。）


## チケット管理システムの導入メリット
>
* タスク管理をするための基本機能がある
* 一覧性、検索性が高い
* 情報の一元管理と共有が可能である
* レポーティングに利用できる
* 他システムとの連携が可能、拡張性がある

Excelをマクロを組んでゴリゴリ作りこんでいる管理表を幾度と無く見てきました。悲しくなりますよね。「タスク管理をするための基本機能がある」という項目のメリットで以下が挙げられていました。
>
* 「何をしなければいけないのか」というタスクの定義
* 「誰がするのか」という担当者のアサイン
* 「いつまでにするのか」という期限の管理
* 「今どうなっているのか、作業中なのか、完了したのか」というステータスの管理

「誰がするのか」ってことがいつまでも決まらないことってありました。「手が空いた人」という曖昧なアサイン程困るものは無いですよね。


## インテグレーション
### 以下の様なビルドとテストを行うプロセス
>
* すべてのソースコードを１カ所にに集める
* 依存するライブラリなどにパスを通す
* 必要な場合はコンパイルする
* データベースの構築とデータのロードを行う
* 必要に応じてミドルウェアの設定や起動を行う
* 単体テストと結合テスト、ユーザ受け入れテストなどを実施する

これまで、単体テストや結合テストなどは"実装"工程とは完全に切り離してすすめることが多かったと思います。ここらへんのプロジェクトの進め方は社内政治が大きく関わっていることもありますよね。

## なぜCIプラクティスが求められるのか
>
* コストメリット
* 市場の変化のスピード

文中、ここで言う"コスト"とは「バグフィックス」と「メンテナビリティ」を指していました。この2点って工数を低く見積もられがちだと個人的には思いますが、本当は複雑で大変なこともありますね。共感した部分は以下の部分です。

『機能追加のスピードが上がることによる経済的なメリットだけでなく、運用や機能追加を担当する開発者の精神衛生を保ち、開発生産性を高める』

精神衛生って言葉が出てくるあたりが、エンジニア向けの書籍だなと感じました。


## テストを書くためのフレームワーク
>
* テスト駆動開発(TDD)系フレームワーク
* 振る舞い駆動開発(BDD)系フレームワーク

TDDはチームとしては実施するよりは、個人の生産性を高めるという目的で導入して行っていました。テストコードってどうやって書くの？みたいな質問された時点で「ここには、テストコードを書く文化がないのか・・・」と思ったので諦めました。BDDって何だと思ったら正式には「Behavior Driven Development」っていうみたいですね。テストファーストに対してスペックファーストという言い方するみたいです。ふむふむ。

## CIの運用
ビルドが壊れた場合の運用について、記載がありましたが実運用を経験したことがないのでとても新鮮でした。「ビルドを壊した時の罰ゲーム」についてという部分は、ここらへんは各社どのようなユニークな取り組みがあるのか知りたいですね。

## 開発者(Dev)と運用者(Ops)とのデプロイの自動化における共通認識
>
* すべてのバージョンを管理せよ
* すべての環境を同じ方法で構築せよ
* リリース作業は自動化し事前に検証せよ
* 繰り返しテストせよ

アプリケーションのビルド/デプロイ/テスト/リリースのプロセスを自動化する実装を『デプロイメントパイプライン』と呼ぶそうです。

## プロビジョニングツールチェーン
>
* ブートストラッピング(Bootstrapping)→サーバOSの設定や仮想マシンによるサーバ立ち上げの自動化に関するツール
* コンフィグレーション(Configuration)→サーバやミドルウェアの設定を自動化するツール
* オーケストレーション(Orchestration)→ソースコードのデプロイやリリースに関するサーバの操作などを自動化するツール

それぞれの項目について以下のツールを挙げていました。
### Bootstrapping
* Vagrant
* Kickstart
* AWS(EC2)
* Cobbler
* VMware

### Configration
* Puppet
* Boxen
* Chef
* serverspec(RSpec)

### Orchestration
* Capistrano
* Fabric


BootstrappingやConfigrationのツールはいくつか使ったことはありましたが、Orchestrationに関しては触ったことなかったです。

## コンフィグレーションのベストプラクティス
### サーバ構築を自動化
Jenkins + Chef + serverspec + Vagrant

### サーバ投入からサービスインまでの時間の時間を短縮
Kickstart + Chef + serverspec


## リリース作業についてのアンチパターン
>
* リリース作業を手動で行う
* リリース作業の内容が毎回違う
* リリース作業に特別な知識が必要(属人性が高い)
* 何度も繰り返してリリースが行えない

耳が痛い内容ですね。リスクが高い作業で精神衛生的にも良くないですね。

## オーケストレーションのベストプラクティス
### デプロイの自動化
Jenkins + Fabri

## まとめ
重要なポイントをまとめていたら、こんな長文になってしまいましたが一度読んだだけでは理解出来ていない部分が多いので繰り返し読んだり改善ポイントが挙がったタイミングで読み返して、チームとしての取り組みへ反映していければいいと思います。