ソフトウェア変更支援パターン
ソフトウェア進化を実現するために,ソフトウェア変更は必須である.このような観点から,OORP[7]の7章では,システムの移行戦略に関する12個のパターンが紹介されている(OORPパターン7.1〜7.12).さらに,9章と10章では,設計変更(責任の再分配と条件から多態性への変換)に関するパターンが紹介されている(OORPパターン9.1〜9.3,10.1〜10.6).これらは,リエンジニアリングにおける単一のソフトウェア変更を扱ったパターンである.
これに対して,ソフトウェア進化において,変更は繰り返し,かつ,継続的に発生する.このため,ソフトウェア進化を想定した環境では,ソフトウェア構成管理システム(software configuration management system)や版管理システム(version control system)の利用が一般的である[18].また,IDE(Integrated Development Environment)や継続的インテグレーション(CI: Continuous Integration)[19]の普及も進んでおり,ソフトウェア変更を積極的に活用する技術が登場している.
このような状況を受け,ソフトウェア変更を支援する5つのパターンを紹介する.
パターン 4.1
変更履歴を記録しよう
Record Change Histories
変更履歴を記録することで,変更すべき箇所を知りたい.
問題
- ソフトウェアは複雑な依存性を内包しているため,一カ所を変更することで,他の多くの場所にも変更が必要となることが多い.
- ソフトウェアモジュール間の依存性は,詳細に解析をすることでそのほとんどを発見することは可能である.しかし,詳細な解析はコストが高く,また依存関係は膨大な量であるため,依存解析のみで変更が必要となる個所を特定することは困難である.
解法
- 変更履歴(change history)を記録・解析する.
- 変更の度に,ある目的のために変更したモジュール群の履歴を保存する.変更履歴を記録・解析することで,一度に変更するべきモジュール集合を特定することができる.
- 変更履歴には,依存解析の結果必要と判断された変更が残っている.この情報を蓄積,解析することによって,依存解析をせずに一度に変更するべき変更箇所を推薦することが可能となる.
トレードオフ
-利点
- 詳細な依存解析が削減できる.
- 一般的な構成管理ツールのログが利用できるため,過去の開発データを活用できる.
-欠点
- 一定の蓄積データがないと推薦できない.
- 蓄積されているデータに間違い(変更漏れ)があると正しく推薦できない.
関連するパターン
本パターンは,過去から学ぼう / Learn from the Past (OORP パターン5.5) を補うものである.頻繁に変更が行われるプロジェクト,もしくは長期間の記録があり,変更候補が多数提示される場合には,活動履歴を記録しよう/ Record Interaction Histories (パターン4.2)によって候補の順位付けを行うことができる.
パターン 4.2
活動履歴を記録しよう
Record Interaction Histories
活動履歴を記録することで,変更すべき箇所を知りたい.
問題
- 変更履歴を記録・解析する手法によって,詳細な依存解析をせずに必要な変更を推薦することが可能となる.しかし,変更履歴に含まれる情報は変更した結果のみであり,類似したモジュール集合に起こる変更を弁別することが難しい.
解法
- 活動記録(interaction history)を記録する.
- 変更履歴だけでなく,開発中にどのように活動(成果物の参照・変更)したかを記録する.
- 最終的な変更結果だけでなく,どのようなファイルを参照し,どのような順で変更を行ったかを区別することで,より精度の高い推薦が可能となる.
トレードオフ
-利点
- 多数の変更候補がある場合に,状況に応じた適切な推薦が可能となる.
-欠点
- 一般的な構成管理ツール以外に,特別な環境が必要となる.一定の蓄積データがないと推薦できない.蓄積されているデータに間違い(変更漏れ)があると正しく推薦できない.
パターン 4.3
粒度を調整しよう
Manage Granularity
ソフトウェア保守の際には,過去に行った変更の正しさを検証したり,また同チームの他の開発者が行った変更を分析したりする.こういった変更の利活用に役立つよう,変更の記録を行っておきたい.
問題
- ソフトウェア変更の際に,異なる意味の修正が同時に行われていたり,意味的に強い関わりのある修正が複数の別の変更として登録されていたりすると,理解の妨げとなる.
- また,計算機による変更の推薦を効果的に行うためには,関連性のあるモジュールを一度に修正しているような変更履歴が保持されている必要がある.そのためには,複数の意図の変更を混在させて行ったり,細切れに行ったりせず,存在していた関連性を正しく維持したまま変更を構成することが望ましい.
解法
- 適切な粒度で変更を記録する.
- 意味的に強いつながりのある修正を,他の意味の修正を含まないようにひとつの変更として変更履歴に登録する.バグや追加機能候補等を管理する問題管理システムを利用している場合,問題管理システム上の票の粒度を適切に調整し,すべての変更を票と関連づけて登録することにより,変更の粒度を調整することができる.
トレードオフ
-利点
- 意味的に関連のある修正をひとまとめに分析することが出来るため,その理解が容易となる.また,変更の再利用・取り消しも容易となる.
-欠点
- 開発者はしばしば,複数の変更を一度に登録したり,また変更漏れを起こしたりすることがすでに知られており,適切な変更となるためには開発者に注意が必要である.また,誤った粒度での変更を記録し直すこともしばしば必要となる.
-困難
- 互いに影響し合う変更を扱う場合,それぞれを分離することが困難となる.変更の順番や依存関係を調整し,分割を行えるようにすることが望ましいものの,難しい場合もある.
根拠
- 複数の意図の修正が混在したソースコード変更の理解は,そうでないものに比べて難しいと言われている.例えば,リファクタリングと機能変更の混ざった修正は,そうでないものに比べて理解が困難であったという実験結果が報告されている[20].また,そういったもつれた変更が実際には多数行われていることも報告されている[21].
問題よく知られた使い方
オープンソースソフトウェアKDEでは,完了していない変更や原始的(atomic)でないコミットを構成しないよう,コミットポリシーに定めている[22].
関連するパターン
本パターンの実現は,変更履歴を記録しよう / Record Change Histories (パターン4.1)の欠点である,記録に間違いがあると正しく変更を推薦できないことの防止に役立つ.また,本パターンは構成管理パターンランゲージ[23]における Task Level Commit と同種のものである.ただし,保守や進化のためのパターンランゲージとして再構成されている.
パターン 4.4
変更から意味的差分を抽出しよう
Extract Semantic Difference from Changes
過去に発生したソフトウェアの変更をなるべく容易に理解したい.
問題
- ソフトウェアの保守・進化の際には,過去に行った変更の正しさの検証や,同チームの他の開発者が行った変更の分析を行うために,変更内容を理解することが必須となる.
- 変更内容の理解には差分仕様書や変更履歴が助けになるが,これらの記録が散逸している,あるいは不十分な記述である場合,正確な変更内容を理解できない.あるいは,これらの記録が真に正しいものであるかを確認すべき場合が存在する.
- このような場合,往々にして頼りになるのはソースコードのみであり,作業者は2バージョンのプログラムテキストをつぶさに比較する必要に駆られる.しかし全コードを全て作業者が読んで比較するのは非常にコストが高い.
- そこでこのような場合において,diffなどのテキストベースの差分抽出ツールが利用される.あるいは場合によっては,使用されているプログラミング言語を考慮した構文ベースでの差分抽出ツールが使われるかもしれない.差分抽出ツールを用いることにより,コードの内容に目を通す前にまず違いを見つけることができるようになり,作業コストをある程度軽減できる.
- しかし,こうしたテキスト/構文ベースの差分抽出ツールでは,以下に示す2つの点から,なお作業コストは高いといえる.
- 実際にその変更がどのようなものか(ソフトウェアの挙動をどのように変更するものか)を理解するには,結局作業者が2バージョンのコードを詳しく読んで比較する必要がある.
- リファクタリングを経ている場合,実際には処理内容が変化していないにも関わらずコードの記述が変化するが、テキスト/構文ベースの差分抽出ではそのような変更でも抽出されてしまう.
解法
- 変更に伴う意味的差分(semantic difference)を,変更前後のソースコードから取得し,比較する.
- 意味的差分において,ソフトウェアの変更とは,広義にはソフトウェアの振舞いの変化を指す.狭義には,同一の入力に対して2つのバージョンが異なる出力をするようなソフトウェアの変化を指す.逆に言えば,このような変更を表すソフトウェアの差分を意味的差分と呼ぶ.
議論
差分の表現形式に特に定型的なものはなく,技術/ツールによって様々なものがある.代表的なものを以下に挙げる.
- 変化が発生する入力の条件と,各バージョンでの対応する出力(文献[24]など)
- 入出力が変化するソースコード上のパス(文献[25]など)
トレードオフ
-利点
- 抽象度が高く要約された情報が得られる.
- リファクタリングなど,処理内容が実質的に変化しない変更を除外できる.
-欠点
- 関数/メソッド単位であるのが一般的で,またスケーラビリティに困難さが伴うことが多い.大規模なソフトウェアに適用する場合は適用方法に工夫が必要である.
- 理論的な限界や計算量の問題から,ツールで得られるのは本来の差分の「近似」である.多くの技術/ツールは「過大近似」となるように設計されており,本来の差分でないものも差分として報告される可能性がある(が、本来の差分は漏れなく報告される).
問題よく知られた使い方
意味的差分を抽出する技術は,知られたところではJacksonとLaddによって最初に提案され(semantic diff と呼ばれる)[7],その後も改良を加えた様々な技術が提案されている[24][25].
関連するパターン
意味的に単一な変更でない場合,プログラム解析の結果も大きくなって得られる結果も取り扱いが難しくなる.粒度を調整しよう / Manage Granularity (パターン4.3)の適用により変更の粒度に関して注意を払えば,本パターンの効果は大きくなる.
パターン 4.5
変更作業の手順書を作成しよう
Make Instructions for Software Modification
変更作業を実施する前に手順書を作成することで,ソフトウェアを変更する際に発生する作業効率を高める.
問題
- ソフトウェアを変更するためには,問題把握・修正分析,修正実施,レビュー・受入れの各作業が必要となり,この作業に時間が掛かりすぎる.例えば,小さな変更に数日を要することなどが問題となったとする.このことはソフトウェア変更の実施を阻害する要因となりうるため,組織として変更作業の効率を高める必要が生じる.しかし,この作業の効率をどのようにして高めるかが明らかではないという問題がある.
- ソフトウェア変更作業の効率に影響すると考えられる要因は数多く存在する.例えば,対象ソフトウェアの規模,システム構成,求められる信頼性,技術者の作業スキルなどがあり,作業効率を高めるためには,どの要因に着目し,改善すべきかが明らかではない.このため,作業効率の改善は容易であるとはいえない.
解法
- ソフトウェア変更作業の手順書を作成している(手順を標準化している)組織では,平均的に1人あたりの作業量が大きい,すなわち作業の効率が高い傾向がみられる.このことから,変更作業の手順書を作成することにより,作業効率の改善が期待できる.
- ソフトウェアの変更時に実施している作業(問題把握・修正分析,修正実施,レビュー・受入れ)の各手順を明確に定義し,変更作業の手順書を作成する.作業時にこの手順書を参照することにより,作業の効率を高めることを目指す.以下に手順を示す.
- 各技術者(プログラマー)がソフトウェアの変更時に実施している作業,すなわち問題把握・修正分析,修正実施,レビュー・受入れの各作業の詳細な手順を,可能な限り列挙する.
- 列挙されたソフトウェア変更作業をレビューし,複数の技術者がソフトウェア変更作業において共通して実施しており,かつ適切と考えられる手順(例えば,あるモジュールをレビューする際には,特定のチェックリストを利用するなど)を絞り込む.
- 絞り込んだ手順をまとめた,ソフトウェア変更作業の手順書を作成する.
- 各技術者はソフトウェア変更作業時に標準手順書を確認し,それに従って変更を行う.
トレードオフ
-利点
- 手順書を参照して作業することにより,ソフトウェア変更作業の効率が高まることが期待できる.
- 手順書を参照して作業することにより,各技術者の作業効率の差が小さくなる可能性がある.これにより作業時間見積もりの誤差が小さくなることが期待できる.
-欠点
- 各技術者のソフトウェア変更作業を列挙し,それに基づいて手順書を作成するためには,ある程度のコストが必要となる.
- ソフトウェアの進化により,最適な作業手順も変化する可能性がある.そのため,一定期間ごとに作業手順書の内容が適切であるか,検討を行う必要が生じる.この検討にもコストを要する.
-困難
- ソフトウェア作業手順書を適切に作成し,かつ実際に作業実施する技術者に取り入れてもらうためには,手順書に対する技術者の理解と同意が必要となる.
- 技術者がソフトウェアの変更作業を行う際,手順書を参照してその内容に従うことをしないで作業する可能性がある.
根拠
- 保守における作業効率(投入された人的資源に対する産出量)に関連を持つ(影響すると考えられる)特性を明らかにする研究がある[27].
- ソフトウェアの保守作業は,各技術者が1人で大部分の作業を行っていることが多い.他の技術者と共同で作業しないため,各技術者は他の技術者の作業手順を知る機会が少ないといえる.そのため,各技術者が実施する変更作業の内容に差異が生じている可能性があり,さらに,作業内容に必ずしも効率の高くない手順が含まれていたとしても,技術者自身それに気づかない可能性もある.組織が作業手順書を作成し,各技術者が手順書に従って作業することにより,効率の高くない手順を取り除くことができる可能性が高まる.その結果,ソフトウェア変更の作業効率が高まると期待できる.
参考文献
- [1] M. M. Lehman, M. M., “Programs, Life Cycles, and Laws of Software Evolution”, Proc. IEEE, Vol.68, No. 9, pp. 1060-1076 (1980)
- [2] 大森隆行, 丸山勝久, 林晋平, 沢田篤史, “ソフトウェア進化研究の分類と動向”, コンピュータソフトウェア, Vol.29, No.3, pp.3-28 (2012)
- [3] W. M. Ulrich, P. H. Newcomb, “Information Systems Transformation: Architecture-Driven Modernization Case Studies”, Morgan Kaufmann (2010)
- [4] D. L. Parnas, “Software Aging”, Proc. ICSE'94, pp.279-287 (1994)
- [5] M. Jazayeri, “Species Evolve, Individuals Age”, Proc. IWPSE'05, 2005, pp.3-12 (2005)
- [6] E.J. Chikofsky, and J. H. Cross II, “Reverse Engineering and Design Recovery: A Taxonomy”, IEEE Software, Vol.7, No.1, pp.13-17 (1990)
- [7] S. Demeyer, S. Ducasse, O. Nierstrasz, “Object-Oriented Reengineering Patterns”, Morgan Kaufmann (2002)
(ダウンロード)
- [8] M. Fowler, “Refactoring: Improving the Design of Existing Code”, Addison-Wesley (1999)
(訳) 児玉公信, 平澤章, 友野晶夫, 梅沢真史, “リファクタリング”, ピアソンエデュケーション (2000)
- [9] パターンワーキンググループ, “ソフトウェアパターン入門”, ソフト・リサーチ・センター (2005)
- [10] P. Clements and L. Northrop, “Software Product Line: Practices and Patters”, Addison Wesley (2001)
- [11] K. Pohl, G. Böeckle, F. J. van der Linden, “Software Product Line Engineering: Foundations, Principles and Techniques”, Springer (2005)
(訳) 林好一, 吉村健太郎, 今関剛, “ソフトウェアプロダクトラインエンジニアリング ― ソフトウェア製品系列開発の基礎と概念から技法まで”, エスアイビーアクセス (2009)
- [12] J. McGregor, D. Muthig, K. Yoshimura, P. Jensen, “Successful Software Product Line Practices”, IEEE Software, Vol. 27, No. 3, pp.16–21 (2010)
- [13] K. C. Kang, S. G. Cohen, J. A. Hess, W. E. Novak, A. S. Peterson, “Feature-Oriented Domain Analysis (FODA) Feasibility Study”, CMU/SEI-90-TR-21 (1990)
- [14] K. C. Kang, V. Sugumaran, S. Park, “Applied Software Product Line Engineering”, Auerbach Publications (2010)
- [15] L. Gorchels, “The Product Manager's Handbook: The Complete Product Management Resource”, McGraw-Hill (2000)
- [16] 位野木万里, 杉本信秀, 深澤良彰, “ステークホルダの意思決定を支援するプロダクトライン再生シナリオの提案”, ソフトウェア工学の基礎ワークショップ(FOSE2008), pp.75–80 (2008)
- [17] 神谷年洋, 肥後芳樹, 吉田則裕, “コードクローン検出技術の展開”, コンピュータソフトウェア, Vol.28, No.3, pp.29–42 (2011)
- [18] J. Humble, D. Farley, “Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation”, Addison-Wesley Professional (2010)
(訳) 和智右桂, 高木正弘, “継続的デリバリー: 信頼できるソフトウェアリリースのためのビルド・テスト・デプロイメントの自動化”, アスキー・メディアワークス (2013)
- [19] P. M. Duvall, S. Matyas, A. Glover, “Continuous Integration: Improving Software Quality and Reducing Risk”, Addison-Wesley Professional (2007)
(訳) 大塚庸史, 丸山大輔, 岡本裕二, 亀村圭助, “継続的インテグレーション入門”, 日経BP社 (2009)
- [20] S. Thangthumachit, S. Hayashi, M. Saeki, “Understanding Source Code Differences by Separating Refactoring Effects”, Proc. APSEC'11, pp.339–347 (2011)
- [21] K. Herzig, A. Zeller, “The Impact of Tangled Code Changes”, Proc. MSR'13, pp. 121–130 (2013)
- [22] KDE TechBase, “Policies/Commit Policy”,
http://techbase.kde.org/Policies/Commit_Policy#Commit_complete_changesets
- [23] S. Appleton, B. Berczuk, “Software Configuration Management Patterns”, Addison-Wesley (2002)
- [24] S. Person, M. B. Dwyer, S. Elbaum, C. S. Păsăreanu, “Differential Symbolic Execution”, Proc. FSE'08, pp.226–237 (2008)
- [25] S. Lahiri and C. Hawblitzel, “Symdiff: A Language-Agnostic Semantic Diff Tool for Imperative Programs”, Proc. CAV’12, pp.712–717 (2012)
- [26] D. Jackson and D. A. Ladd, “Semantic Diff: A Tool for Summarizing the Effects of Modifications”, Proc. ICSM’94, pp. 243–252 (1994)
- [27] 角田雅照, 門田暁人, 松本健一, 押野智樹, “受託開発ソフトウェアの保守における作業効率の要因”, コンピュータソフトウェア, Vol.29, No.3, pp.157–163 (2012)