「チーム開発実践入門」を読んだ纏め

# チーム開発実践入門

技術評論社の「チーム開発実践入門」を読んで学んだことを随時、（自分のためだけに）纏めていきます。
書籍だけから得た知識で頭でっかちなので、今後、CI/CDの実践を交えて情報を追記していければ。



### P17メモ

- メールでプロジェクト管理をすることは困難
  - 可視性が悪く、優先度や重要度の判断をつけにくい
  - ステータスの管理ができない
  - 一覧性、検索性が低い
    
    

## バージョン管理

P33

- 修正箇所にコンフリクトが発生するのは、同じ箇所を違う目的でコード追加しているからであり、リファクタリングが必要な証拠
- リファクタリング（外部からみた振る舞いを変えないでコードを書き換える）を安心して行うには、テストコードを書くこと

P69

- バージョン管理（Git）

  - リリースブランチ

    - 本番環境へのリリースの際に実際に使うために用意するブランチ
    - masterを常にリリース可能なブランチとして用意するケースもあれば、別途、ブランチを切るケースもある

  - ブランチ作成の流れ

    ```
    # まずはローカルへコピー
    git clone git@github.com<リポジトリ名>
    
    # 新規開発のためのブランチを切る
    git branch new-cool-function
    
    # ブランチを作成したらチェックインし、ブランチを切り替える
    git checkout new-cool-function
    ```

  - コミットとコミットログ

    ```
    git commit -m "メッセージ"
    
    # コミットログの確認
    git log --pretty=oneline
    <ログの表示>
    ```

  - ブランチの確認

    ```
    git branch
    <ブランチ名>
    ```

  - ブランチ作成と切替を同時に実施

    ```
    git checkout -b issue345
    ```

    - git checkout -b でブランチ作成とチェックアウトを同時に行うことができる

  - issue345をmasterにマージする場合

    - masterに切り替えてmergeコマンドを実行するのみ

      ```
      git checkout master
      git merge issue345
      ```

- タグ

  - リリースのタイミングをスナップショットとして記録

    ```
    git tag -a v0.1 -m "最初のリリースバージョン"
    ```

- 過去のコミットの探し方

  ```
  git log --pretty=oneline
  ```

  - 該当のコミットに対してあとからタグ付け

    ```
    git tag -a v0.1 <コミットID>
    ```

  - タグの中身を確認する方法

    ```
    git show v0.1
    ```

  - 中央リポジトリにpush

    ```
    git push origin v0.1:v0.1
    ```

  - 中央リポジトリからclone

    ```
    git clone git@github.com:Coolinc/someniceapp.git
    ```

  - クローン実行後にブランチを作ってそこにタグをチェックアウトする

    ```
    git checkout -b 0.1 v0.1
    ```

    - 0.1がブランチ名、v0.1がタグ名

    ※Gitにおいてタグとブランチは別の名前空間に属しているが、通常利用においてはそれを意識しなくてよいようになっている。なので、同一名になる場合は、「refs/tags/v0.1」など明示する必要がある。

  - git-flowでは中央リポジトリにメインブランチを２つ、各開発メンバーのリポジトリにサポートブランチを３つ、決まったモデルを作ることを提案している。P84

    - メインブランチ

      - 中央リポジトリとそれをクローンした各開発者リポジトリにずっと存在するメインのブランチ

        - master

          リリースするためのブランチ。リリースのたびにタグ付けする。

        - develop

          開発用ブランチ。リリース前の最新バージョン。

    - サポートブランチ

      - 原則、各開発メンバーのリポジトリにだけ存在し、役目が終わったら消える短命なブランチ。

        - feature

          developから派生し、特定の機能開発のために作成されるブランチ。機能開発が終わったらdevelopにマージされて消える。

        - release

          developから派生し、リリースのために準備をするブランチ。リリースのための準備作業中、余計なfeatureが混ざり込まないようにするために作られる。リリースが終わればmasterとdevelopにマージされて消える。

        - hotfix

          主にリリース済みの製品に障害があったときなどに緊急的に作られるブランチ。masterから直接派生し、バグを直したらmasterにマージされ、タグを打つ。またこのバグフィクスが将来漏れないように、同時にdevelopにもマージする。もしそのときリリース作業中でreleaseが存在している場合は、そこにもマージする。

  - git-flowを容易にする**git-flowスクリプト**が提供されている

