2.19 リファクタリングと技術的負債
概要と動機
リファクタリングとは、外から見たコードの動作を変えずに、内部の構造を変えることです。変数の名前を変え、長い関数を分割し、クラスを取り出し、絡まった条件分岐を読み手がたどれるものにまとめても、プログラムはまったく以前と同じように振る舞います。その最後の部分が規律のすべてです。リファクタリングは定義上、振る舞いを保存するものであり、同時に振る舞いも変えた瞬間、それはもうリファクタリングではなく、二つの危険なことを同時に行い、それぞれを他方の陰に隠しています。本章は意図してこれらを別の行為として扱います。両者の混同こそが、ほとんどのリファクタリングが間違う所だからです。
大きなチームでは、これは個人開発者の場合よりも重要です。片付けているコードは、何百人もの他の人が読み、依存し、触れるのを恐れているコードだからです。リファクタリングは、共有のコードベースが何年も人員の入れ替わりを通じて住める状態に保たれる方法です。それは、日々のコーディングの質が決まるソフトウェア構築(2.9章)と、リファクタリングを安全にする安全網であるテスト戦略(2.4章)に直接つながります。また、より難しい問いである技術的負債にもつながります。近道、古くなる設計、先送りされた片付けの蓄積されたコストで、将来のあらゆる変更を遅くするものです。リファクタリングはその負債を返す主な方法なので、二つのトピックは一つの章に属します。
企業や政府の設定では、賭け金が上がります。これらのシステムは長寿命で、しばしば何十年も古く、あらゆるコードの変更を統治されたイベントとして扱う監査と変更管理の制度のもとにあることが多いものです。市民の給付システムを長い週末で書き直すことはできません。小さく、元に戻せる、証拠に裏付けられた歩みでモダナイズします。それがまさに、規律あるリファクタリングが与えるものです。多くのチームと長寿命のシステム(10.4章)にまたがってその仕事を調整することは、大規模エンジニアリングの決定的な課題の一つであり、それを誤ることが、組織が凍りつき、もう理解していないソフトウェアを変更できなくなる道です。
主要原則
- リファクタリングは振る舞いを保存します。コードの動作を変えるなら、それは別の変更として、別に行います。
- 信頼できるテストスイートは、安全なリファクタリングの前提条件であり、任意の追加ではありません。
- 小さく、名前のある、元に戻せるステップで作業し、各ステップの後もコードが動く状態を保ちます。
- 技術的負債を可視化して追跡し、それから返済を、英雄的行為ではなく安定した容量として資金づけます。
- すでに変更しているコードをリファクタリングします。そこでは片付けが見合うからです。
- すべての負債が返す価値があるわけではありません。安定した、まれにしか触れられない、あるいはまもなく退役するコードは、そのままにしておけます。
- 内部の品質を、判断に情報を与えるために測定し、操作される目標としては決して測定しません。
推奨事項
リファクタリングと振る舞いの変更を厳密に分ける
始める前にどちらをしているかを決め、一つのコミットで二つを決してぼかしてはいけません。リファクタリングをするとき、以前に通ったテストは、観察できる振る舞いが動いていないので、変更なしに後でも通らなければなりません。振る舞いを変えるときは、独自のテストを伴う独自のコミットとして行います。理由は実践的です。混ざった変更が何かを壊したとき、あなたの再構成がバグを持ち込んだのか、振る舞いの変更がそうしたのかを区別できず、コードレビュー(2.5章)では、レビュアーはどちらの半分もきれいに推論できません。うまくいく習慣は、Martin Fowlerの二つの帽子のルールです。常にリファクタリングの帽子か機能の帽子のどちらかをかぶり、どちらかを知っていて、意図して切り替える。別々のコミットはまた、バージョン管理の履歴を読めるものにし、失敗を二分探索するエンジニアが、純粋なリファクタリングのコミットを自信をもって飛ばせるようにします。
再構成する前に、信頼できる安全網を確立する
テストのないリファクタリングは、編集して祈ることにすぎません。重要なものを再構成する前に、自分が振る舞いを変えたら捉えてくれると信頼できるスイートが必要で、それはテスト戦略(2.4章)の中核の議論です。すでに良いカバレッジのあるコードでは、テストを実行し、小さなステップでリファクタリングし、各ステップの後に再び実行します。テストのないレガシーコードでは、誠実な動きは、まず特性化テストを書くことです。特性化テストは、コードが何をすべきかをアサートせず、コードが今実際に何をするかを、その癖も含めて捉えるので、振る舞いのどんな変化も失敗するテストとして現れます。Michael Feathersは、まさに大きな組織が生きている状況、つまり動き、重要で、テストがないコードのために、このアプローチを広めました。現在の振る舞いが固定されたら、その下で安全にリファクタリングでき、その後でようやくその上で振る舞いを変えられます。
コードの臭いを認識し、小さな名前付きのリファクタリングを適用することを学ぶ
コードの臭いとは、その下で何かが注意を要するかもしれないという表面的な兆候です。育ちすぎた関数、知りすぎているクラス、重複したロジック、長いパラメータのリスト、実際の動作について嘘をつく名前。臭いはヒントであって評決ではないので、盲目的に従うのではなく調査します。対応は、Fowlerのカタログの小さな名前付きのリファクタリングです。関数の抽出、変数名の変更、メソッドの移動、条件分岐のポリモーフィズムへの置き換え、その他数十。名前付きの動きを使う価値は、それぞれが小さく、理解されていて、機械的に安全で、しばしばIDEが直接サポートしていることです。検証できない一つの大きな飛躍をするのではなく、多くの小さく信頼できるステップから大きな改善を構成し、その間ずっとコードを緑に保ちます。
機会に応じたリファクタリングを好み、キャンペーンは本物の構造的必要のために取っておく
ほとんどのリファクタリングは、すでに行っている仕事に織り込まれた、機会に応じたものであるべきです。ボーイスカウトのルールがそれを捉えています。コードを見つけたときより少しきれいにして去る。機能を加えたりバグを直したりするためにファイルに触れるとき、その一角をすでに理解しているので、そこでの小さな片付けは、誰かの許可も別の予算も要さず、時間とともに複利で効きます。チームが機能の仕事を止めて大きな領域を再構成する計画的なリファクタリングのキャンペーンは、ときに必要ですが、高価で、製品の圧力に対してスケジュールするのが難しく、領域のテストが貧弱だと危険です。機会に応じた片付けでは届かない構造的な問題のためにキャンペーンを取っておき、支払っている変更コストについての証拠で論拠を示します。小さな片付けの安定した雫を好んでください。ときどきの英雄的な書き直しより長持ちします。
大きな構造的変更にはストラングラーフィグパターンを使う
サブシステム全体を置き換える必要があるとき、一年走って最後にマージされる一括の書き直しを試みてはいけません。それがモダナイゼーションのプロジェクトが死ぬ道です。木の周りに育って次第にそれを置き換える蔓にちなんでMartin Fowlerが名付けた、ストラングラーフィグパターンを使います。古いシステムの前にファサードを置き、機能の一片ずつを、そのファサードの背後の新しいコードにルーティングし、本番で検証し、古いシステムが完全に囲まれて取り除けるようになるまで繰り返します。各片は小さく、出荷可能で、元に戻せるので、リスクは限られたままで、価値は継続的に届きます。近い親戚である抽象化によるブランチは、一つのコードベースの中で同じことをします。置き換えたいものの上に抽象化の層を導入し、両方が共存する間にその背後に新しい実装を築き、利用者を徐々に切り替え、何も依存しなくなったら古い実装を削除します。どちらも、レガシーシステムが生きたまま進化できるようにし、それが、ほとんどの大きな組織が実際に負担できる唯一の種類のモダナイゼーションです。
技術的負債をポートフォリオとして扱い、可視化する
Ward Cunninghamが作った負債のメタファーは、二つのものを分けます。元本(乱雑なコードや近道そのもの)と、利子(それのために将来のあらゆる変更が払う余分な労力)。すべての負債が等しいわけではありません。Fowlerの四象限は、それを二つの軸で分類します。意図的か不注意か、そして慎重か無謀か。慎重で意図的な負債(「今出荷して、次のスプリントで片付ける。コストは承知している」)は、正当なビジネスの決定です。無謀で不注意な負債(「デザインパターンって何?」)は、単なる損害です。意思決定とガバナンス(1.5章)とその、負債をポートフォリオとして扱う考え方につながる管理の仕事は、負債を推論できるよう可視化することです。重要な項目を仕事のある場所で追跡し、コードにタグを付け、払っている利子を記録して、返済が、最も声の大きい不満ではなく証拠で容量を競うようにします。見えない負債は管理できません。
返済を英雄的行為ではなく安定した容量で資金づける
失敗モードは、片付けを「落ち着いたらやる」ものとして扱うことで、それは決して来ません。持続的なパターンは、返済のための固定された、守られた容量です。各サイクルの明示的な一部、あるいは片付けが同じ領域の機能の仕事に同乗するという常設の合意。うまくいかないのは、誰かが週末を燃やしてすべてを直す、定期的な英雄的スプリントです。それは持続不能で、レビューされず、たいてい自らを元に戻します。安定した容量は利子の支払いを低く保ち、危機が高価な書き直しを強いるまで負債が積み上がる好況と不況の循環を避けます。これは、エンジニアリングの実践であると同時に、マネジメントのコミットメントであり、システムの寿命にわたるソフトウェアの保守(3.7章)の計画の仕方に属します。
内部の品質を測定するが、測定を目標にさせない
内部の品質は、循環的複雑度(関数を通る独立した経路の数)、重複、テストカバレッジ、変更失敗率、疑わしい領域で変更にかかる時間のようなシグナルで測定できます。これらの数字は、負債がどこに集中するかを見つけ、時間にわたる傾向を見るのに有用です。危険はグッドハートの法則です。指標が目標になると、実際には何も測らなくなります。カバレッジの数字を義務づければ、何もアサートしないテストが得られ、低い複雑度のスコアに報いれば、指標をかわすためにロジックがより多くの関数にまき散らされます。指標は会話を始め、ホットスポットを見つけるために使い、人々が操作する動機のあるゲートに、品質指標を決して結びつけないでください。
いつリファクタリングしないかを知る
リファクタリングは投資であり、一部のコードは決して元を取りません。モジュールが安定していて、まれにしか触れられず、やむを得ずまれに変更するときに変更できる程度に十分理解されているなら、それを片付けることは、払っていなかった利子のために費やされる労力です。コードが退役の予定なら、それをリファクタリングするのは、捨てようとしているものを磨くことです。規律は、片付けの予算を、変更が頻繁で苦痛な所、つまり利子を減らすことが実際に複利で効く所に使い、静かな一角はそのままにしておくことです。
トレードオフ: 長所と短所
| アプローチ | 長所 | 短所 |
|---|---|---|
| 機会に応じたリファクタリング(ボーイスカウトのルール) | 安く、継続的で、別の予算が不要。時間とともに複利で効く | カバレッジが不均一。ホットなファイルは改善し、冷たいものは腐る |
| 計画的なリファクタリングのキャンペーン | 片付けでは届かない構造的な問題を直す | 高価。機能と競合する。良いテストなしでは危険 |
| ストラングラーフィグ / 抽象化によるブランチ | 漸進的で、元に戻せ、システムを稼働させ続け、リスクを限る | 紙の上では書き直しより遅い。終わらせる規律が必要 |
| 一括の書き直し | まっさらな状態。レガシーの制約がない | 失敗率が高い。価値までの時間が長い。振る舞いのギャップ |
| 意図的で慎重な負債 | 今価値を出荷する。明示的で計画された返済 | 返済がスケジュールされないと無謀になる |
| 指標でゲートされる品質 | 客観的で可視。ずれを早期に捉える | 操作を招く。ニュアンスを罰する。本物の品質を損ないうる |
中心的な緊張は、今の速度と後の変更容易性であり、それは本物です。締め切りが本物で、負債が慎重で追跡されているなら、近道を出荷することは正しい判断でありえます。間違いは、負債が無料であるふりをすることや、システムが変更するには高価すぎるようになるまで、見えないまま積み上がるに任せることです。毎回取引を明示的にして解決します。負債に名前を付け、利子を見積もり、意図して決め、返済が忘れられるのではなくスケジュールできるよう、決定を記録する。承知で借り、安定して返すチームは、何年も速いままで、盲目的に借りるチームは止まります。
チームで議論すべき問い
リファクタリングと振る舞いの変更が同じコミットに染み出さないようにするにはどうし、私たちのレビューは実際にそれを徹底していますか。 これは章全体の基礎的な規律であり、締め切りの圧力のもとで最も頻繁に破られるものです。「ここにいる間にこれを片付けよう」と、すべてを一緒に出荷するのが効率的に感じられるからです。コストは後で落ちます。混ざったコミットが本番を壊したとき、再構成と機能のどちらがそれを引き起こしたかを誰も言えず、履歴をたどる二分探索はもう信頼できなくなります。最近のプルリクエストを数件持ち込み、いくつが二つの帽子を混ぜたかを正直に確認してください。相反する考慮は摩擦です。仕事を別々のコミットに分けることは、前もって少し手間がかかるからです。答えは、コミットの規約とレビューのチェックリストを形づくるべきです。
技術的負債はどこにあり、それにどれだけの利子を払っていて、何を返済するかを決めるのは誰ですか。 ほとんどのチームはこれに答えられず、それこそが本当の問題です。見えない負債は、コストが実際にある所ではなく、最も声の大きい人によって管理されるからです。可視化するとは、重要な項目を追跡し、コードにタグを付け、どの領域が変更を遅く失敗しやすくしているかの証拠を集めることです。相反する引力は、返済に費やすすべての時間が、機能に費やさない時間であることなので、決定は、エンジニアリングの仕事の統治の仕方(1.5章)につながる、リーダーシップとともに行うポートフォリオの決定でなければなりません。変更失敗率のデータと、皆が触れるのを恐れているファイルのリストを持ち込んでください。答えは、落ち着いたら片付けるという漠然とした意図ではなく、守られた安定した返済の容量になるべきです。
コードベースのどの部分を意図してリファクタリングすべきでなく、それをどう知りますか。 すべてをリファクタリングすることは、何もリファクタリングしないことと同じく失敗です。安定した、まれにしか触れられない、あるいはまもなく退役するコードを片付けるのに費やした労力は、負っていなかった借金の利子だからです。判断は本物です。モジュールは醜く見えても、誰も変更しないなら、投資する場所として誤りでありうるのです。複雑さのシグナルとともに変更頻度のデータを持ち込んでください。高い変動と高い複雑さの交点が、片付けが複利で効く所で、変動の少ないコードは、たいていそのままにするのが最良だからです。相反するリスクは、「そのままにする」が、何も難しいものに触れない言い訳になることです。答えは、投資する価値のあるホットスポットの明示的な短いリストと、静かな一角を無視する許可を与えるはずです。
最も変更する必要のあるコードをリファクタリングするのに十分テストスイートを信頼していますか。そして、どこで先に特性化テストを書かなければなりませんか。 信頼できない安全網は、リファクタリングを編集して祈ることに変え、大きなチームでは、最も怖いコードは通常、最もテストされていないコードで、まさに片付けが最も見返りをもたらす所です。ホットスポットのカバレッジと変更失敗率のデータを持ち込み、再構成が振る舞いを変えても警告を与えない重要なモジュールがどれかを正直に述べてください。相反する考慮は、レガシーコードの特性化テストを書くことは、機能を出荷しない遅く地味な仕事で、永遠に先送りしやすいことです。監査と変更管理のもとにある企業や政府のシステムでは、それらの固定されたテストは、変更が振る舞いを保存した証拠でもあるので、それらに資金を出すことは、安全対策であると同時にコンプライアンス上の対策でもあります。答えは、誰かが触れる前にテストハーネスを得る領域を名指しするはずです。
サブシステムが本当に置き換えを必要とするとき、漸進的なストラングラーフィグのアプローチと書き直しをどう決め、書き直しにノーと言う権限は誰にありますか。 一括の書き直しは、テーブルの上で最も魅力的で、最も失敗しやすい選択肢です。まっさらな状態は、古い制約と生きるよりも、紙の上では常に安く見えるからです。大きな組織にとって、漸進的な道(ファサード、一度に一片、本番で検証)は、システムを稼働させ続けてリスクを限りますが、遅く、終わらせる規律を要し、新しい出発への欲求と競合します。サブシステムの変更頻度マップ、書き直しが価値を届けるまでにどれだけ走るかの正直な見積り、並行する書き直しが埋めなければならない振る舞いのギャップを持ち込んでください。政府や規制された設定では、最後にマージされる数年にわたる書き直しは、監査のもとで生き延びるのがまれなので、答えは、ストラングラーフィグか抽象化によるブランチを既定とし、どんな書き直しも、証拠で論じなければならない例外として扱うべきです。
数字が人々に操作される目標にならずに、内部の品質指標を使って負債の集中する場所を見つけるにはどうしますか。 複雑さ、重複、カバレッジ、変更失敗率のような指標は、大きな組織が、誰一人読まないコードの全体を見渡せる唯一の方法ですが、一つがゲートや人事評価に結びついた瞬間、グッドハートの法則が支配し、その数字は何も本物を測らなくなります。指標がすでに行動を駆り立てている例を持ち込み、それが会話を始めているのか、それとも何もアサートしないテストや、閾値をかわすために関数にまき散らされたロジックに静かに報いているのかを問ってください。相反する引力は、リーダーシップが単純なダッシュボードの数字を欲しがり、「判断を使え」が緑のバーより売り込みにくいことです。指標がガバナンスの報告に流れ込む企業や政府の文脈では、品質のシグナルが投資に情報を与え、ホットスポットを見つけるが、個人をゲートすることは決してないと明確にしてください。答えは、学ぶための測定と、判断するための測定の間に、しっかりした線を引くべきです。
セクター別の視点
スタートアップ。 少数のエンジニアで余裕のあるランウェイもないので、機会に応じてのみリファクタリングしてください。履歴が二分探索可能なままになるよう、コミットごとに一つの帽子をかぶり、意図して取った近道の短く正直なリストを保ちます。片付けのキャンペーンを始めたり、安定したモジュールを磨いたりせず、乏しい注意を、皆が恐れる一つのファイルに使い、変更が実際に怖い所でだけ特性化テストを書きます。この段階では、意図的で可視の負債は問題ありません。あなたを殺すのは、無謀で見えない負債です。
小規模事業者。 専任のプラットフォームやツールの専門家はおらず予算も厳しいので、IDEと言語のエコシステムが無料で与えるものに頼ってください。自動の名前変更と抽出、リンター、基本的なカバレッジのシグナル。ほとんどの負債を、コンサルタントを雇って直すものではなく、通常の仕事の過程で管理するものとして扱い、自分で作って後でリファクタリングしなければならなくなるより、よく保守されたライブラリを買うことを好みます。まれな有償の取り組みは、遅さが直接顧客を失わせている一つのシステムのために取っておきます。
大企業。 多くのチームにわたって、問題はポートフォリオのガバナンスです。共有の負債の台帳、変更頻度と複雑さによるホットスポットの一貫したタグ付け、そして片付けが既定で機能に負けるのをやめるよう、各チームの容量の守られた一部を返済のために。二つの帽子の規律と特性化テストの実践を標準化し、チーム間を移るエンジニアが同じルールを見つけられるようにし、グループ間で調整される構造的な変更にはストラングラーフィグと抽象化によるブランチを使います。品質指標は情報提供にとどめ、人事評価で操作されることなく負債を見つけられるようにします。
政府。 厳格な監査と変更管理のもとにある長寿命のシステムは、規律あるリファクタリングを、エンジニアリングの資産であると同時にコンプライアンスの資産にします。再構成を振る舞いの変更から厳密に分けることで、監査人はどのコミットが振る舞いを変え、どれが単に整えただけかを正確に見られます。調達と透明性の規則は、一括の書き直しより、小さく元に戻せる証拠に裏付けられた歩みを好むので、振る舞いが保存されたことを文書化する特性化テストを伴うストラングラーフィグを既定としてください。負債の台帳とその返済計画を、システムの保守記録の一部にして、監督機関が求めるトレーサビリティを得られるようにします。
事例
スタートアップ。 6人のスタートアップは、速く出荷し、負債を負っていることを知っているので、二つの安いことをうまく行います。すべてのプルリクエストが一つの帽子をかぶります。リファクタリングのコミットは機能のコミットと別なので、高い速度でも履歴は二分探索可能なままです。そして、意図して取った近道の短く正直なリストを、それぞれが払う利子の一行のメモとともに保ちます。決済モジュールが皆の恐れるファイルになったとき、そのリストと変更失敗の履歴が、より清潔な境界を取り出すのに二日を費やす論拠になります。現在の振る舞いを固定するために特性化テストを書き、IDEの名前変更と抽出の動きでその下をリファクタリングし、誰も変更しない安定したモジュールには決して触れません。彼らが負う負債は意図的で可視なので、無謀な種類にはなりません。
大企業。 グローバルな物流会社が、多くのチームが毎週変更する、15年前の注文システムを運用しています。書き直しではなく、ストラングラーフィグパターンを採用します。モノリスの前にファサードを置き、一度に一つの境界付けられた機能を、その背後の新しいサービスに振り分け、次の片が始まる前に本番で検証します。チームと長寿命のシステム(10.4章)にまたがってこれを調整することが難しい部分なので、共有の負債の台帳を維持し、変更頻度と複雑さでホットスポットをタグ付けし、各チームの容量の決まった一部を返済のために確保します。内部の品質指標はどこを見るかに情報を与えますが、誰の人事評価もゲートせず、数字を誠実に保ちます。二年かけてモノリスは着実に縮み、どの単一の変更もシステム全体を危険にさらすことはありません。
政府。 国の税務当局は、あらゆるコードの変更が統治された証拠に裏付けられたイベントである厳格な監査と変更管理の規則のもとで、何十年も古い査定プラットフォームをモダナイズしなければなりません。一括の書き直しは不可能なので、抽象化によるブランチを使います。レガシーの計算エンジンの上に抽象化の層が導入され、その背後に新しい実装が築かれ、利用者が一度に一つの税のルールずつ移行されます。各移行は、振る舞いが変わらないことを証明する特性化テストを伴う、小さく元に戻せる変更として文書化されます。リファクタリングが立法に基づく振る舞いの変更から厳密に分けられているので、監査人はどのコミットが振る舞いを変え、どれが単に再構成しただけかを正確に見られます。負債の台帳とその返済計画は、システムの保守記録(3.7章)の一部になり、監督機関に求められるトレーサビリティを与えます。
ビジネスケース: 動機、ROI、TCO
リファクタリングと負債の返済の見返りは、ソフトウェアを安く変更し続けられる能力であり、ほとんどのシステムで生涯コストの大半は保守なので、ここで総所有コストが大部分決まります。技術的負債の利子は、リーダーシップがすでに追跡している通貨で支払われます。遅いデリバリー、高い変更失敗率、インシデントからの長い復旧時間、最も怖いコードを避けるエンジニア。負債を可視化して返済を安定して資金づければ、最も重要な領域での将来のあらゆる変更のコストを下げ、放置された負債が高価な緊急の書き直しを強いる好況と不況のパターンを避けられます。
採用のコストはささやかで、大半が文化的です。二つの帽子の規律を確立し、リファクタリングが必要な所に安全網を築き、負債の台帳を保ち、返済のための安定した容量の一部を守る。放置のコストは静かに複利で増えます。ベロシティが崩壊し、組織が凍りついて、もう理解していないシステムを安全に変更できなくなるまで、あらゆる変更に利子が積もります。それが最も高価な結果です。リーダーシップに論拠を示すには、負債を彼らがすでに気にかけているデリバリー指標に直接結びつけ、返済を、エンジニアが片付ける時間を求めるのではなく、測定可能な見返りを伴うポートフォリオの決定として枠づけてください。
アンチパターンと落とし穴
- リファクタリングと振る舞いの変更の混在: 一つのコミットが両方を行うため、破損を帰属させられず、履歴が信頼できなくなること。
- 安全網のないリファクタリング: テストされていないコードを再構成して祈ること。信仰による編集です。
- 一括の書き直し: 動いているシステムを一度に置き換えること。失敗率が高く、価値までの時間が長いパターンです。
- 英雄的な週末としてのリファクタリング: 安定した容量ではなく、レビューされず持続不能で、自らを元に戻す片付け。
- 見えない負債: 誰も追跡しない近道のため、返済が実際のコストではなく不満の量で駆動されること。
- 品質指標の操作: 指標が目標になったために、カバレッジや複雑さの目標を達成しながら、本物の品質が落ちること。
- 誤ったコードのリファクタリング: 本物のホットスポットがコストをかけ続ける間に、安定した、あるいはまもなく退役するモジュールを磨くこと。
- 終わりのないリファクタリング: 価値を出荷しない終わりのない再構成。決して片付けないことの鏡像です。
成熟度モデル
- レベル1、開始: リファクタリングは場当たり的で反応的で、しばしば同じコミットで振る舞いの変更と混ざります。信頼できる安全網はなく、技術的負債は見えず追跡されず、片付けはときどきの英雄的な爆発でしか行われないか、まったく行われません。
- レベル2、発展: 一部のチームはリファクタリングを振る舞いの変更から分け、あるテストに頼り、名前付きのリファクタリングと特性化テストが局所に現れます。実践はチーム間で一貫せず、負債は議論されときに記録され、返済は場当たり的に機能と競合して、たいてい負けます。
- レベル3、標準化: 二つの帽子の規律、レガシーコードの特性化テスト、小さな名前付きのリファクタリングが、文書化され、組織全体で期待されています。負債は元本と利子を分ける共有の台帳で追跡され、返済のための守られた容量が各サイクルで計画され、レビューで徹底されます。
- レベル4、管理: 負債と片付けがベースラインに対するデータで測定され、制御されています。変更頻度と複雑さを追跡してホットスポットを見つけ、リファクタリングされた領域での変更失敗率と変更のリードタイムを観察し、各重要な項目が払う利子を記録するので、返済の決定は証拠に基づき、捨てるか投資するかの判断は不満の量ではなく傾向に基づきます。品質のシグナルは、人々が操作できるゲートに結びつけられることなく、投資に情報を与えます。
- レベル5、オーケストレーション: 負債は、組織全体で製品と保守の計画と統合された、継続的に再均衡されるポートフォリオとして管理されます。構造的な変更は日常的に、チーム間で調整されたストラングラーフィグと抽象化によるブランチを使い、返済は継続的で、変更が頻繁で苦痛な所に合わせられ、実践はシステムとそのリスクの状況の変化に応じて適応するので、長寿命のコードは何十年も変更可能なままです。
議論のためのアイデア
- リファクタリングを振る舞いの変更から分けておくための、チームの実際の徹底されたルールは何で、締め切りの圧力のもとでどこで崩れますか。
- どのコードが片付けに値し、どれがそのままが最良かを、証拠をもってどう決めますか。
- 特性化テストがあれば、現在避けているレガシーの領域を、どこで安全にリファクタリングできますか。
- 次の大きなモダナイゼーションで、ストラングラーフィグのアプローチはどんな形になり、最初にどんなファサードや抽象化を導入しますか。
- 技術的負債の台帳は誰が所有し、返済は機能の仕事に対して、実際にどう容量を勝ち取りますか。
要点
- リファクタリングは振る舞いを保存します。振る舞いの変更から厳密に、別々のコミットで分けておきます。
- 信頼できるテストスイートは、安全なリファクタリングの前提条件であり、特性化テストはレガシーコードにそれを与えます。
- 小さく、名前のある、元に戻せるステップで作業し、機会に応じた片付けを好み、大きな構造的変更にはストラングラーフィグや抽象化によるブランチを使います。
- 技術的負債を可視化し、元本と利子を分け、返済を英雄的行為ではなく安定した容量で資金づけます。
- 内部の品質を、判断を導くために測定し、操作される目標としては測らず、安定した、あるいは退役予定のコードはリファクタリングしません。
参考文献とさらなる読み物
- Martin Fowler, Refactoring: Improving the Design of Existing Code, second edition
- Michael Feathers, Working Effectively with Legacy Code
- Ward Cunningham, The WyCash Portfolio Management System (OOPSLA 1992 experience report, origin of the debt metaphor)
- Martin Fowler, “TechnicalDebtQuadrant” and “StranglerFigApplication” (martinfowler.com)
- Kent Beck, Tidy First? A Personal Exercise in Empirical Software Design
- Steve McConnell, Code Complete: A Practical Handbook of Software Construction
- Robert C. Martin, Clean Code: A Handbook of Agile Software Craftsmanship