虎の穴開発室ブログ

虎の穴ラボ株式会社所属のエンジニアが書く技術ブログです

MENU

『レガシーコードからの脱却』を読んだ感想

皆さんこんにちは、虎の穴ラボのH.Kです。
オライリー書評シリーズは、今回で第7弾になります。
(前回の書評はこちら)

toranoana-lab.hatenablog.com

その他のオライリー書評はこちらになります。

今回の記事では、2019年9月のオライリー定期購読で届いた、『レガシーコードからの脱却』を読んだので感想を書きたいと思います。

読んだ動機

とらのあなの通販サイトは2018年6月にリニューアルされました。
リリースから1年半以上経過し、当時からは新機能も多数加わったこともあり、徐々に改修時に「技術的負債」を実感することが多くなりました。
開発メンバーも増えていく中で、いかに開発効率をあげることができるか、という課題もあったため、本書を読み、今後の開発に活かしていこうと考えました。

目次

目次は以下のような構成になっています。

目次

第Ⅰ部 レガシーコード危機

1章 何かが間違っている
    1.1 レガシーコードとは何か?
    1.2 滝(ウォーターフォール)に流される
    1.3 一か八かの勝負
    1.4 なぜウォーターフォールは機能しないのか?
        1.4.1 レシピと公式
        1.4.2 開発とテストの分離
    1.5 「プロセス」が「忙しい仕事」になるとき
    1.6 ガチガチのマネジメント
    1.7 ここにドラゴンがいる
    1.8 未知を見積もる
    1.9 素人業界
    1.10 本章のふりかえり

2章 CHAOSレポート再考
    2.1 CHAOSレポート
        2.1.1 成功
        2.1.2 問題あり
        2.1.3 失敗
    2.2 スタンディッシュレポートの誤り
    2.3 プロジェクトがなぜ失敗するのか
        2.3.1 コードの変更
        2.3.2 蔓延
        2.3.3 複雑性の危機
    2.4 失敗のコスト
        2.4.1 ここにも10億ドル、あそこにも10億ドル
        2.4.2 新しい研究、相変わらずの危機
    2.5 本章のふりかえり

3章 賢人による新しいアイデア
    3.1 アジャイルに入門する
    3.2 小さいほどよい
    3.3 アジャイルを実践する
    3.4 芸術と技能のバランスを保つ
    3.5 アジャイルがキャズムを超える
    3.6 技術的卓越性を求める
    3.7 本章のふりかえり

第Ⅱ部 ソフトウェアの寿命を延ばし価値を高める9つのプラクティス

4章 9つのプラクティス
    4.1 専門家が知っていること
    4.2 守破離
    4.3 第一原理
    4.4 原則となるために
    4.5 プラクティスとなるために
    4.6 原則がプラクティスをガイドする
    4.7 予測か対応か
    4.8 「良い」ソフトウェアを定義する
    4.9 9つのプラクティス
    4.10 本章のふりかえり

5章 プラクティス1 やり方より先に目的、理由、誰のためかを伝える
    5.1 やり方は言わない
    5.2 やり方を目的に転換する
    5.3 プロダクトオーナーにいてもらう
    5.4 ストーリーで目的、理由、誰のためかを語る
    5.5 受け入れテストに明確な基準を設定する
    5.6 受け入れ基準を自動化する
    5.7 実践しよう
        5.7.1 プロダクトオーナーのための7つの戦略
        5.7.2 より良いストーリーを書くための7つの戦略
    5.8 本章のふりかえり

6章 プラクティス2 小さなバッチで作る
    6.1 小さなウソをつく
    6.2 柔軟に進める
    6.3 ケイデンスがプロセスを決める
    6.4 小さいことはよいこと
    6.5 分割統治
    6.6 フィードバックサイクルを短くする
    6.7 ビルドを高速化する
    6.8 フィードバックに対応する
    6.9 バックログを作る
    6.10 ストーリーをタスクに分解する
    6.11 タイムボックスの外側を考える
    6.12 スコープを管理する
    6.13 実践しよう
        6.13.1 ソフトウェア開発を計測する7つの戦略
        6.13.2 ストーリーを分割する7つの戦略
    6.14 本章のふりかえり