- git-hub flow

  1. masterのものはすべてリリース可能である
  2. 新しく何かをするときはmasterから直接ブランチを作る
  3. 作成したブランチはローカルマシンにコミットして、リモートリポジトリにも同じ名前のブランチとして定期的にPushする
  4. 開発が完了したらPull Requestする
  5. Pull Requestがレビューされたらmasterへマージし、その場で本番環境にリリースする

- P87のgit-flowとgit-hub flowがチーム開発をするうえではベスト？

- データベーススキーマのバージョン管理

- データベーススキーマをCI（継続的にメンテナンス）することをCDBI（Continuous DB Integration）というが、最近ではデータベースマイグレーションということが多い

- 設定ファイルは環境毎に分けてバージョン管理すべき

  - 絶対に手作業で環境毎に書き換えるようなことをしてはいけない

    

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

- チケット駆動開発の手順

  - 新機能やバグ修正を行う際、その都度に内容や目的を記述したチケットを起票する。
  - チケットの内容に応じて適切にコードを修正してコミットする。このとき、コミットログに関連するチケット番号を入れる。チケットにもコミットログの番号を記入する。

- チケット駆動開発を徹底する

  - バージョン管理システムがもっているクライアントサイドフックやサーバサイドフックを用いるとよい。
  - コミットメッセージのなかにチケット番号が入っているかどうかチェックし、入っていない場合はコミットを受け付けないようにする。

- Redmineをよく使う自分には以下の状況が該当

  > GitHubが登場し、Gitの手軽さとGitHubのPull Requestの便利さが知られ普及した今となっては、あえて自分たちでGitリポジトリをセットアップしてTracまたはRedmineをリポジトリブラウザとして使う意味が薄れました。素直にGitHubを使うのがコスト的にも合理的な時代になっています。リポジトリブラウザとしてGitHubを使い、TracやRedmineはチケット管理システムとしてのみ使うのが良いでしょう。GitHubのService HooksにもTracとRedmineは用意されていますので活用してください。

- Git自身のHookを使う方法

  - GitのHookはクライアント・サーバサイドそれぞれで動作するHookがリポジトリの.git/hooks/の下に多数用意されている。.samplesという名前のサンプルスクリプトを参考に記載すべし。

- どこまでをチケット管理システムでカバーできるのか

  - Scrum開発の言葉を借りて説明

    | No.  | 課題名称                                               | 説明                                                         | 該当するツール         | チケットシステムの管理対象 |
    | ---- | ------------------------------------------------------ | ------------------------------------------------------------ | ---------------------- | -------------------------- |
    | 1    | エピック（大きな要望、部署横断の課題など）             | システム要求に落ちる前の要件定義のフェーズ<br />- 非エンジニアが関わることが多い<br />- 優先順位付けをするのがメインの目的であるため一覧性が重要<br />- 曖昧な状態で始まるものが多く定形フォーマットは向かず、柔軟な編集が可能なものが良い<br />- 複数の人たちの編集、共有がかんたんなものが良い | Google Docs、Excelなど | -                          |
    | 2    | ストーリー（具体的な要望、機能要求や仕様に近いレベル） | 顧客に届ける価値を表す<br />- その製品に責任を持つ人が書くことが多い<br />- 組織やプロジェクトによってかわるが、非エンジニアもあり得るし、プログラマ自身が書くこともある<br />- ステータス管理が必要である<br />- コードとの関連性をつけ始めた方が良い<br />- 担当者が複数であることも単独であることもある<br />※タスクに落とすときはチケット管理システムでチケットの親子関係を作り、親：ストーリー、子：タスクとすると良い。<br />※組織の境目で表計算ソフトと使い分ける方法もある。組織横断の時点では表計算ソフトで扱い、具体的な組織内のタスクに落ちてきたらチケットを起票、という感じ。 | -                      | ○                          |
    | 3    | タスク                                                 | - 具体的な作業内容<br />- ストーリーの下に複数ぶら下がるイメージ<br />- 担当者は単独<br />- コードとの連携が必要かどうかは内容による | -                      | ○                          |
    | 4    | バグ、障害対応、問い合わせ                             | - レベル感はタスクと近い<br />- 担当者は通常単独<br />- コードとの連携が必要 | -                      | ○                          |



