nikkie-ftnextの日記

イベントレポートや読書メモを発信

読書ログ | 『Clean Craftsmanship』 第5章、リファクタリングはたしかに"ルービックキューブ"

はじめに

花丸ちゃん、お誕生日おめでとうございます!1 nikkieです。

ミノ駆動本_読書py 第14章『リファクタリング』の事後となりましたが、予習していた事項のアウトプットです。
Uncle Bobの『Clean Craftsmanship』のリファクタリングの章(第5章)を読みました。

目次

第5章 リファクタリング

https://www.tumblr.com/asciidwango/693992928727760896/clean-craftsmanship

公開されている目次より

第5章 リファクタリング
 リファクタリングとは?
 基本的なツールキット
 規律
 結論

他の章と比べると5章は簡潔です。

本章を意図的に簡潔にしたのは、マーチン・ファウラーの『リファクタリング』に追加したいアイデアが少なかったからだ。繰り返しになるが、リファクタリングを深く理解するには『リファクタリング』を読んでほしい。(Kindle版 pp.258-259)

Martin Fowlerの『リファクタリング』を読もう!

Uncle Bobのお墨付きが出ました!
私もちょっとずつ読み進めていますが、『リファクタリング』、コードの構造を改善する技術が例を通して学べて、めちゃめちゃいい本だと思います。
最近の私を助けている一冊です。

リファクタリング』で関連するアウトプットがこちら:

リファクタリングは、ルービックキューブ

第5章で一番印象に残ったのがこちらのたとえ。
これは本当に言い得て妙だと思うんですよ!

そして、ルービックキューブは手を動かさないと習熟しないように、リファクタリングも練習が必要です。
言い換えると、今はうまくできなくても練習していけば身につけられるということですね。
Practice, practice, practice!!

IDEの使い方を押さえよう

第5章は「名前の変更」や「メソッドの抽出」、「変数の抽出」を紹介したあとで以下のように続きます。

これまでに小さなリファクタリングがいかに強力であるかを説明した。(略) これらのリファクタリングを学び、IDEの使い方とコツを覚えることが重要である。(Kindle版 p.254)

私もおんなじこと考えるようになったんですよね3

VS Code Conference Japan 2022 - 2023 - connpass

nikkie / 楽々入門!VS Codeで『リファクタリング
このトークでは、書籍『リファクタリング https://www.ohmsha.co.jp/book/9784274224546/ 』で紹介されたテクニックをVS Codeの操作と結び付けて理解するのを目的とします。

引用した箇所を読んで、「私、クラフトマンシップの道進んでるじゃん!」と嬉しく思いました😃

IDEリファクタリング操作=ルービックキューブの操作だと思います。
1つ1つでいいので、操作の使い所とIDEの操作を身につけるのがオススメです。
これができるとルービックキューブの操作を1つ覚えた状態になります。

上で挙げた3つの小さなリファクタリングが使えるようになるだけで、開発で取れる選択肢が広がると実感しています。
3つを組合せて簡単にリファクタリングできると経験してからは、私はコードを書くときに悩むことが減りました。
一発で正解は書けないと割り切り、悩むよりも手を動かし、その後はテストコードも用意してよりよい構造にリファクタしていくようになりました。

Uncle Bobオリジナル? 「フィールドの抽出」

『Clean Craftsmanship』で初めて知ったのが、「フィールドの抽出」というテクニック。
先日のエントリはこれを写経するための準備でした。

サンプルコードは、COVIDの新規感染者数を郡と州で合計するコードです。
NewCasesReporterは長大なmake_reportメソッドを持っています。

class NewCasesReporter:
    def make_report(self, county_csv: str) -> str:
        total_cases = 0  # 全州の新規感染者数の合計
        state_counts = {}  # 州毎の新規感染者数
        counties = []  # 郡(County)を入れていく配列(Countyは郡の新規感染者数も持つ)

        lines = county_csv.split("\n")
        for line in lines:
            # 長大なループ(リファクタリング対象)
            # 上で定義したtotal_casesなどを更新している
            ...

        # reportを作成する処理