7章 プラクティス3 継続的に統合する
    7.1 プロジェクトの鼓動を確立する
    7.2 完了と、完了の完了と、完了の完了の完了が違うことを知る
    7.3 継続的にデプロイ可能にする
    7.4 ビルドを自動化する
    7.5 早期から頻繁に統合する
    7.6 最初の一歩を踏み出す
    7.7 実践しよう
        7.7.1 アジャイルインフラストラクチャーの7つの戦略
        7.7.2 リスクを減らす7つの戦略
    7.8 本章のふりかえり

8章 プラクティス4 協力しあう
    8.1 エクストリームプログラミング
    8.2 コミュニケーションと協働
    8.3 ペアプログラミング
        8.3.1 ペアリングのメリット
        8.3.2 どうやってペアを組むか
        8.3.3 誰とペアを組むか
    8.4 バディプログラミング
    8.5 スパイク、スウォーム、モブ
        8.5.1 スパイク
        8.5.2 スウォーミング
        8.5.3 モブ
    8.6 タイムボックスの中で未知を探求する
    8.7 コードレビューとレトロスペクティブのスケジュールを立てる
    8.8 学習を増やし、知識を広げる
    8.9 常にメンター、メンティーであれ
    8.10 実践しよう
        8.10.1 ペアプログラミングの7つの戦略
        8.10.2 レトロスペクティブの7つの戦略
    8.11 本章のふりかえり

9章 プラクティス5 「CLEAN」コードを作る
    9.1 高品質のコードは凝集性が高い
    9.2 高品質のコードは疎結合である
    9.3 高品質のコードはカプセル化されている
    9.4 高品質のコードは断定的である
    9.5 高品質なコードは冗長でない
    9.6 コード品質が私たちを導いてくれる
    9.7 明日のベロシティのために今日品質を上げる
    9.8 実践しよう
        9.8.1 コード品質を上げる7つの戦略
        9.8.2 保守しやすいコードを書く7つの戦略
    9.9 本章のふりかえり

10章 プラクティス6 まずテストを書く
    10.1 テストと呼ばれるもの
        10.1.1 受け入れテスト = 顧客テスト
        10.1.2 ユニットテスト = 開発者によるテスト
        10.1.3 それ以外のテスト = QAテスト
    10.2 QA
        10.2.1 テスト駆動開発はQAの代わりではない
        10.2.2 ユニットテストは万能ではない
    10.3 良いテストを書く
        10.3.1 テストではない
        10.3.2 ふるまいの集合体
    10.4 テスト駆動開発はすばやいフィードバックをもたらす
    10.5 テスト駆動開発はリファクタリングをサポートする
    10.6 テスト可能なコードを書く
    10.7 テスト駆動開発は失敗することがある
    10.8 テスト駆動開発をチームに広める
    10.9 テストに感染する
    10.10 実践しよう
        10.10.1 優れた受け入れテストのための7つの戦略
        10.10.2 優れたユニットテストのための7つの戦略
    10.11 本章のふりかえり

11章 プラクティス7 テストでふるまいを明示する
    11.1 レッド/グリーン/リファクタ
    11.2 テストファーストの例
        11.2.1 テストを書く
        11.2.2 コードをスタブアウトする
        11.2.3 ふるまいの実装
    11.3 制約を導入する
        11.3.1 テストを書いてコードをスタブアウトする
        11.3.2 ふるまいの実装
    11.4 作ったもの
    11.5 テストは仕様だ
    11.6 完全であれ
    11.7 テストを一意にする
    11.8 コードをテストでカバーする
    11.9 バグにはテストがない
    11.10 モックを使ったワークフローテスト
    11.11 セーフティネットを作る
    11.12 実践しよう
        11.12.1 テストを仕様として使うための7つの戦略
        11.12.2 バグを修正する7つの戦略
    11.13 本章のふりかえり

