楽々入門!VS Codeで『リファクタリング』

Event:

VS Code Conference Japan 2022 - 2023

Presented:

2023/01/21 nikkie 14:20-

お前、誰よ(※自己紹介)

  • にっきーって言います。VS Code使ってます

  • @ftnext @ftnextはてなブログ

  • Python 大好き。コードは 構造 にもこだわりたい

  • 株式会社ユーザベースでデータサイエンティスト(自然言語処理、XP)

楽々入門!VS Codeで『リファクタリング』

このトークでは、書籍『リファクタリング』で紹介されたテクニックをVS Codeの操作と結び付けて理解するのを目的とします。

イベントサイト より

📘『リファクタリング

リファクタリングは、ソフトウェアの外部的な振る舞いを保ったままで、内部の構造を改善する作業を指します。

書籍サイト(リンク先)の「内容紹介」より

📘『リファクタリング』

  • Martin Fowler著、「リファクタリングのガイドブック」(「内容紹介」より)

  • IMO:リファクタリングテクニックをたくさん載せた カタログ

  • Web版(英語) https://refactoring.com/catalog/

このトークでは

  • 📘『リファクタリング』のテクニックのいくつかを

  • VS Codeの操作と結びつけて 理解する

おことわり(nikkieの文脈共有兼ねて)

  • VS CodeのUIは 英語 で紹介

  • 本発表のコード例は Python (後述)

  • 「リファクタリング」のとらえ方(後述)

Pythonのコード例、ぜひ 読み替え てください

  • Pythonの詳細には立ち入りません

  • 📘『リファクタリング』ではJavaScript

  • リファクタリングは異なる言語でもほぼ同じような形になります。」(📘の「はじめに」「JavaScriptによる例」)

「私の知っている リファクタリング と異なる!」かも

  • 異なる=「小さい!」かもしれません

  • このトークの「リファクタリング」は、開発中に絶えずやる、コードの構造の小さい改善 を指しています

  • 数日〜数週かける規模のリファクタリングは想定していません(テクニックは適用できるかも)

開発中に絶えずやる、コードの構造の小さい改善 補足 🏃‍♂️== skip

  • XPのプラクティスの1つ テスト駆動開発

  • 「動作するきれいなコード」を目指す(Red-Green-Refactoring)

  • まず動作させ(Green)、次にきれいにする(リファクタリング)。この 小さいサイクルを何回も 繰り返す

楽々入門!VS Codeで『リファクタリング』

  1. トークの認識合わせ✅

  2. 主張:リファクタリングテクニックをエディタと結び付けよう

  3. カタログ:VS Codeでリファクタリング(別目次)

Part 2. リファクタリングテクニックをエディタと結び付けよう

  1. トークの認識合わせ

  2. 主張:リファクタリングテクニックをエディタと結び付けよう

  3. カタログ:VS Codeでリファクタリング(別目次)

リファクタリング、名詞と動詞

  • 個々のテクニックは 名詞のリファクタリング

  • ※これをエディタと結び付けようと共有していきます

リファクタリング(名詞)

外部から見たときの振る舞いを保ちつつ、理解や修正が簡単になるように、ソフトウェアの内部構造を変化させること

📘『リファクタリング』第2章の中の「リファクタリングの定義」

リファクタリング(名詞) 🏃‍♂️

  • 変えるのは構造だけ

  • 振る舞いは変えない

  • 開発者がコードを理解しやすく・変更しやすくするために構造を変える

動詞のリファクタリング

  • 名詞のリファクタリング 複数を適用 して構造を変えること

  • 1つ1つのテクニックは小さい。組合せて適用する

動詞のリファクタリング 🏃‍♂️

  • 名詞のリファクタリングの手順は、📘『リファクタリング』6章以降で解説される

  • 6章が基本のリファクタリングテクニック。基本を 組合せ たテクニックも存在する

一発で正解することが難しいからこそ

  • 俺は弱い! だから 正解に近づけていく (リファクタリングもその一環)

  • 参考: Make It Work Make It Right Make It Fast

    • まず動かしてから正しくする順 (その後に速くするが来る)

主張:リファクタリングテクニックをエディタと結び付けよう

  • リファクタリングを「知っている」の先「使える」状態になるには、

  • エディタの操作 として身体で覚えよう

テクニックのいくつかはエディタの機能になっている

  • VS Codeを操作 してリファクタリングテクニックを適用できる

  • サポートしているテクニックの範囲はエディタによって異なる

    • IntelliJ IDEAはもっと広くサポート

IMO:リファクタリングを使えるようになるために知ること

  • どんなとき に使うのか」

  • 「エディタでは どんな操作 になるのか」

使える=体で覚える="常中"

「どんなときに使うのか」:

📘『リファクタリング』から あるべき を紹介

「VS Codeではどんな操作になるのか」:

