📖

【リーダブルコード】変数と可読性についての気づき

に公開

※ 下記のリンクにある本の韓国語版を読んで簡単に整理しました。
https://www.amazon.co.jp/Art-Readable-Code-Practical-Techniques-ebook/dp/B0064CZ1XE

中間結果を保存するだけの変数は本当に必要か?

public static void removeOne(List<String> list, String valueToRemove) {
    Integer indexToRemove = null;
    for (int i = 0; i < list.size(); i++) {
        if (list.get(i).equals(valueToRemove)) {
            indexToRemove = i;
            break;
        }
    }

    if (indexToRemove != null) {
        list.remove((int) indexToRemove);
    }
}

このコードでは、indexToRemoveという変数が中間結果の保持に使われています。これは改善の余地があります。

改善後のコードはこちら:

public static void removeOne(List<String> list, String valueToRemove) {
    for (int i = 0; i < list.size(); i++) {
        if (list.get(i).equals(valueToRemove)) {
            list.remove(i);
            return;
        }
    }
}

たったこれだけの変化で、コードの見通しがぐっと良くなります。最初の例では動作は理解できても、改善案がすぐには思い浮かばなかったのが正直なところ。しかし、答えを見た瞬間「なるほど!」と納得。まるでなぞなぞの答えを聞いたときのような感覚でした。


グローバル変数を避けてクロージャでカプセル化する(Java的に言えばクラス内部で閉じ込める)

public class FormSubmitter {
    private boolean submitted = false;

    public void submitForm(String formName) {
        if (submitted) {
            return;
        }

        // 送信処理
        submitted = true;
    }
}

JavaScriptではクロージャを使いますが、Javaではこのようにフィールドで状態を保持しつつメソッドで処理を隠蔽することで同様のカプセル化を実現できます。

グローバル変数のsubmittedを使う代わりに、クラス内部のフィールドとして隠すことで、外部からの誤用を防ぐことができます。


一時的な変数の削除でコードを簡潔にする

Integer exampleValue = null;
if (request != null) {
    for (Integer value : request.getValues()) {
        if (value > 0) {
            exampleValue = value;
            break;
        }
    }
}

if (exampleValue != null) {
    for (Logger logger : debug.getLoggers()) {
        logger.log("Example: " + exampleValue);
    }
}

このようなコードも、一時的な変数を排除して関数に処理を渡すことでよりシンプルになります:

public static void logExample(int value) {
    for (Logger logger : debug.getLoggers()) {
        logger.log("Example: " + value);
    }
}

if (request != null) {
    for (Integer value : request.getValues()) {
        if (value > 0) {
            logExample(value);
            break;
        }
    }
}

変数が多いと、その意味や値の整合性、影響範囲を意識しなければならず、バグの温床になります。必要なときに即座に処理するスタイルは、意外と見落としがちですが強力な手法です。


変数には一度だけ値を代入するよう心がける

// 悪い例
int total = 0;
total = calculateSubtotal();
total += calculateTax();
total -= applyDiscount();

上記のように何度も代入を繰り返すよりも:

final int subtotal = calculateSubtotal();
final int tax = calculateTax();
final int discount = applyDiscount();
final int total = subtotal + tax - discount;

このように定数(final)を多用することでコードの追跡が楽になり、変更ミスのリスクも下がります


第9章についての所感

第9章では次のようなことが学べました:

  • 変数は少ない方がよい。それにより、バグの混入リスクが減る。
  • 中間変数や一時変数は、可能であればなくすことを検討する。
  • 再代入よりも一度きりの代入を優先し、状態の追跡を容易にする。
  • 変数のスコープを狭く保ち、意図しない再利用や変更を防ぐ。

この章を通じて、**「変数を減らす=コードを安全に・シンプルに保つ鍵」**であることを再認識しました。これからは、コードを書くたびに「この変数は本当に必要か?」と自問しながら書いていきたいと思います。


必要であれば、ZennQiita形式にも整えてお渡しできます。希望があればお知らせください。

Discussion