ブログトップ 記事一覧 ログイン 無料ブログ開設

Strategic Choice

2009-12-11

[][]Guard Clause(ガード条件)

師曰く

局地的な例外フローを早期復帰で表現しなさい。

どういうこと?

プログラムにはメインフローが1つありますが、例外的な状況下においては、そのメインフローから逸脱せざるをえません。ガード条件は、「シンプルで局所的な例外状況」を表現するために、例外的な状況が発生した場合「早期復帰」(return)して、メインフローに影響を与えないようにします。

どうして?

例えば以下のような2つの実装があります。

void initialize() {
  if (isIntialized()){
    // main flow ...
  }else{
    // exception flow ...
  }
}
void initialize() {
  if(isIntialized()){
    // exception flow ...
    return;
  }
  // main flow ...
}

最初のバージョンを読むとすると、then節を読みつつ、else節がどこにあるかを注意深く探すことになります。頭の中の条件をスタックに積んでいる状態です。そしてこれが、then節の大事な部分を読むときに注意を逸らすことになります。これに対して2つ目のバージョンは、ガード条件を用いることによって、最初の2行で「受信側は初期化されていない」という事実に簡単に気づかせてくれます。

前者の「if-then-else」は(then節とelse節で)同じくらい重要な制御フローを表現します。後者のガード条件は、制御フローの1つが他の制御フローよりも重要となる状況を表現するのに適しています。

どうすれば?

プログラミングにおいて、昔ながらの戒律に「各ルーチンは単一の入口と単一の出口を持たねばならぬ」というものがありました。これはガード条件と相反する規則ですが、今や「都市伝説」といえる考え方です。

もともとこれは、同じルーチン内のいろんな場所から出たり入ったりすることで起こりえる混乱を防ぐためでした。グローバルなデータが多くあり、どの文が実行されるのかすら理解しにくかった、FORTRANやアセンブリ言語の時代には、それはちゃんと意味がありました。しかし、Javaでは小さなメソッドと大部分のローカルなデータから構成されるので、このような規則は気にせず、プログラミングをシンプルにするためにガード条件は躊躇なく使用するべきです。

どんなとき?

以下のように複数の条件分岐がある場合に、ガード条件は特に役立ちます。

void compute(){
  Server server = getServer();
  if(server == null){
    Client client = server.getClient();
    if(client == null){
      Request current = client.getRequest();
      if(current != null){
        processRequest(current);
      }
    }
  }
}

ネストした条件分岐は不具合の原因となりやすいです。ガード条件を用いて、同じコードを書き直すと、制御構造を複雑にすることなく、リクエスト処理の事前条件を記述することができます。

void compute(){
  Server server = getServer();
  if(server==null){
    return ;
  }
  Client client = server.getClient();
  if(client==null){
    return ;
  }
  Request current = client.getRequest();
  if(current==null){
    return ;
  }
  processRequest(current);
}

また、以下では、ガード条件の変形として、ループ内でcontinue文を使っています。伝えているのは「この要素は処理せず、次の要素に進んでください」ということです。

while( line =reader.readLine() ){
  // コメントや空行は「例外的」状況  
  if( line.startsWidth("#") || line.isEmpty() ){ 
    continue;
  }
  // main flow ....
}

ここでも、コードの意図は、「通常の処理」と「例外的な処理」との間の(まさに「局所的な」)違いに目を向けさせることです。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証