📌

[関数リファクタリング] 定義指向プログラミングをしよう💪 〜 プライベート関数への抽出でネストを解消編 〜

に公開

はじめに

前回はローカル変数を用いてネストを解消する方法について記事にしてみました。

https://qiita.com/fujihara_hideyuki/items/2c0c3466f668f544aae1

今回はローカル変数による解消では難しいパターンに対してプライベート関数で対応する方法についてまとめてみようと思います。

具体例

例えば以下のようなコードがあったとします。

// バッドコード

if(messageModelList.hasValidModel(messageId)) {
    if(messageListPresenter.isMessageShown(messageId)) {
        if(requestQueue.contains(messageId)) {
            showStatusText("Sending");
        }
    }
}

3重のif文になっており、可読性が良くないですね😅

まずはローカル変数でやってみる

では、これをローカル変数で解消してみましょう。

// このコードは上記のコードと完全に一致しない

final isMessageValid = messageModelList.hasValidModel(messageId);
final isMessageViewShown = messageListPresenter.isMessageShown(messageId);
final isMessageSendingOngoing = requestQueue.contains(messageId);
if (isMessageValid && isMessageViewShown && isMessageSendingOngoing) {
  showStatusText("Sending");
}

見た目上は確かにネストを解消できていますね。

ただ、このコードは上のコードと完全に一致していません。

というのもそれぞれの条件を変数の初期化で対応させているので、条件がfalseでも後続の処理が初期化の際に走ってしまっています。

そこまで意識するケースはないかもしれませんが、

仮に、

// 計算量の多いコードかも知れない...
final isMessageSendingOngoing = requestQueue.contains(messageId);

このコードの計算量が多かった場合、

毎度実行してしまうとパフォーマンス上で問題があることも想像されます。。。

プライベート関数でやってみる

では次にプライベート関数で解消を試みてみましょう💪

// グッドコード ~ ネストをプライベート関数で解消 ~

bool _isMessageValid(MessageId messageId) =>
    messageModelList.hasValidModel(messageId);

bool _isViewShownFor(MessageId messageId) =>
    messageListPresenter.isMessageShown(messageId);

bool _isUnderSending(MessageId messageId) =>
    requestQueue.contains(messageId);

if (_isMessageValid(messageId) &&
      _isViewShownFor(messageId) &&
      _isUnderSending(messageId)) {
    showStatusText("Sending");
}

このコードであればfalseの場合は後続の条件は処理されないので、

先述のパフォーマンス上の懸念点も解消され、

かつネストも解消されていて良いですね👍



このように、ローカル変数ではうまく対応が出来ない場合は

プライベート関数として抽出することで解消されることもあるので、

代替案として使えそうですね。

参照

https://gihyo.jp/book/2022/978-4-297-13036-7

Discussion