分岐とはプログラム言語が、開発者が実現したい「処理」内の条件による判定処理を表現するために用意された最も基本的な構文の1つです。
分岐に用意された構文は、if文(if,elseif,else)とswitch文になります。
switch文は、次の頁分岐(switch)にて説明します。
if
(
判定式 ) {
判定式がtrueの場合に、実行するステートメント;
} else {
判定式がfalseの場合に、実行するステートメント;
}
上記の例は、判定式に該当する場合又はそれ以外の場合両方に実行するステートメントが必要な場合です。
判定式に該当する場合のみ実行するステートメントが必要な場合には、以下の構文を利用します。
if
(
判定式 ) {
判定式がtrueの場合に、実行するステートメント;
}
複数の判定式を用いて、2つ以上の分岐処理を表現する場合には、以下の構文を利用します。
if
(
判定式A ) {
判定式Aがtrueの場合に、実行するステートメント;
} else if (
判定式B ) {
判定式Aはfalseの場合、かつ判定式Bがtrueの場合に、実行するステートメント;
} else {
判定式A及び判定式Bがtrueに該当しない場合、実行するステートメント;
}
大規模なシステムではこのif文の記述形式がとても重要になります。
if文は、if ( 判定式 ) { 処理A; } else { 処理B; }の形式で全て表現可能です。
私の15年程度の経験上ですが、else if文が記載されたソースコードは処理内容をみなくてもバグの温床と捉えています。
現状は、正しい処理要件を表現できていても、将来処理要件が変更された場合には、トラップとなる可能性が非常に高いです。
そのため、特定の理由がない限りif ( 判定式 ) { 処理A; } else { 処理B; }で分岐を表現する習慣をつけた方が望ましいです。
好ましくない例
boolean isAdd = true;
//bad case1 { } を省略して1行で表記。
if( isAdd ) result = x + y;
//bad case2 elseifを利用
String checkStr = "こんにちは";
Greeting greetObj = new Greeting();
if ( "おはよう".equals( checkStr ) ){
greetObj.goodMorning();
} else if ("こんちには".equals( checkStr ) )
greetObj.hello();
} else if ("こんばんは".equals( checkStr ) || "今晩は".equals( checkStr ) ){
greetObj.goodEvening();
} else {
greetObj.howAreYou();
}
上記例のような記述形式がでてきたら、開発資産の保守性が低下する危険性が潜んでおり危ないと判断できます。
上記例をelse if を利用しないルールベースで修正すると次のようになります。
修正例
boolean isAdd = true;
//bad case1 { } を省略して1行で表記。
if( isAdd ) {
result = x + y;
}
//bad case2 elseifを利用
//主文のみで構成する。
String checkStr = "こんにちは";
Greeting greetObj = new Greeting();
if( isGoodMorning( checkStr ) ) {
greetObj.goodMorning();
} else {
greeting( greetObj , checkStr );
}
/**
* メッセージが"こんにちは"以外の処理判定と処理内容
* @param greetObj 挨拶オブジェクト
* @param str 判定する文字列
*/
private void greeting( Greeting greetObj , String str) {
if( isHello( str ) {
greetObj.hello();
} else {
if( isGoodEvenning() ){
greetObj.goodEvening();
} else {
greetObj.howAreYou();
}
}
}
/**
* 文字列がこんにちはであるか判定する。
* @param str 判定する文字列
* @return true:こんにちはである。 false:こんにちはでない。
*/
private boolean isGoodMorning( str ){
return "おはよう".equals( checkStr ) ;
}
/**
* 文字列がこんにちはであるか判定する。
* @param str 判定する文字列
* @return true:こんにちはである。 false:こんにちはでない。
*/
private boolean isHello( str ){
return "こんにちは".equals( str ) ;
}
/**
* 文字列がこんばんはであるか判定する。
* @param str 判定する文字列
* @return true:こんばんはである。 false:こんばんはでない。
*/
private boolean isGoodEvenning( str ){
return ("こんばんは".equals( str ) || "今晩は".equals( str ) );
}
主処理はif ( 判定 ) { 処理A } else { 処理B }
という形式になりました。
このように複雑になりそうな判定式は、適度にboolean型を返すprivateメソッドを記述することで主処理の可読性が良くなります。
またこのようにif文の判定をメソッド化する利点は、複雑な条件の要件が増えても、1メソッド内の条件の修正で済み、
if文の階層間違いや条件間違いなどを抑制する事が可能です。
纏めると
if ( 判定式 ) { 処理; }
の形式か if ( 判定式 ) { 処理A; } else { 処理B; }
形式で記述する。本サイト「コーデイング規約」に電通国際情報サービス様のコーディング規約をダウンロードできるようにしています。
本記述内容の事が、ダウンロードしたコーディング規約に掲載されていますので、ご参照下さい。