レガシーコードからの脱却 まとめ – 14.2

14.2 不要な出費はしない 内容 保守性に注力し「CLEAN」でテスト可能なコードを書くことが、ソフトウェアを保守するにも拡張するにもコストを下げる唯一の方法だ。 開発チームの中には、テスト駆動開発(TDD)をしておらず、QAプロセスをあてにして、開発者がコードに関するフィードバックをもらうのに2週間もかかるチームもある。そしてバグを修正するために数週間前に書いたコードを思い出す。そのために開発者の1日のほとんどを費やすようになる。同じバグならTDDで数秒でバグを直すほうが、よほど安くて済む。 本書でも言ったがQAが不要というわけではない。しかし、QAプロセスで品質を保証するだけよりも、良いプラクティスを使って品質を作り出すことに取り組もう。 学び CI/CD、ペアプロ、TDDなどのプラクティスは品質につながるものだが、最終的にランニングコスト削減につながる。ランニングコストが減るから続けることができる。 テストを自動化しリファクタリングしやすい状況を作り、リファクタリングして保守しやすいコードを作り、減った改修コストで更にテストとリファクタリングをする、というサイクルを作る努力をしよう。 学びを活かすアイディア・行動 CI/CD環境構築 テストコードの運用 簡単な案件のペアプロでペアプロ力を増やす

レガシーコードからの脱却 まとめ – 14.1

14.1 もっと良く速く安く 内容 アジャイルプラクティスの各種効果事例を紹介している。 それらによりテスト駆動開発(TDD)は「テストも書くのでコードは倍書くが、質もスピードも上げることができる」と論理付けている。開発者はコーディングとテストに時間を費やしているわけではない。仕様書の解読、ドキュメント作成、会議出席にも時間を費やすし、いちばん多くの時間を浪費しているデバッグ。 TDDはバグを意図的に発生させ修正しながら進める。「それがバグであること」と「修正が正しいこと」を仕様となるテストコードで担保しながら開発を進める。そしてコード変更のたびにテスト実行するため、後で意図しないバグ発生を抑え、デバッグの時間を減らすことができる。 生産性を向上させるのに、品質低下の犠牲を払う必要はない。 以下、論文や調査事例を紹介。 QSMA社によるアジャイルプラクティス導入効果調査 ウォーターフォール 欠陥率が大規模チームであるほど高い。 平均の4倍以上の場合もある。 XP、スクラム 欠陥率が平均より30%〜50%減。 論文:Realizing Quality Improvement Through Test-driven Development: Results and Experiences of Four Industrial Teams(テスト駆動開発を通じた品質向上の気づき:4つの事業チームの事例から) 調査対象のTDDを実践しているすべてのチームが欠陥密度の大幅な低下を示し、「テスト駆動開発は開発チームは生産性を大幅に減らすことなく、開発したソフトウェアの欠陥密度を大幅に減らす」ことができるとしている。 IBMのチーム → 40%減 マイクロソフトのチーム → 60%〜90%減 論文:Evaluating the Efficacy of Test-Driven Development: Industrial Case Studies(テスト駆動開発の有効性評価:業界事例) 同じ組織で、TDDを使ったプロジェクトと使っていない似たようなプロジェクトで、使った方がコード品質が2倍以上良い。 ノースカロライナ州立大学のボビー・ジョージとローリー・ウィリアムズによる2つのソフトウェア開発者のグループ調査 テスト駆動開発者は 高品質なコードを生み出した 18%多くブラックボックステストをパス 開発できる時間が16%も長くなったにも関わらず、テスト駆動開発者のテストケースは平均「メソッドの98%、命令文の92%、分岐の97%のカバー」を達成。 開発者の92%が「テスト駆動開発は高品質なコードを生み出す」と信じていることもわかった Exploring Extreme Programming in Context: …

レガシーコードからの脱却 まとめ – 14