結び付け ます

Part 3. カタログ:VS Codeでリファクタリング

  1. トークの認識合わせ

  2. 主張:リファクタリングテクニックをエディタと結び付けよう

  3. カタログ:VS Codeでリファクタリング(別目次)

VS Codeの操作と結び付けて紹介するテクニック

  • 変数名の変更

  • 関数名の変更

  • 変数の抽出

  • 関数の抽出

  • 特性の移動に関する数テクニック

紹介フォーマット

  • どんなとき に使うのか

  • VS Codeでは どんな操作 になるのか

Part 3. カタログ:VS Codeでリファクタリング

  • 変数名の変更

  • 関数名の変更

  • 変数の抽出

  • 関数の抽出

  • 特性の移動に関する数テクニック

コンピュータサイエンスで最も難しい2つ

cache invalidation and naming things (Phil Karlton)

ref: TwoHardThings

命名(naming things)は難しい🤯

  • 名前重要 (by Matz)だけれど、激ムズ

  • IMO:一発でいい命名ができないからこそ、 いい名前に気付いたらコードを更新 して理解しやすくしたい

「{変数,関数}名の変更」の使い所

  • 適切な名前に気付いたとき

  • コードを明快にしたい(理解しやすい・変更しやすい)

  • 不可思議な名前」 (📘『リファクタリング』第3章)

テクニック:変数名の変更

- a = height * width
+ area = height * width

テクニック:関数名の変更

VS Codeを操作して名前を変更

  • Rename Symbol

  • F2 キー(これだけ!)

Rename Symbol

Rename Symbolによる「変数名の変更」のデモ

# 面積の計算。a を area にrenameする
a = height * width

スコープを考慮のデモ & 「関数名の変更」のデモ

# 面積を計算する関数。calc を calc_area にrenameする
def calc(height, weight):
    # スコープを考慮してrenameされる例
    a = height * weight
    return a

変数名の変更・関数名の変更

どんなときに使うのか:

適切な名前 に気付いたとき

VS Codeではどんな操作になるのか:

F2 (Rename Symbol)

「{変数,関数}名の変更」で省略したこと 🏃‍♂️

  • クラス名・属性名・メソッド名の変更もRename Symbolできます

  • モジュール名(spam.py)の変更はPython拡張がサポート

Part 3. カタログ:VS Codeでリファクタリング

  • 変数名の変更

  • 関数名の変更

  • 変数の抽出

  • 関数の抽出

  • 特性の移動に関する数テクニック

すなわち、 式に名前を付ける

「変数の抽出」の使い所

  • 式を説明するコメント を見つけた・書きたいとき

  • コメントを書かなくとも内容がわかるようなコードを目指す」(📘『リファクタリング』第3章)

VS Codeを操作して変数を抽出

  • 式を選択

  • Extract variable

Extract variable

Extract variableによる「変数の抽出」のデモ💡

# base_price = order.quantity * order.item_price のように抽出する例
def price(order):
    # price = base price - quantity discount + shipping
    return (
        order.quantity * order.item_price
        - max(0, order.quantity - 500) * order.item_price * 0.05
        + min(order.quantity * order.item_price * 0.1, 100)
    )

「変数の抽出」を繰り返すと、この例のコメントは不要になります

エディタでExtract variableするメリット

  • 📘『リファクタリング』はエディタのサポートを受けない手順

  • 式をコピーして変数を導入 ➡ 式を変数で置き換え

  • IMO:エディタの機能を使うことで ができる(常中しやすい)

変数の抽出

どんなときに使うのか:

式を説明するコメント がある・必要があると思われるとき

VS Codeではどんな操作になるのか:

コードを選択して Extract variable

Part 3. カタログ:VS Codeでリファクタリング

  • 変数名の変更

  • 関数名の変更

  • 変数の抽出

  • 関数の抽出

  • 特性の移動に関する数テクニック

関数の抽出

「関数の抽出」の使い所 1

  • 処理の一部が コメントで説明されている とき

  • 長い関数」 (📘『リファクタリング』第3章)

  • コードの 自己文書化 (意図と実装を分離して、理解しやすく)

VS Codeを操作して関数を抽出

  • 処理を選択

  • Extract method

Extract method

Extract methodによる「関数の抽出」のデモ💡

# print detailsというコメントで説明された処理を関数に抽出する例
def print_owing(invoice):
    print_banner()
    outstanding = calculate_outstanding(invoice)

    # print details (<- 「関数を抽出」すると、このコメントは不要になる)
    print(f"name: {invoice.customer}")
    print(f"amount: {outstanding}")

Extract methodは一足飛び⚠️

  • 📘『リファクタリング』では まず は関数内関数(入れ子)として抽出する

    • 渡す必要がある引数を1つずつ調整していって、最後に外側のスコープに移す

  • IMO:エディタのサポートで楽をしたいが、一足飛びだと嬉しくない場面もあり、この手順が必要になることも

