はじめに
パターンによるソフトウェア構成管理はソフトウェア開発課題のシリーズとして日本では2006年、原著は2002年に発売されたソフトウェアの構成管理に関する書籍です。
**パターンによるソフトウェア構成管理 (IT Architects’ Archive―ソフトウェア開発の課題) **
ステファン・P・バーチャック (著), ブレッド・アップルトン (著), 宗 雅彦 (翻訳)
https://www.amazon.co.jp/dp/4798112593
発表時期からわかる通り、当時は今のようにとりあえずGitかSvnでも使っていればいいだろうという時代ではありませんでした。様々なバージョン管理ツールが群雄割拠をつげており、それぞれ一長一短ありました。その中で「ツールの使い方」ではなく構成管理をどうすべきかを論じる本著は貴重な資料でした。
本書では構成管理を成功に導くいくつかのパターンが紹介されています。
巻末のオマケとして当時存在したバージョン管理ツールで、これらのパターンをどう扱うかが書かれてはいますが、あくまでオマケにすぎません。
こういった性質なためAmazonのレビューでは、以下のように評している人もいます。
導入本として読むにしては、ソフトウェア工学的な経験がないと行間が読み取りにくく、現場での問題解決に使うには具体性に欠ける。
この意見には私も同意で、お手軽にバージョン管理ツールを導入したいからやり方を調べたいという用途に使用するには向いていません。いくつかのバージョン管理ツールを知っている人間が自分のプロジェクトで構成管理をどう進めるかを考えるヒントとするための本です。
残念ながら発売時期的に分散バージョン管理が出る前の本なので、巻末のオマケだけを見る分には古いです。
しかしながら、本質的な部分は今だ使えるものとなっています。
今回は「成功を導くいくつかのパターン」の概要を説明したうえで、現在のGitなどの分散バージョン管理ツールで、どう扱われるかを考えてみることにします。
構成管理のパターン
構成管理を成功に導くパターンとして説明されているものを簡単に抜粋します。
これらのいくつかはすでにバージョン管理ツールを使用している人にとっては、無意識に実現していることも含まれます。
パターン名 | 説明 |
---|---|
Mainline | 実際に開発作業が行われているコードラインの数を管理可能な数に抑えます。ブランチのベースとなるような、またブランチへの作業をマージする先となるような作業の中心となるコードラインを保ちます |
Active Developement Line | 急速に発展していくコードラインについてどう使える状態にするかを、安定と活発さのバランスをとったポリシーを定めます |
Private Workspace | 他人の変更が自分に影響を与えない、自分の作業が他人に影響を与えないワークスペースを作ります |
Repository | 適切なコンポーネント適切なバージョンを使用して適切な開発用のワークスペースを構築するためのRepositoryを用意し一元管理します |
Private System Build | Private Workspaceで変更した自分の更新をRepositoryに反映する前に最新のコードベースでも自分の変更を含めてビルドできるかを確認します |
Integration Build | 多くのワークスペースにおいて各人が行った変更を反映したコードベースが必ずビルドされるかどうかを確認します |
Third Party Codeline | サードパーティのソースコードやライブラリのバージョンと自製品のバージョンとの調整を行うため、サードパーティー用のコードラインを用意します |
Task Level Commit | 作業単位でバージョン管理システムへのコミットします |
Codeline Policy | 自分のコードをコードラインに反映する際に、どういうテストをすべきか、どのタイミングで反映するかなどのルールをコードラインごとに定めて周知します |
SmokeTest | 変更を加えた後もシステムが問題なく動くことを最低限度確認するテストを実施します |
Unit Test | 変更を加えた後のモジュールが要求仕様通り動作することを詳細にテストします |
Regression Test | 変更を加えた後の既存コードが悪くなっていないことを確認します |
Private Versions | 作業者個人の小さい変更を他人に影響を与えずに行い、作業履歴として利用できる方法を提供します |
Release Line | リリース済みの保守用のコードラインを用意します。 |
Release Prep Code Line | リリース前の準備用のコードラインを用意します。このコードラインはリリース後、Release Lineとして使用します |
Task Branch | 長期にわたり複数人が変更する必要があるタスクを現在のコードラインに影響を与えないように、そのタスク専用のコードラインを作成します |
これらのパターンの関連性をあらわしたものが下記の図になります。
Mainline
実際に開発作業が行われているコードラインの数を管理可能な数に抑えます。ブランチのベースとなるような、またブランチへの作業をマージする先となるような作業の中心となるコードラインを保ちます。
このMainlineの例は以下のようになります。
たとえば、リリース用にReleaseAやReleaseBのブランチを作成したとします。
それぞれのブランチはMainLineを基に作成し、それぞれのブランチで発生した変更はMainLineにマージします。
これにより、ブランチが無秩序に増加することを防ぎ、また、マージにかかる作業を最小限にすることができます。
SubversionではMainline考え方をtrunkで実現しようとしています。
Active Developement Line
複数の人間が共同作業をしていく場合、作業の同期をとって各個人の作業内容をまとめる必要があります。
そのため、他人の変更が自分のテストを不合格にすることもありますし、自分の変更が他人のテストを不合格にする場合があります。それを避けるには十分にテストされたコードラインを基に変更を行う必要があります。
このため、各開発者はPrivate Workespaceを作成して作業の分離を行い、自分が行った変更がコードラインを不安定にしないことを確認するためにPrivate System Buildを行い、Unit TestやSmoke Testをできるようにする必要があります。場合によってはRegression Testが必要になるかもしれません。
たしかに十分なテストを行えば、コードラインは安定しますが、それは開発速度の低下とのトレードオフになります。リリース前で許容できる不安定さとリリース後で許容できる不安定さはことなると思います。このようなコードラインの不安定と迅速さを考慮したうえで、各作業者がどうふるまうかをCodeline Policyで決めておく必要があります。
Private Workspace
他人の変更が自分に影響を与えない、自分の作業が他人に影響を与えないワークスペースを作ります。
このワークスペースにはビルドに必要なコンポーネントや変更元となるコードが必要です。
Private Workspaceにはリスクがあります。作成時は適切なバージョンだとしても、長い時間作業をしている間、取得したコンポーネントや変更元のコードが古くなるかもしれません。
このため定期的にPrivate System Buildを行いワークスペースを更新して最新にたもつ必要があります。
Subersionでは、Private Workspaceを作成する場合、checkoutコマンドで自分専用のワークスペースを作成することができます。
また、ワークスペースを更新するにはupdateコマンドになります。
gitの場合、Private Workspaceを作成する場合はcloneコマンドで自分のマシンにリポジトリを作成することになります。
また、ワークスペースを最新にするにはpullコマンドを利用します。
##Repository
適切なコンポーネント適切なバージョンを使用して適切な開発用のワークスペースを構築するためのRepositoryを用意し一元管理します。
以下の図のようにワークスペースには様々なものが含まれます。
自分が作業しているコードはもちろん、依存しているjarやdll、設定ファイルやデータファイル…
もし、自分のワークスペースを作成、更新するのに多くの手作業が必要ならば、いずれめんどくさくなっていくでしょう。
そのためワークスペースの構築・更新を容易にするため、ワークスペースを構築するためのコンポーネントをリポジトリにまとめて一元管理します。
これにより、ワークスペースを作成する際はリポジトリから適切なバージョンを取ってくるだけとなります。
Private System Build
Private Workspaceで変更した自分の更新をRepositoryに反映する前に最新のコードベースでも自分の変更を含めてビルドできるかを確認します。
多くの場合、ビルド後にSmokeTest等を実施します。
ビルド時の検討要素として、クリーンビルドを行うか差分ビルドを行うかが問題になります。
時間が許せばクリーンビルドの方が望ましいでしょう。
また、どのアプリケーションをビルドすべきかという問題もあります。
可能ならば、自分が知っているものすべてが望ましいでしょう。
しかし、これらは完全である必要はありません。作業者全員が無限の時間をかけることはできないのです。こういったものはIntegration Buildでフォローしてもいいでしょう。
##Integration Build
多くのワークスペースにおいて各人が行った変更を反映したコードベースが必ずビルドされるかどうかを確認します。
実行のトリガーとしては日次だったり、コミットイベントだったりします。
ビルドの頻度はビルドの所要時間と変更の発生量に基づいて決める必要があります。
これを実施することにより、コミット漏れなどの事象を検知することができます。
ビルド後にSmokeTestやRegressionTestが実施できるかを検討した方がよいでしょう。
##Third Party Codeline
サードパーティのソースコードやライブラリのバージョンと自製品のバージョンとの調整を行うため、サードパーティー用のコードラインを用意します。
サードパーティ用のコードラインを自製品に取り込むにはSubersionの場合、 svn:externals (外部参照) を使用し、gitの場合はsubmoduleを使用することになります。
##Task Level Commit
作業単位でバージョン管理システムへのコミットします。
これにより、コミットの頻度をあげて、他の開発者との競合を減らすことができます。
また、特定の作業の変更を差し戻すときも、複数の作業を一度にコミットしたときより、作業ごとにコミットしておいた方が楽です。
具体的には障害レポート単位だったりチケット単位だったりします。
これらを発展させた思想がチケット駆動開発になります。
RedmineではSubversion等のコミットログに特別なキーワードをチケット番号を記述してチケットとコミットの紐づけを行えるようにしています。
チケットとSubversion等のリポジトリへのコミットを関連づける
http://redmine.jp/faq/repository/association_ticket_revision/
##Codeline Policy
自分のコードをコードラインに反映する際に、どういうテストをすべきか、どのタイミングで反映するかなどのルールをコードラインごとに定めて周知します
##SmokeTest
変更を加えた後もシステムが問題なく動くことを最低限度確認するテストを実施します。
あくまで最低限度なので、詳細にわたる結合テストではないことに注意してください。
理想をいえば自動化すべきです。
##Unit Test
変更を加えた後のモジュールが要求仕様通り動作することを詳細にテストします。
##Regression Test
変更を加えた後の既存コードが悪くなっていないことを確認します。
回帰テストの実行は仮に自動化しても実行に長い時間がかかるのでどのタイミングで行うかは検討する必要があります。
##Private Versions
業者個人の小さい変更を他人に影響を与えずに行い、作業履歴として利用できる方法を提供します。
Subversionの場合、これを実現するには個人用のブランチを用意する必要があります。
Gitの場合、分散型バージョン管理という性質上、ローカルの環境で自由に作業履歴を利用できます。
##Release Line
リリース済みの保守用のコードラインを用意します。
多くの場合、MainLineからリリース毎にブランチを作成することになります。
ReleaseLineでは、そのリリースに対する障害対策をおこないます。
適度なタイミングで修正したバグをMainLineに反映させる必要があるでしょう。
##Release Prep Code Line
リリース前の準備用のコードラインを用意します。このコードラインはリリース後、Release Lineとして使用します。
##Task Branch
長期にわたり複数人が変更する必要があるタスクを現在のコードラインに影響を与えないように、そのタスク専用のコードラインを作成します。
Git Flowと構成管理のパターン
gitのブランチモデルとして以下の文章が公開されています。
A successful Git branching model
http://keijinsonyaban.blogspot.com/2010/10/a-successful-git-branching-model.html
このブランチモデルの導入を補助するGit Flowというプラグインが存在します。
GitFlowで実現する各ブランチの例は以下になります。
GitFlow Examples
https://gitversion.readthedocs.io/en/latest/git-branching-strategies/gitflow-examples
今回はGitのブランチモデルが構成管理のどのパターンにあてはまるかみてみます。
master
リリースされたタイミングでタグをつけるmasterは強いていうなら、構成管理モデルのRelease Lineパターンに当てはまります。
develop
構成管理モデルのMainlineパターンにあたります。
Feature branches
構成管理モデルのTask Branchパターンにあたります。
hotfix
本番リリースにたいする故障対応になるのでRelease Lineパターンに当てはまります。
masterを元に作成したTask Branchパターンともいえるかもしれません。
Release branches
リリース準備のために作成して、リリースしたらmasterとdevelopにマージして削除しているので構成管理パターンのRelease-Pre Code lineになります。
ただし、リリース後のリリース保守はmasterに任せているようです。
さて、「A successful Git branching model」を読んで一つ疑問が出ると思います。
たとえば、Ver1.0とVer2.0がリリースされて、Ver1.0に対する障害対応が必要になった場合どうするかという疑問です。※これは構成管理のパターンとしてはRelease Lineパターンになります。
これについてはGitFlowのサンプルにSupport Branchesがあります。
リリース後、サポートが必要なバージョンについてはRelease branchesではなくSupport branchesとしてサポートが必要なあいだブランチを消さずに生存させます。
もし障害対応が必要になったら、Support Branchesをもとにhotfix用のブランチを作成します。
まとめ
今回はパターンによるソフトウェア構成管理に記載されているパターンについて簡単に説明しました。
15年以上前の古い本ではありますが、その考え方自体は現在の構成管理の方法にもつながっていると思います。
もし、ツールのHowToでなく構成管理をどのようにすべきかを考えたい人は一読して損はないでしょう。
なお、こういう本に影響を受けて共有フォルダでの管理を改善しようとしてダメだった場合は以下を参考にしてください。
共有フォルダ教が支配する世界に転生した場合の対応案
https://qiita.com/mima_ita/items/ef3588df4d65cf68f745
参考
パターンによるソフトウェア構成管理 (IT Architects’ Archive―ソフトウェア開発の課題)
https://www.amazon.co.jp/dp/4798112593
A successful Git branching model
http://keijinsonyaban.blogspot.com/2010/10/a-successful-git-branching-model.html
GitFlow Examples
https://gitversion.readthedocs.io/en/latest/git-branching-strategies/gitflow-examples
Following git-flow how should you handle a hotfix of an earlier release?
https://stackoverflow.com/questions/16386323/following-git-flow-how-should-you-handle-a-hotfix-of-an-earlier-release