14 レガシーコードからの学び 内容 紹介した9つのプラクティスによって保守可能なコードができ、それによって保守コストを下げることができ、それによってユーザーに価値を提供し続けられることを知った。 特に、テストファースト開発、リファクタリング、ペアプログラミング、設計スキル、継続的インテグレーションといったXPの技術プラクティスが、開発成功の鍵。 アジャイルもXPもソフトウェア開発者がソフトウェア開発のために始めたものであるにもかかわらず、それが正しく定着していない。 オブジェクト指向プログラミングが一般的になったのは1990年代だが、うまく活用し保守性を高められた人は少なかった。 スクラムはXPを支えるはずだったが、技術的なプラクティスはそれほど重きを置かれず、マネジメントプラクティスになってしまった。経験上、アジャイルの本質的な価値は技術プラクティスを適用することによって得られる。だから技術プラクティスはマネジメントプラクティスと同じくらい重要。 プラクティスを正しく使うためには根本にある原則を理解する必要がある。開発者もマネージャーもそれを理解する必要がある。 ここで紹介したプラクティスを「習得する」のは一つのゴールと言える。 学び アジャイル開発シーンには紹介されたプラクティスがいくらか適用されていることが少なくない。しかしそれを開発者が意識してない場合があり、それぞれのプラクティスの習得に向けた動きが出来ていないことは多い。 開発者が意識できていない理由として、以下が思い当たる。 プラクティス適用を明言していない。明言しないと、フォーカスした取り組みが難しくなる。例えば、経験の浅いメンバーへの教育が出来ないし、いちメンバーとして習得に対しての学習効率も悪い可能性がある。プラクティスの適用は、チーム内のレベル感は置いておくとしても、明言することが大事だと感じた。 また、プラクティス習得をトライはしたが、納期の関係などにより、未熟なまま一時中断し、そのまま陳腐化してしまった場合も考えられる。 プラクティスの習得には時間がかかるが、習得しないままだと本質的なプロセス改善はできない。既存の慣れた方法で開発しながらも、同時に練度を上げる方法を考えて進めたい。 学びを活かすアイディア・行動 現場で簡単な案件をペアプログラミング。 現場でCI/CD環境構築

レガシーコードからの脱却 まとめ – 13.10

13.10 本章のふりかえり 内容 13章の内容のふりかえり。 効果的なリファクタリングの観点 オープン・クローズドの原則 機能追加する場合、変更前に変更するためのリファクタリングをする DIできるようにするところを目指す ストラングラーパターンでシステムをリファクタリングする 機能追加の前準備と、実際の機能の追加を切り離すことで、作業が大幅に単純化され、バグ発生リスクが減る 学び なし 学びを活かすアイディア・行動 なし

レガシーコードからの脱却 まとめ – 13.9.2

13.9.2 いつリファクタリングを行うかについての7つの戦略 内容 リファクタリングできるコードはかなり多いはずだ。基本的に触ることもないし、拡張する必要もないコードはリファクタリングしなくてもよい。ここでは何をいつリファクタリングすれば効果的なのかを判断するための7つの戦略を紹介。 戦略 説明 重要なコードがうまく保守されていないとき 明らかに主要機能で、今後も修正は見込まれるけど、複雑になりすぎている場合。まずはテストコードから追加しよう。 コードを理解している人がいなくなったとき いなくなる前に、関連コードを修正する場合は、そのキーパーソンがクリーンアップしよう。基本全員が扱える状態を目指そう。 新しい情報によって、より良い設計が見つかったとき 今の設計を改修するコストよりもメリットが大きい場合リファクタリングが選択肢となる。 バグを修正するとき テストがなかったからバグが発生したと考えることができる。テストを書いてついでにリファクタリングするとよいだろう。 新機能を追加するとき 安全に機能追加する方法は、まず機能追加できるようにリファクタリングしてから機能追加すること。 レガシーコードのドキュメントを書くとき 難解なコードを理解するためのドキュメントに起こすとき。製造中であれば設計を見直し、リファクタリングできるか検討しよう。 作り直すより安いとき 同じような開発プロセスで作り直す場合、高い確率で同じような技術的負債を産む。リファクタリングをプロセスに組み込む方が安くなるか検討しよう。 学び リファクタリングできるタイミングは意外と多い 学びを活かすアイディア・行動 何をいつリファクタリングできるか整理 リファクタリング内容と関連しているコードの整理

レガシーコードからの脱却 まとめ – 13.9 – 13.9.1

13.9 実践しよう 13.9.1 リファクタリングから価値を得るための7つの戦略 内容 リファクタリングから効果的に価値を得るための7つの戦略を紹介。 戦略 説明 既存のシステムを学ぶ わかりにくいところは全部反面教師。 小さく改良する メソッド、クラスの移動、名前変更はツールで安全にできる。これを先にやるとロジックの修正がしやすくなる。 レガシーコードをテストで改良する リファクタリングは後々の開発コストを減らすことができる。テストはリファクタリングを安全にサポートする。まずテストを書こう。 クリーンアップしながら進める 開発を進める中、常にリファクタリングは行おう。 詳細がわかったら実装を再設計する 既存の設計では実現が難しい場合や、明らかに既存設計より良い設計が出た場合、今後を見越して再設計実施を検討する。 進む前にクリーンアップする 動作確認したら次に進む前にかならずリファクタリングする。 やってはいけないことを学ぶリファクタリング リファクタリングには良い学びがある。間違いを認識し、良いプラクティスを積み上げよう。 学び これまでのまとめなので、特になし 学びを活かすアイディア・行動 現場メンバーへの展開