12章 プラクティス8 設計は最後に行う
    12.1 変更しやすさへの障害
    12.2 持続可能な開発
    12.3 コーディング対クリーニング
    12.4 ソフトウェアは書かれる回数より読まれる回数のほうが多い
    12.5 意図によるプログラミング
    12.6 循環複雑度を減らす
    12.7 生成と利用を分離する
    12.8 創発する設計
    12.9 実践しよう
        12.9.1 創発設計をマスターする7つの戦略
        12.9.2 コードをクリーンにする7つの戦略
    12.10 本章のふりかえり

13章 プラクティス9 レガシーコードをリファクタリングする
    13.1 投資か負債か?
    13.2 怠け者になる
    13.3 コードの変更が必要なとき
        13.3.1 既存コードへのテストの追加
        13.3.2 良い習慣を身に付けるために悪いコードをリファクタリングする
        13.3.3 不可避なことを先送りする
    13.4 リファクタリングのテクニック
        13.4.1 ピンニングテスト
        13.4.2 依存性の注入
        13.4.3 ストラングラーパターン
        13.4.4 抽象化によるブランチ
    13.5 変化に対応するためのリファクタリング
    13.6 オープン・クローズドにリファクタリングする
    13.7 リファクタリングで変更しやすさを確保する
    13.8 2回めは適切にやる
    13.9 実践しよう
        13.9.1 リファクタリングから価値を得るための7つの戦略
        13.9.2 いつリファクタリングを行うかについての7つの戦略
    13.10 本章のふりかえり

14章 レガシーコードからの学び
    14.1 もっと良く速く安く
    14.2 不要な出費はしない
    14.3 まっすぐで狭いところを歩く
    14.4 ソフトウェア職のスキルを高める
    14.5 アジャイルの向こうへ
    14.6 理解を体現する
    14.7 成長する勇気

より詳細な目次は以下をご覧ください

www.oreilly.co.jp

本の概要

2部構成となっており、第Ⅰ部ではソフトウェア業界がまだ発展途上である(改善の余地を十分に残している)とした上で、レガシーコードとは何か、なぜ生まれるのかを著者の実体験を含めて述べられ、レガシーコードを生まないためのアイデアとしてアジャイル開発について触れています。一方、第Ⅱ部では、レガシーコードを生まないための実際の取り組みとして9つのプラクティスが紹介されています。
各章の最後には章ごとの"まとめ"が書かれているため、一読してから、ここどうだっけ?という確認もしやすいことが特徴です。
そして、9つのプラクティスにはそれぞれのプラクティスを実践するための戦略が書かれています。これにより、「目的は理解したけど、このあとどうすれば」と道に迷うことなくプラクティスを適用していけます。

全体の感想

はじめに、全体の感想について述べておきます。
まず注意点として、タイトルが『レガシーコードからの脱却』とありますが、9つのプラクティスは基本的にはレガシーコードを生まないことに注力しています。
つまり、リファクタリングの手法が書かれている本ではありません。
しかし、9つのプラクティスが述べていることの本質(何を目的としているか、なぜ有効なのか)を理解することにより、リファクタリング時の道しるべになるはずです。
なお、本書の9つ目のプラクティスではリファクタリングについても詳しく述べられています。
本書の原題は『Beyond Legacy Code』で直訳すれば「レガシーコードを越えて」となります。 この原題には原著者の「より良いソフトウェア業界を作りたい」という願いが込められているように感じます。
9つのプラクティスは実践的で、できることから日頃の開発に取り込んでいこうと思いましたが、(本書の前半で何度も繰り返されていますが、)9つのプラクティスを実施することが目的ではないことを認識し、メンバー内でより良い開発手法を見出していければと思いました。 本書は開発者だけでなく、マネージャー含めソフトウェア業界に関わる全ての人にレガシーコードを生まないように考える機会を与える、そんな一冊です。

以下、気になった章や内容をピックアップして感想を書きます。

1章 何かが間違っている