テストがあるのでリファクタリングは好きなだけできます!🙌
まずmake_reportのループをIDEの機能でメソッドに抽出しようとするのですが、以下のようなシグネチャを提案されます。

    def new_method(self, total_cases, state_counts, counties, lines):

これはキャンセルします。

引数を4つも渡したくない。抽出した関数に渡していいのは、配列のlinesだけだ。(Kindle版 p.247)

make_reportメソッドのローカル変数total_casesなどが抽出先の関数のシグネチャに入ってくるのが、メソッドの抽出をキャンセルした理由(の1つ)です4

これをどう解消するか?
「フィールドの抽出」を使うのです!

やることは、ローカル変数をインスタンスのフィールドに持たせること(だけ)です。

class NewCasesReporter:
    def __init__(self) -> None:
        self.total_cases = 0
        self.state_counts = {}
        self.counties = []

    def make_report(self, county_csv: str) -> str:
        self.total_cases = 0
        self.state_counts.clear()
        self.counties.clear()

        lines = county_csv.split("\n")
        for line in lines:
            # 長大なループ(リファクタリング対象)
            # self.total_casesなどを更新するように変わっている
            ...

        # reportを作成する処理

これにより、ループ部分はlinesだけを引数とする関数に抽出できます。

    def new_method(self, lines):

写経したコードはこちらです:
https://github.com/ftnext/road-to-craft-skills-py/commits/c3874113fff806d956e559ad54c359f93bed0ba2/covid/report.py

ローカル変数をインスタンス変数に置き換えるというのは、ほとんど見たことがなかったので学びになりました。
Uncle Bobは「それほど使うことはない」と述べていますが、私は読む前はこの発想すら持ち合わせていなかったので、「自分が作ったクラスで、メソッドのローカル変数をフィールドにして、クラスをよい構造に育てていけるかも」と可能性を感じています。

この後は処理のまとまりごとに、インスタンス変数を更新するメソッドへと抽出が進んでいきます。
「フィールドの抽出」をきっかけに、このコードの構造は劇的に改善されます!(さすがです、おじさま(Uncle Bob)。略してさすおじ!)

Clean Code』ではメソッドの引数は0個がよい(インスタンス変数を使う)という主張だったので、それと重なるな〜と思いました5
オブジェクトのフィールドが可変になっているので、このやり方について好みは分かれるかもしれないですね。

終わりに

『Clean Craftsmanship』第5章を読んで、リファクタリングの理解を深めました。

私、なかなかソフトウェアが書けないんですよ。
「プログラム書いてるからソフトウェアじゃん」と思われるかもしれないですが、私の書いたプログラムは全然ソフト(変更容易)じゃないんです!(つまり、ハードウェア!6
このあたりは日々精進という感じですが、打ち手の1つとしてリファクタリングを学び始めたところ、小さい範囲を変更容易な構造にリファクタできたという成功体験を少しずつできており、ちょっとは前進しているのかなという感覚です(まだ全然道半ばですけどね)


  1. 市役所もお祝い、未来ずら〜
  2. え、待って!リファクタリングって1つ1つのステップそんなに小さく実施するの!? (『The Art of Agile Development』読書録) - nikkie-ftnextの日記
  3. ミノ駆動本 14.4にも同様の話題があります
  4. 他の理由は書籍を是非どうぞ
  5. 第3章に「関数の引数は理想的には0」とあります
  6. 今期めちゃめちゃお気に入りの『お隣の天使様にいつの間にか駄目人間にされていた件』、石見舞菜香さん演じる天使様のセリフに「家事ができないのに一人暮らしとか、なめているのですか?」(1話)というのがあるのですが、私はこれを脳内で「変更しやすいコードが書けないのにソフトウェア開発とか、なめているのですか?」に置き換えてぐさっとなりました