ソースコードを漸進的に改善するための組織的活動のパターン・ランゲージを作りました。リファクタリングはソースコードの改善テクニックですが、ソースコードの品質改善活動を成功させるためにはリファクタリングだけでは足りません。品質改善を利害関係者も含めたチームの活動として捉えることが必要です。このソースコード品質改善パターンを参考にしてソースコードの品質改善を成功させてください。
ソースコード品質改善パターンとは
筆者は、製造業の組込みソフトウェア開発チームに対してプロセス改善や技術支援のコンサルティングを行っています。そのコンサルティングの中で、ソースコードの品質を漸進的に改善することに成功したチームに共通するコツのようなものをパターン・ランゲージとしてまとめたものが、このソースコード品質改善パターンです。
まだ、数チームの事例分析に基づくものなのでパターン・ランゲージとして練りきれていないところがあるでしょう。そのため、このパターン・ランゲージは適用できる範囲が狭い恐れがあります。ですが、下記のような状況の開発チームにおいては、参考になるパターン・ランゲージであると考えています。
- 何年にもわたって製品を支えるソースコードを維持している
- レガシーコードを抱えている
- リファクタリングをやりたいが(やっているが)うまく進められない
パターンについては、私の下記の記事を参考にしてください。
パターン・ランゲージ全体像
ソースコード品質改善パターンの全体像を下図に示します。パターン・ランゲージの読み方については、私が以前に書いた「パターン・ランゲージを使ってチームの問題を解決する方法をデザインする」を参考にしてください。
なお、このパターン・ランゲージは、James O. Coplien氏らによる「組織パターン」から「アーキテクチャチーム」と「缶詰」パターンを拝借し、筆者オリジナルのパターンと組み合わせて作成したものです。
パトレット
パトレットとは、パターンの要約の事です。パトレットを用いてパターンの一覧を下記にまとめました。
パターン名 | 要約 |
---|---|
全ての関係者の理解 | どれくらいのムダが発生しているかの認識を利害関係者間で共有し、ソースコードの品質改善を開始することの理解を得る |
課題の可視化 | ソースコードの課題を特定してそれを共有し、関係者全員が同じ認識を持つようにする |
アーキテクチャチーム | 最初のアーキテクチャを作る責任と権限を持ったチームを作ろう |
缶詰 | アーキテクチャを考え出すチームが苦労しているなら、何日間か物理的に他から隔離して、邪魔されずに作業できるようにしよう |
将来像 | 目指すべきアーキテクチャの将来像を定める |
実験室 | 実際の業務やプロダクションコードに影響のない環境を用意し、将来像の試行錯誤やエンジニアの教育をする |
安全装置 | 既存のソースコードをテストする環境を用意してからソースコードを変更する |
ものさし | ソースコードの変更が将来像に合っているかをチェックする仕組みを構築する |
業務に組込む | リファクタリングを開発チームの努力やモラルのみに頼らず、組織として活動を進める |
漸進的成長 | リスクの面からもコストの面からも少しづつ進めるほうが妥当な判断ができる |
以下が、パターン一つ一つの説明です。
全ての関係者の理解
実際にソースコードをメンテナンスし、日々ソースコードと向き合っている開発担当者は、ソースコードのどこがメンテナンスしづらいか、そのためにいかに多くの時間が浪費されていることを体感として理解しているだろう。
そのため、すぐにでもソースコードを変更し、ソースコードの品質改善に着手したいと思うかもしれない。
しかし、自動テストがないレガシーコードは、テスト環境(安全装置)を用意するのにコストと時間が必要だ。また、目指すべきアーキテクチャの将来像がなければリファクタリングの方向性が定まらないので、行き当たりばったりの改善になるおそれがある。つまり、目指すべきアーキテクチャを協議する場も時間も必要になる。それが意味することは、ソースコードの品質改善はソースコードを書いている個人の活動ではなく、チームの活動であるべきということだ。よって、利害関係者の理解と協力が必須である。
それゆえ:
管理者層、リードエンジニア等の利害関係者を集めよう。QA部門やプロダクトマネージャも非常に重要な利害関係者だ。ソースコードを書いている現場で困っていること、コードの技術的負債のために発生しているムダを共有し、ソースコードの品質改善を開始することの理解を得よう。
課題の可視化
すべての関係者の理解が得られ、品質の良いソースコードに向かってチームが動き始めた。
開発の担当者は、自分達が思うソースコードの良くないところの品質をさっさと良くしたいと思うかもしれないが、使える時間やコストは有限だ。本当に深刻な問題から良くしていきたい。しかし、多くの場合、どこにどれだけの課題があるのか具体的に挙げられない。リファクタリングを始める前に、対象のソースコードのどこにどれくらい深刻な課題があるか知っておく必要があるのに、実はそれが明確には分かっていないことが多いのだ。
また、品質の悪いソースコードは依存関係が複雑で、下手に手を付けると予想外のモジュールに影響が及び、欠陥を生むこともある。全体が見えてこそ、良い作戦が立てられる。
それゆえ:
対象のソースコード全体の内部構造を可視化しよう。また、メトリクスを測定し内部品質を定量化しよう。それらを材料にしてソースコード全体を俯瞰し、課題を特定して共有する。開発チーム全員が同じ認識を持つようにしよう。どの順番で問題に対処すればよいか、認識を合わせよう。ソースコードをリバースエンジニアリングして、UML等の表記法で表すのは良い方法である。
アーキテクチャチーム
これは、「組織パターン」から拝借してきたパターンである。下記に一部を抜粋し、転載する。
…プロジェクトの方向性は定義した。今やシステムの構造を考案する必要がある。
シンプルで凝集したアーキテクチャを作る必要がある。しかし、アーキテクチャは多様な関係者の中で調整もしなくてはならない。 …(中略)… しかし、様々な視点が衝突するため、難しい面もある。
それゆえ:
「共感しあう」少人数のチームを作り、最初のアーキテクチャを定義しよう。…(中略)… ここで重要なのは、チームメンバーのほとんど、もしくは全員がシステムの一部に割り当てられなければならないということである。それぞれに対してアーキテクチャ上の責任を負うのである。
チームとしてのこの活動を組織構造によって正当化すると、ビジョンを共有するのに必要な社会的やりとりが支えられる。
缶詰
これは、「組織パターン」から拝借してきたパターンである。下記に一部を抜粋し、転載する。
…プロジェクトの最初の構造を考えだすためのアーキテクチャチームがいる。 …(中略)… 多様な人々で構成されたチームが、一貫したアーキテクチャを一つ考案しなければならない。プロダクトには自己充足して一貫した単一のアーキテクチャが必要だ。しかし、プログラマは別々に作業したいという(強い)性質を持っている。…(中略)… 誰か一人にアーキテクチャを作ってもらうこともできるが、それでは全員がアーキテクチャを理解できなくなってしまう(そして、従わなくなってしまう)。
それゆえ:
ドメインエキスパートたちを同じ部屋に集めて、アーキテクチャを考えだしてもらおう(あるいは戦略的な課題に対応してもらおう)。
このパターンの鍵は二つある。第一に、全員が物理的に一緒にいなければならない。 …(中略)… 第二に、アーキテクチャチームは全身全霊で打ち込まなければならない。余計な作業が入ったり、邪魔されたりしないように、アーキテクチャチームのメンバーを隔離しなければならない。
将来像
対象ソースコードの課題は明らかになった。一部の課題については一般的な修正方法が分かっている。
しかし、修正方法が分かっているからといって、すぐに設計を見なおして修正を始めるのは危険だ。局所的に改善されたソースコードにはなるだろうが、大局的に見た時のメンテナンス性は改善されないこともある。
ソースコードを漸進的に改善するにしても、全体観を元にした修正の方向性が必要なのだ。
それゆえ:
目指すべきアーキテクチャの将来像を定めよう。そのためにアーキテクチャチームを結成し、少数精鋭で設計指針を定めるのもよい。アーキテクチャチームが業務から離れて、缶詰になって将来像を協議することも必要かもしれない。
場合によっては、技術的な調査をするために実験室にて多少の試行錯誤が必要なときもある。
実験室
対象ソースコードの問題が明らかになり(課題の可視化)、検討が進むと、チームが目指すアーキテクチャの将来像ができてくる。ソースコードの品質改善活動を更に前に進め、具体的な将来像を定めて、実際のプロジェクトへ適用したい。
しかし、この段階で実際のプロジェクトへ活動を広げるのが危険な場合も多い。まず、将来像を元にソースコードを実際にリファクタリングできるか確かめなければならない。エンジニアの教育も必要だ。これらを実プロジェクトに混乱をもたらすことなく進めなければならない。
それゆえ:
実務に影響のない環境を用意し、将来像の試行錯誤やエンジニアの教育をしよう。教育する場合、実際のソースコードに存在する課題を模したソースコードを使って、リファクタリングの教育をケーススタディとして実施するのも効果的だ。
ここでの活動は、実プロジェクトに改善活動を展開するための準備運動や練習試合だ。実プロジェクトへ活動を展開するときに発生する問題を減らすよう、計画することが必要である。
筆者注)このパターンは、「缶詰」パターンの変形のようにも思えるが、筆者の観察ではエキスパートが集まってアーキテクチャを考え出す缶詰活動と、コードの実験やエンジニアの教育など実験室での活動は別の活動と見なせることが多かった。参加者は重なっていることが多いが。そのため、現時点(2016年8月)ではパターンを分けている。
安全装置
リファクタリングによるソースコードの品質改善は、既存のソースコードの構造に手を入れながら、内部品質の改善を行う。これを既存のソースコードの振る舞いを変えることなく実施しなくてはならない。
しかし、人間はミスをするものだ。どんなに慎重にソースコードを変更しても、振る舞いを変えてしまうことがある。このミスをゼロにすることはできない。そうではなく、ミスをしてもそのミスをカバーし、支えてくれる安全装置をソースコードの変更作業に組込んでおくことが必要だ。
それゆえ:
実装済みの機能に対してテストを用意しよう。ユニットテストレベルの例で言えば、テスティングツールを用いて、既存のソースコードのテストを書いてからソースコードを変更しよう。xUnitと呼ばれる単体テストツールを用いてテストケースを書き、それを常に実行するとよい。ミスがあればテストが失敗し、その変更が間違っていたことを教えてくれる。
また、テスト計画や戦略を立てるときには、課題の可視化によって得られた結果を用いるとよい。
ものさし
将来像が決まり、チームが目指すべき方向が定まった。これからチームメンバーがリファクタリングを始め、ソースコードの品質改善に本格的に取り組む。
ただし、詳細に立ち入れば立ち入るほど全体観を見失いがちになるものだ。ソースコードを相手にしている時に将来像に合っているかを常に考え続けるのは難しい。
よって、将来像に合っているかを測れるものさしを持ち、時々立ち止まってソースコードの変更が狙い通りであるかをチェックできるようにすることが望ましい。
それゆえ:
変更が将来像に合っているかをチェックする仕組みを作ろう。チェックの方法は様々だ。専任のアーキテクトのレビューでもよいし、ソースコードメトリクス測定ツールを CI ツールと連携させて自動測定してもよい。その際、将来像に合うソースコードメトリクスとその基準値を用意することが必要だ。
業務に組込む
リファクタリングによるソースコードの品質改善は、実際の業務に組込めないと一過性の活動に終わる。
小さなソフトウェアの場合ならそれでもよいが、ある一定規模のプロジェクトでは一気にリファクタリングできないため、機能の開発とリファクタリングを並行で進めることになる。
しかし、実際のプロジェクトでは納期のプレッシャーが高く、リファクタリングの優先度が相対的に下がりリファクタリングが進まない。リファクタリングを通常業務の中の1つとして合意されることが必要になる。
それゆえ:
実際のプロジェクトのプロセスにリファクタリングを取り込み、開発活動の中のひとつであると認識されるよう開発現場の合意を取ろう。リファクタリングを現場のエンジニアの努力やモラルのみに頼らず、組織として活動を進めよう。そのためには全ての関係者の理解を取り付けておくことが必要だ。
漸進的成長
目指すべきアーキテクチャの将来像がある。将来像に合ったソースコードのメトリクスと基準値(ものさし)も決まり、後は進むだけだ!
しかし、一度でリファクタリングしようにも、技術的にリスクが明らかになっていない項目があったり、コストとの兼ね合いでどこまで改善するのがベストなのか不明な場合のほうが多い。ソースコードの規模が小さかったり、リリースまでの期間に余裕がある開発でない限り、一度きりのビックリファクタリングをするのは現実的でないのだ。
それゆえ:
少しづつ進めてフィードバックを得ながらソースコードの改善をしよう。中にはコストやリスクなど総合判断して後回しにした方がよい設計課題もあるだろう。また、チームやプロダクトを取り巻く環境の変化によって、優先順が早くなる場合もある(遅くなる場合もある)。リスクの面からもコストの面からも少しづつ進めるほうが妥当な判断ができるのだ。
そのためには、リファクタリングを業務に組込み、日々の開発活動の中で少しづつ進められるようにしておかなければならない。
最後に
上記のパターンは、筆者が見てきたリファクタリングを成功させた開発チームの活動と、うまくいかなかった開発チームの分析結果からまとめたものです。記事の冒頭で示したコンテキストのもとで有効なパターン・ランゲージになっていると思います。しかし、このパターン・ランゲージは、まだ発展途上です。今後、もっと多くのチームの事例の分析や適用事例を増やして、洗練させていきたいと思います。
参考文献
- 「組織パターン チームの成長によりアジャイルソフトウェア開発の変革を促す」James O. Coplien(著), Neil B. Harrison(著), 和智 右桂(訳), 翔泳社 (2013/08)
- 「レガシーコード改善ガイド」マイケル・C・フェザーズ(著), ウルシステムズ株式会社(監訳), 翔泳社 (2009/07)
(誤字修正:2016/09/15)