## CI（継続的インテグレーション）

インテグレーションとは以下のプロセスのことをいう

- すべてのソースコードを1箇所に集める
- 依存するライブラリなどにパスを通す
- 必要な場合はコンパイルする
- データベースの構築とデータのロードを行う
- 必要に応じてミドルウェアの設定や起動を行う
- 単体テストと結合テスト、ユーザ受け入れテストなどを実施する

これらのプロセスを常時実行するのがCI。



### 振る舞い駆動開発（BDD）

- 最初にテストコードを書くのはTDDと同じ
  - ただし、テストというよりは要求仕様に近い記述をする
  - 仕様を書いてからアプリケーションコードを書くスタイル
  - Cucumber-jvmを使って、自然言語で振る舞いを記述する例が挙げられていた
    - この例では、振る舞いを記述してテストを生成→テストクラスにコピペして実行の手順
    - Pythonで同様のものはないのか？？
      - **behave**というBDDフレームワークが有名な模様（あとで使ってみよう）



## カバレッジ

コードカバレッジとは、対象となるアプリケーションコードのうち、テスト時に何％のコードが実行されたかを表す指標。これを計測することによって、対象のコードがどの程度テストされているかを視覚化できる。ただし、コードカバレッジは対象となるアプリケーションコードが実行されたかどうかだけを計測するものであって、テストコードの内容がテストとして妥当化どうかは判断できない。この点はコードレビューで担保すればよい。



## ビルドが壊れたらどうするか

- Subversionなど中央集権型バージョン管理システムの場合

  壊れたらその時点で同じリポジトリの同じブランチ上で作業しているすべてのメンバのコミットを禁止する必要がある。（壊れたコミットのうえにさらにコミットが重なってしまう）

- Gitなど分散バージョン管理システムの場合

  基本はSubversionと同じで同一ブランチ上で作業しているメンバのコミットを禁止する。ただし、git-flowのように、メンバー各位がリポジトリを持ってプルリクを送る運用の場合はその限りではない。（GithubとTravisCIの組み合わせだけでなく、Github－Jenkinsでもプラグインを使えば実現可能）



## デプロイの自動化

ここではプロビジョニングツールを以下の３つにわけ、具体的なツールでの例を挙げて説明している。

1. Bootstrapping

   サーバOSの設定や仮想マシンによるサーバ立ち上げの自動化に関するツール

2. Configuration

   サーバやミドルウェアの設定を自動化するツール

3. Orchestration

   ソースコードのデプロイやリリースに関わるサーバの操作などを自動化するツール

以下、それぞれのレイヤーに属するツールの説明。

1. Bootstrapping

   1. Kickstart

      ベアメタルサーバのOSインストール時に初期設定を記載したConfigファイルを読み込ませて、一律同じ設定のサーバを作成する。

   2. Vagrant

      ベアメタルではなく、VirtualBoxの仮想環境の設定を自動化するツール。Kickstartのように各用途、各人にベアメタルサーバを用意できないときはこちらを用いる。プラグインを入れればAWSにも使えるらしい。同じくRubyで書かれたConfigurationツールのChefとは相性が良い。