レガシーコードからの脱却 まとめ – 13.6 – 13.8

13.6 オープン・クローズドにリファクタリングする 内容 SOLID原則のOこと、オープン・クローズドの原則では、ソフトウェアは「拡張に対して開かれているが変更に対して閉じられている」べきだとしている。こうすると、新しい機能の追加は、新しいコードの追加と最小限の既存コード変更で済むようにする。 変更を加える際は常に2段階のプロセスで進める。 まず新しい機能に対応できるように、拡張したいコードをリファクタリングする。この時点ではまだ新しい機能は追加しない。リファクタリング中の間違いはテストが教えてくれる。 次に機能拡張ステップに入り、テストファーストでレッド・グリーン・リファクタリングを繰り返す。 この手順を混同して進めると混乱して間違えやすい。 13.7 リファクタリングで変更しやすさを確保する コードの変更しやすさを担保することは、正しい抽象化を見つけ、コードが適切にカプセル化されていることを意味する。 つまり、正しい抽象化とはなにかを理解し、それを見つけていき、カプセル化を理解し、カプセル化をしていくことが重要だ。 最終的に重要なのは「自分がモデル化しているものを理解してモデルへ組み込む」ことで、これが正確性と一貫性をもたらす。 プラクティスやTDDは、自分がやろうとしていることを明確にするためのサポートはしてくれるが、自分がやろうとしてくれることそのものをすべて生み出してくれるわけではない。 コードの変更しやすさが偶然生まれることはない。 13.8 2回めは適切にやる 正しい抽象化は、複数のふるまい・具体的な例を挙げることで、何が同じで何が違うかが浮かび上がり、そこから汎化することで見つけられる。 この作業は、具体例が多いほど精度が高くなり少なければ精度が低くなる可能性があることを意味する。プロジェクトが進むにつれて、具体例は見えてくる傾向にある。つまり、プロジェクト初期は精度の高い適切な設計が難しいことを意味している。 ソフトウェアの「柔らかい」特性を理解して、いつでもリファクタリングできるようにしておくことで、プロジェクトを進めながら設計の精度を上げることができる。 学び 修正する際はオープン・クローズドの原則を意識すること 修正は、拡張用のリファクタリング→機能追加の2段階プロセスを踏む。そのためには、どのように拡張するかをドラフト設計する。 プロジェクトを進めながら、リファクタリングしながら設計の精度をあげよう。 学びを活かすアイディア・行動 現場にプラクティスを展開する モデル化の学習 カプセル化の学習 正しい抽象化、カプセル化を理解することが重要 TDD実践記の展開

レガシーコードからの脱却 まとめ – 13.4 – 13.5

13.4 リファクタリングのテクニック 13.5 変化に対応するためのリファクタリング 内容 リファクタリングのテクニックを紹介するよ。 リファクタリングの手法はたくさんあるが、目的は顧客が変更したいものを変更しやすくすることだ。 それを前提に、標準的なやり方を示す規律を作り、直感的に行うのではなく、皆が共通認識を持ち安全に繰り返していくことが望ましい。 13.4.1 ピンニングテスト DIできるようになるまで(モジュールが分離できるようになるまで)、粒度の粗いテストを書いてコード変更できる準備をする。そしてコードをリファクタリングしてテストを再実行しながら少しずつ修正する。DIできるようになると、モックを使うことができるようになるので、モジュール単位で細かいユニットテストができるようになる。 13.4.2 依存性の注入 DIはモジュールを切り離すことができる。そしてモックを注入すればテストができ、モジュールの正しさは担保できる。そして切り離されていることで、そのモジュールに集中してテスト、リファクタリングができる。 13.4.3 ストラングラーパターン システムを停止せずにコンポーネントを変更する場合は、ストラングラーパターンを使う。古いサービスをラッピングする形で新しいサービスを作り、最終的に古いサービスがなくなるまでゆっくりと置き換えていくという考え方である。 リファクタリングに使える手法だ。 13.4.4 抽象化によるブランチ 「抽象化によるブランチ」は変更したいコードからインターフェイスを抽出して、新しい実装を書くというものだ。そして開発中はフラグで古い機能が動くように管理しておき、新しい実装ができたらフラグで新しい機能が動くように切り替える。 学び DIできる状態かどうかは重要な指標。まず粒度の粗いテストでそこを目指すとよい。 モジュールの種類別に役割を概ね決めておいて、リファクタリングの目標の像をある程度明確にする必要がある。 DIはリファクタリングの手助けをする。 アプリ配信の場合、どのように適用できるだろうか。 抽象化によるブランチというテクニックはフラグのスイッチングを前提に小さなリリースをしていくことに向いている。 リファクタリングの目的はソフトウェアが変更可能でありつづけることで、それを忘れてはいけない。 リファクタリングの手法は体系的で共通認識を持っていることが望ましい。 学びを活かすアイディア・行動 ピンニングテストが必要な箇所の洗い出し DIすべきポイントの洗い出し ストラングラーパターンを使ったリファクタリングの適用の検討 抽象化によるブランチを適用したら効果的にリファクタリングできる箇所がないか調査 毎日学習した内容の展開をする

