リファクタリングプロセスパターン
リファクタリングとは,既存ソフトウェアの理解性や変更容易性を向上させることを目的とした上で,外部的挙動を保存したままで内部構造を改善する活動を指す[8].一般的には,リファクタリング前後で,同一の入力値集合(外部入力)に対して同一の出力値集合(外部出力)が得られることを,外部的挙動が保存されているという.また,リファクタリングでは,大きな設計変更を小さな変換の繰り返しで実現することで,挙動の保存を保証するのが特徴である.ソフトウェア進化では,ソフトウェアの改変を伴うため,リファクタリングは進化パターンでひとつである.
ここでは,リファクタリングにおける新たなコード変換を提案するのではなく,リファクタリングプロセスに関する2つのパターンを紹介する.
パターン 6.1
コア資産は今すぐリファクタリングしよう
Refactor Your Core Assets, Just for Today
コア資産の品質を安定させるための適切なリファクタリング時期を逃さない.
問題
- コア資産のリファクタリングをいつやるべきかわからない.
- 何年もたって肥大化してしまったコア資産に対して,ようやくリファクタリングしようとしても,当時の開発者とは担当も異なり,リファクタリングは容易ではない.
解法
- コア資産のリファクタリングは,コア資産を開発している最中から積極的に実施し,その時点で可能なリソースの範囲で実施すべきである.
- プロダクトライン型の開発は長年に渡り,コア資産を維持管理,拡張させていく.製品開発とコア資産拡張の繰り返しによって,コア資産が肥大化,複雑化が進行する.長年の開発の過程では,当然,コア資産開発者も変化するため,逆に開発時点から継続的に,適切なタイミングでリファクタリングを実施しておかないと,例えば3年後では,当時のコア資産開発者は関わっておらず,過去の経緯は把握できなくなる.
- リファクタリングコストが確保されたプロジェクトも稀であるので,その時のコア資産の開発者がその時点でできることをタイムリーに実施していくことが必要である.
トレードオフ
-利点
- 製品承認(パッケージとして出荷されて)から,大掛かりなリファクタリングをする計画をしていても,技術や市場の変化が速い業界では,投資ができなくなるリスクが高いので,コア資産の裁量で,その場その場でリファクタリングしておくことは重要である.
- そのコア資産が,もっと大きなプロダクトラインの一部に組み込まれることもある.組み込まれてから,品質を高めることは手戻りコストがいっそう高くなる.
-欠点
- その時点でコア開発者のスキルに依存したリファクタリングとなり,リファクタリングした結果のコア資産の品質が均質化されないリスクがある.
根拠
エクストリーム・プログラミングに,YAGNI(You Aren’t Gonna Need It)がある.これは,機能は実際に必要となるまでは追加しないのがよいとする原則である.言い換えれば,今必要なことだけを行うべきである,という意味である.コア資産の拡張におけるリファクタリングは,まさに今必要なことである.追加要求は,コア資産の次の版で実現される要求であるから,その際に対応すれば良い.コア資産の品質を高めるためのリファクタリングは,まさに,今やるべきことである.
パターン 6.2
リファクタリングのフレーム条件を定義しよう
Define Frame Conditions before Refactoring
安全に(挙動の保存を担保して)リファクタリングを実施したい
問題
- 挙動が保存されるかどうかが不明なため,リファクタリングの実施をためらうことがある.
- 保存する挙動が明確でないために,リファクタリング前後で挙動が保存できているかどうかが判定できない.保存する挙動を決めたとしてもそれを明示する方法がなく,挙動の保存を確認できない.
- リファクタリングが改善する内部的構造とテストケースが完全に対応するわけではない.つまり,挙動の保存を保証するためのテストが不十分となる場合がある.このため,テストを行うことで挙動が保存されているという確信が持てない.
解法
- リファクタリングを行う前に,保存すべき挙動を明確に定義する.例えば,定義する内容として,範囲(システム全体,パッケージ,クラス,メソッド,API集合など),要素間関係(継承や参照など),振る舞い(通常処理と例外処理,セキュリティなど)が考えられる.
- リファクタリングによって保存される挙動を形式的に記述し,検証可能とする.
- リグレッションテストだけに頼らず,保存すべき挙動に応じたテストケースを必ず用意する.
トレードオフ
-利点
- 適用したリファクタリングが挙動を保存しているどうかを形式的に確認できる.
-欠点
- リファクタリングの費用が高くなる.
- 保存したい挙動を形式的に記述するためのスキルがプログラマに要求される.
関連するパターン
挙動の保存を確認するためには,OORP[7]の進化を実現するためのテストを書こう / Write Tests to Enable Evolution (OORP パターン6.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)