2. Configuration

   1. Chef

      サーバ設定を自動化するツール。小規模なサーバ構築であればChef Soloのみで、大規模なサーバ構築であればChef Severを構築するとよいらしい。検証－本番等の環境差異については、レシピ中の変数にattributeとして記載できるため、差異を吸収できる。よって、全環境で同一のCookbooksを利用すべき。注意事項としては、本ツールを使う以上、手作業でのサーバ構築を禁止しなければいけない。

   2. serverspec

      サーバ構成をユニットテストするためのツール。Chef等でサーバ構築を行ったあとに利用するとよい。Rubyで書かれていてRubyに精通してないとキツいと思われがちだが、対象にたいしてどうなっているべき（shoud be xx）みたいな簡潔な書き方であり、すぐに慣れると思われる。

   以下、Bootstrappinng→Configurationへのベストプラクティスとして、以下のような例が挙げられています。

   <u>ベストプラクティス１</u>	

   　①Vagrantでクリーンなインスタンスを起動

   　②ChefのCookbookとserverspecのテストケースをGitからチェックアウト

   　③Chefが実行され、サーバが設定される

   　④serverspecでサーバの状態テストが実施される

   　⑤実行結果がJenkinsにフィードバックされる

   これら一連の処理がVagrantfileに記載され、実行されます。

   <u>ベストプラクティス２</u>

   　ベアメタルサーバを使わざるを得ない人向け（自分はレガシーな職場にいるのでこちらのほうが使えそう…）。

   　こちらは上記のVagrantがKickstartに変わったようなものだと思っていただければよい。

   　※Kickstartは仮想環境のインストールにも適用できるため、ベアメタルに行く前に検証は必須。

3. Orchestration

   1. Capistrano

      Capistranoサーバを用意するだけど、アプリやDBサーバに手を入れることなく、Pushでリリース作業を行ってくれる。

   2. Fabric

      Python製のツール。Capistranoとの違いは、処理の直列／並列を簡単に切り替えられること。ゼロダウンタイムデプロイメントの例を挙げてこのメリットが説明されている。

   <u>ベストプラクティス</u>

   ​	全体のジョブ管理用のJenkinsとFabricの組み合わせの例が挙げられています。Jenkinsでマスター／スレーブノードを構成し、スレーブエージェント経由でFabricを実行しています。この構成を取ることで、Fabricの実行結果をJenkinsのコンソールログとして残すことができます。

   ※セキュリティ

   ​	Fabric等でリモートサーバに接続する際、どこからでもrootログインを許容するとセキュリティを損なうことになる。Fabric等を実行するサーバに限定してrootログインが可能なように設定すること。また、それらのサーバは限られたユーザのみ限定してログイン可能とし、公開鍵認証方式でセキュリティを担保するとよい。

   ​	sshdでは、/etc/ssh/sshd_configにおいて、Matchディレクティブという条件分岐を設定でき、条件にあったIPアドレスやユーザアカウントからのSSH接続要求があった場合に指定した設定通りの振る舞いを制御することが可能。例では、Fabric実行サーバからの接続のみrootアカウントへのRSA認証でのSSH接続を許可している。

参考）P255では手作業のデプロイで便利なツールが紹介されている。

| ツール名                          | 説明                                                         |
| --------------------------------- | ------------------------------------------------------------ |
| RLogin                            | Windows上で動作するターミナルソフトで、開いているすべての接続にキー操作を同時におくることができ、ログイン先のサーバですべて同じ作業を同時に実施することが可能。 |
| Tera Term                         | RLogin同様、複数の接続先へ同時にコマンドを送信できるブロードキャストコマンド機能がある。 |
| ClusterSSH/ Parallelssh/ClusterIt | LinuxやまｃなどのUnix環境で使える同時実行ツール。            |



## 運用について考慮する

### ブルーグリーンデプロイメント

ロードバランサによりテストアカウントはブルー環境に割り振られ、一般ユーザはグリーン環境に割り振られる。

この章はなんとなく言ってることは分かるんだけど、経験が乏しすぎてなんとも…



## リグレッションテスト

P289で、Seleniumで取得した画面キャプチャをImageMagickで比較する手法が挙げられている。この手法は試したことがないので、ぜひ試してみたい。レガシーな職場（多くのSIerの現場）でも有効なのではと思う。