レガシーコードからの脱却 まとめ – 13.3 – 13.3.3

13.3 コードの変更が必要なとき 13.3.1 既存コードへのテスト追加 13.3.2 良い習慣を身につけるために悪いコードをリファクタリングする 13.3.3 不可避なことを先送りする 内容 変更しづらいレガシーコードは地雷と例えることができる。そのままにしておかないと危ない。 しかし、そんな地雷コードでさえも変更する必要がない限り、そのままにしておけば価値を提供し続けられる。物理的な機械とは違ってまったく故障しないからだ。 ただし、変更、拡張、リファクタリングが必要になったとき、地雷撤去には大きなコストを生む。 ソフトウェアはリリースされれば新しいビジネスの方向性が見えてくる。どのレガシーコードがいつまでレガシーコードのままで良いかはわからない。だから、いつでも変更が簡単な状態を保つことが重要なのだ。 既存コードへのテスト追加は、既存コードをテストしやすいようにする。テストファースト開発で行うよりも難易度は高くなる場合があるが、変更コストの削減を見込める。 だから変更要求がある機能、あるいはそこに関連する機能については積極的にテストを追加した方がよい。 悪いコードのリファクタリングにはスキルアップの価値がある。 開発者全員がリファクタリングスキルを知っているわけではないが、これはソフトウェア開発において常に必要なスキルだ。 リファクタリングができるようになると、最初からクリーンなコードを書こうとするようになる(プレファクタリング)。 悪いコードをリファクタリングすることで「してはいけないこと」「代わりにすべきこと」がわかるようになる。 ソフトウェア開発者としての目標は、私たちが開発するソフトウェアが価値を創造し、未来でも価値を生み出し続けることだ。 しかし、ソフトウェアは実を結ばずに死ぬか、思った以上に長く生き残るかのどちらかだ。コードが将来どのような形になっていくのかを正確に予測することはできない。 ソフトウェアが価値を生み出し続けるためには、投資対効果をできる限り高くするのと同時に、コストを下げることも必要だ。 学び ビジネスが息が長くなるかどうはかはわからない。だから、エンジニアはいつでも変更が簡単な状態にコードを保つ必要がある。 早さのために保守性を失うのであれば、それは保守性を考慮したスキル、プラクティスが足りないからだ。本当に早い人は、きれいだからこそ早い。 変更要求がある場合、テスト追加するチャンスだし、テスト追加して今後の変更コストを削減した方がよい。 開発の学習の中にリファクタリングの工程を入れたほうがよい。TDDを教えることが、それにつながる。 ソフトウェアが価値を生み続けるために、ランニングコストは常に低くあれ。 学びを活かすアイディア・行動 テスト追加のタイミングの共有。 リファクタリング内容と関連モジュールの一覧作成 リファクタリング内容と関連モジュール一覧を作成し、メンバーに実施してもらうことで、リファクタリング力をアップさせる。

レガシーコードからの脱却 まとめ – 13.2

13.2 怠け者になる 内容 クレジットカード業界では全額決済し支払残を残さない人のことを「怠け者」と呼ぶ。 技術的負債と金銭的負債は似ている。たとえば17,000ドル借りていて、最低限の決済で返済した場合、93年と184,000ドルが必要になる。 技術的負債も、ときには問題を先送りにする必要があるかもしれないが、ほったらかしにしていると、思っている以上に技術的負債と付き合っていくことになる。 だれも完璧な仕事をすることはできないし、完璧など存在しないが、それでも納得しながら責任を持てるかたちでリリースしていかないと、結局どんどんきつくなる。 学び 技術的負債は気づけば大きくなる。ほったらかしにしていると、どんどんきつくなる。 学びを活かすアイディア・行動 レビューではアーキテクチャ通りになっているか、読みやすいコードになっているかをしっかり見る。