本書で、「レガシーコードとは修正や拡張、作業が難しいコード」と定義しています。 ソフトウェア開発は未知に溢れ、抽象的で、正しいものがわかりにくい世界で、基本原則や共通の知識体系が確立していないと多くの比喩を使って述べています。
これについてはフレデリック・ブルックス氏の『人月の神話』でもソフトウェア開発の難しさとして述べられており、私の体感とも合っています。
この難しさが絡み合った結果がレガシーコードになってしまうというのも納得がいく内容でした。

4章 9つのプラクティス

この章では、これ以降の章で紹介するプラクティスとどのように向き合っていけば良いかが書かれています。
ソフトウェアの変更は必至であり、変更を想定してソフトウェアを作るべきということは、エンジニアであればなんとなく感じていることだと思います。
ただ、「変更を想定したソフトウェア作りとは何か?どうしたら良いか?」と問われたときに答えを出せるエンジニアは少ないはずです。
第一原理->原則->プラクティスという3つの概念をもとに、9つのプラクティスが何を目指している先が解説された章になっています。

8章 プラクティス4 協力しあう

この章では4つ目のプラクティスである「協力しあう」を説明しています。
ペアプログラミングなどで協力することによって、コードレビューのサイクルを短くできたり、知識の共有を行えたりします。これによってコードの不具合は減り、より良いソフトウェアを作ることができるとしています。
私も大量のソースコードを一度にレビュー依頼をし、結果として大量のコメントが返却されたということがありました。
思い返せば、このときペアプログラミングを行って実装していれば、よくないコードが書かれた時点でアドバイスがもらえ、もう少し楽に作業できたのではないかと思います。
ペアプログラミングで、実際の生産性はどう変わるのか?といったペアプログラミングに対する疑問への回答も記述されており、なかなかチームでペアプログラミングの導入が進められない……といった方の背中を押せる内容です。

13章 プラクティス9 レガシーコードをリファクタリングする

この章では9つ目のプラクティスである「レガシーコードをリファクタリングする」を説明しています。
新規での開発ではコードの量がそれほど多くないため、全量を一気にリファクタリングすることもできるかもしれません。
既存のソースコードに変更を加えるような開発ではそうもいきません。「レガシーコードである」とわかっていても既存コードに修正を行うのは勇気がいるものです。
そんなときに使えるリファクタリングの手法が紹介されています。
また、リファクタリングを行うことで既存のコードベースや良いコードの書き方を学べるという考えが書かれていて、「たしかにそうだ」と納得するとともにリファクタリングへの機運が高まりました。
私が携わっているプロジェクトもリファクタリングしたいと思っていて進められていないところが多いので、紹介されている手法をもとに進めていきたいです。

最後に

本書はソフトウェア開発に携わる全ての人に向けて、業界からレガシーコードをなくすために書かれたものです。
コーディング、テスト、マネジメントなど、どの立場であってもメンテナンスしやすいソフトウェアを作りたい人には非常におすすめできる本です。

P.S.

虎の穴ラボでの開発に少しでも興味を持っていただけた方は、採用説明会やカジュアル面談という場でもっと深くお話しすることもできます。ぜひお気軽に申し込みいただければ幸いです。
カジュアル面談では虎の穴ラボのエンジニアが、開発プロセスの内容であったり、「今期何見ました?」といったオタクトークから業務の話まで何でもお応えします。

カジュアル面談や採用情報はこちらをご確認ください。
yumenosora.co.jp

また、毎週火曜、木曜にはTora-Lab Meetup!と称して虎の穴ラボのエンジニア・採用担当とお話できる機会を設けさせていただくことになりました。
虎の穴ラボに興味がある、エンジニアや採用担当に質問したいことがある、などどなたでもご参加下さい。
news.toranoana.jp

6月12日に「【オンライン開催】とらのあな採用説明会 6/12 オタク企業で働くエンジニアの魅力について」を開催します。
とらのあなラボのエンジニアの働き方など説明します。ぜひ奮ってご参加ください。 yumenosora.connpass.com

さらに、弊社では新型コロナウイルス感染症終息後もフルリモートを継続導入することになりました!
prtimes.jp