📘 まずは関数内関数に抽出 🏃‍♂️

def print_owing(invoice):
    print_banner()
    outstanding = calculate_outstanding(invoice)

    print_details()

    # まずは抽出だけ実施し、その後引数を調整します(関数宣言の変更)。最後に関数スコープの外へ
    def print_details():
        print(f"name: {invoice.customer}")
        print(f"amount: {outstanding}")

関数の抽出

どんなときに使うのか:

長い関数で 一部を説明するコメント があるとき

VS Codeではどんな操作になるのか:

コードを選択して Extract method

「関数の抽出」の使い所 2 🏃‍♂️

  • 何度も登場する同じ式(重複は変更を難しくする🥺)

  • 重複したコード」(📘『リファクタリング』第3章)

  • 重複した式を関数に抽出し、それで置き換えることで重複コードをなくす

Part 3. カタログ:VS Codeでリファクタリング

  • 変数名の変更

  • 関数名の変更

  • 変数の抽出

  • 関数の抽出

  • 特性の移動 に関する数テクニック

特性の移動

  • 📘『リファクタリング』第8章

  • 文・フィールド・関数を 移動 するリファクタリングテクニックを紹介

特性の移動のテクニック(一部) 🏃‍♂️

なぜ移動する?

  • 関連する要素をまとめる

  • 一発で正解の関連を見つけることもまた難しい🥺

  • 関連についての理解が深まったら、移動してまとめ方を更新 する

VS Codeで移動といったら ⌥↑⌥↓

Move line up and downのデモ

Move line up and down

  • 行を動かしただけで「特性の移動」が完了することは少ない

    • 移動先の文脈に位置づける(引数の追加・編集が必要)

  • IMO:リファクタリングの 端緒 として、簡単にできる操作という点がオススメ

特性の移動(文・フィールド・関数の移動テクニック)

どんなときに使うのか:

深まった理解に基づき、関連する要素の まとめ方を変える とき

VS Codeではどんな操作になるのか:

⌥↑⌥↓ が最初の操作

Part 3. カタログ:VS Codeでリファクタリング まとめ🌯

  • 変数名の変更➡️ F2 (Rename Symbol)

  • 関数名の変更➡️(同上)

  • 変数の抽出➡️ Extract variable

  • 関数の抽出➡️ Extract method

  • 特性の移動に関する数テクニック➡️ ⌥↑ ⌥↓ で始めよう

落穂ひろい🌾:リファクタリングとテストコード

テストコード で、ますます捗るリファクタリング

  • 振る舞いを変えずに構造を変えるのがリファクタリング

  • テストコードがあると、 振る舞いを変えてしまったことに気付ける

テストは 不安を退屈に変える 賢者の石

  • テスト駆動開発』第25章の言葉

  • 「リファクタリングで振る舞いを変えているんじゃないか」という不安がなくなった

  • 都度手動テストでも確認できるが、何度も繰り返すため、 テストコードが一番効果的 と考えます

今回紹介したVS Codeのリファクタリング操作について(IMO)

  • VS Codeは信頼している。デモのような 小さい範囲 はガンガンリファクタリング

  • ですが、テストコードがないとき、広い範囲に関わるならば私は見送ります

今回紹介したリファクタリングテクニックはごく一部 🏃‍♂️

  • 📘『リファクタリング』にはまだまだテクニックが載っている

  • VS Codeがサポートしないテクニックは、テストコードを書いて、リファクタリング手順を練習して常中させていきましょう!

まとめ🌯:楽々入門!VS Codeで『リファクタリング』

  • Martin Fowler著『リファクタリング』のテクニックをVS Codeの操作と結び付けて紹介

  • 使い所(理論)とエディタの操作(身体)で覚えている 常中 状態の提案

紹介したテクニックとVS Codeの操作

  • 変数名・関数名の変更➡️ F2 (Rename Symbol)

  • 変数の抽出➡️ Extract variable

  • 関数の抽出➡️ Extract method

  • 特性の移動に関する数テクニック➡️ ⌥↑ ⌥↓ で始めよう

ご清聴ありがとうございました!

Enjoy development!

References

VS Codeドキュメント

関連アウトプット

Appendix

インライン化

  • 抽出の 逆操作 (リファクタリングは可逆な操作)

  • VS CodeやPython拡張ではサポートされないらしい(Marketplaceにあるかも)

も〜っとリファクタリング

  • VS Codeでできるリファクタリングには限界がある

  • もっと多くのリファクタリングについてサポートを受けて開発したい場合

  • 👉IntelliJ IDEAやPyCharm

鬼滅の刃フィーチャー

  • 「常中」

  • リファクタリングテクニックは多数ある。まずは「ひとつのことを極め抜け」

EOF