読者です 読者をやめる 読者になる 読者になる

loggingにはgotoを使いたいだろうか?

田辺さんからご指摘があったので。

元のコード。

public function getSystemValue($key) {
	$this->getLogger()->log(LOG_DEBUG, 'start');
	
	// すでに読み込み済みデータの場合はそのデータを使用
	$value = $this->findCache($key);
	if (!is_null($value)) {
		goto END;
	}

	// DBから取得
	$value = $this->getDao()->read($key);
	if (!is_null($value)) {
		goto END;
	}

	// 設定ファイルから取得
	$value = $this->getConfig()->get($key);

    END:
	$this->getLogger()->log(LOG_DEBUG, "end(value=$value)");
	return $value;
}

田辺さんの書かれたreturnコード

public function getSystemValue($key) {

  $this->getLogger()->log(LOG_DEBUG, 'start');

  // すでに読み込み済みデータの場合はそのデータを使用
  $value = $this->findCache($key);
  if (!is_null($value)) {
    $this->getLogger()->log(LOG_DEBUG, "end(value=$value)"); ←これ
    return $value;
  }

  // DBから取得
  $value = $this->getDao()->read($key);
  if (!is_null($value)) {
    $this->getLogger()->log(LOG_DEBUG, "end(value=$value)"); ←これ
    return $value;
  }

  // 設定ファイルから取得
  $value = $this->getConfig()->get($key);

  $this->getLogger()->log(LOG_DEBUG, "end(value=$value)"); ←これを何度も書くのが嫌。
  return $value;
}

この程度ならこんな風に書いてしまうですかねえ。なぜかC++で。

int Hoge::getSystemValue(const char* key)
{
      debug_printf("Hoge::getSystemValue ");
      int value = findCache(key);
      if (value == INVALID_VALUE) {
          // キャッシュになかった
          value = getDao()->read(key);
          if (value == INVALID_VALUE) {
              // DBにもなかった
              value = getConfig()->get(key); 
          }
      }
      debug_printf("key:%s=%d\n", key, value);
      return value;
}

このケースならネストがたいしたことはないわけでgotoが使えるC++でもgotoを使いたいと思わないと思います。
さらにネストが深くなるようなら、関数を分けてそこでロギングすればいいと思います。
getSystemValueCache
getSystemValueDB
getSystemValueConfig
といった感じで。すると、どこからとったかも解るので便利でしょう。
ここでロギングの際に「どこから」とることができたのかをロギングするとなると
面倒ですしね。

int Hoge::getSystemValue(const char* key)
{
      int value = getSystemValueCache(key); // ログはこのなかにある
      if (value != INVALID_VALUE) {
          return value;
      }
      value = getSystemValueDB(key); // ログはこの中にある
      if (value != INVALID_VALUE) {
          return value;
      }
      return getSystemValueConfig(key); // ログはこの中にある
}

一応ですが、
gotoを使わない場合と同じで
異なる場所にログを書かなければならない(各メソッド毎にログは必要なら書かなくてはいけない)ですが、
手動ロギングとはそういうもの、でもあると思います。