私はswitch文が嫌い


私はswitch文が嫌いである。

理由1:同じ変数が入るswitch文があちこちにある場合には問題が多い。

 同じ変数が入るswitch文が多数ある場合には、「単一責任の原理」を破っている可能性が高い。コードを改変したとき、一方だけ改変して、他方が放置される可能性が生じる。

理由2:論理構造とデータが分離されていない。

 switch文では、データが追加されるとcaseの分岐が増えてしまい、制御構造への変更が生じてしまう。データの追加によって制御構造が変わってしまうのは、case文がbreakを書き忘れしうることから、うれしくない。

理由3:整数型しか用いることができない。

 switch文で記述できるのは、整数値に限られる。そのため、比較先の値がenum型を使われることが多いのだが、enum型の値は、印字したときに整数値にすぎず(注)、「5という値は何を意味していたかなあ」とヘッダファイルからenumの値とその意味を探らなければならなくなる。
 整数型で値の比較で条件わけするのは、確かに速いのだろう。しかし、CPUの性能が上がっているときには文字列との比較をして、文字列を印字させた方が、はるかに意味がわかりやすく、開発時の値の表示の意味がわかりやすい分だけ、開発効率が上昇するように思う。

理由4:switch文ではbreak;のありなしの自由度があるのが嫌い。

 分岐の数が多数あるときに、いちいちswitch-caseの詳細をきちんと読むことをしたくない。どのcaseではbreakがあり、どのcaseにはbreakがないなどの可能性がありのが嫌い。

理由5:caseごとに、記述される動作が共通性なく記述できることが嫌い。

 caseごとに記述できる内容は、脈絡なくどのような内容でも記述可能です。そのため、そのswitch文が何をするのかは、全てを読まないと確認できないのです。

switch(dayOfWeek){
case Sunday:
 市場に出かけ;
  break;
case Monday:
 おふろをたいて;
  break;
case Tuesday:
  おふろにはいり;
  break;
case Wednesday:
  ともだちが来て;
  break;
case Thursday:
  送っていった;
  break;
case Friday:
  糸まきもせず;
  break;
case Saturday:
  おしゃべりばかり:
  break
default:
 ;
}

対策:

 私は、このような目的にmap型を使っている。
効果1:
 switch文をstd::map型に置き換えることで、そのmap型を参照することで、map型の定義を1回記述するだけで済むので、単一責務の原則を実現しやすい。
効果2:
 論理構造とデータが分離される。データの追加があっても、論理構造が改変されることがない。
効果3:
std::mapなどのように条件わけの入力にstd::stringや他のデータ構造を入れることができる。
そのため、enum型よりも表示させたときに意味がわかりやすい。

効果4:
 map型は値の入力に対して値を返すだけなので、breakの有り無しのような自由度が入りようがない。
効果5:
 map型は返される値の型が決まっているので、一定のルールが守られる。
返される値に関数を入れることもできるので、一貫性のある設計を簡潔に記述することができる。

注:
ブログサイトenum(列挙型) の使い方

C++ では、enum(列挙型) の値を例えば printf で表示しようとすると、整数として表示するしか方法がないということです。

追記:
switch文については
コードの不吉な臭い
の中にもあげられています。
「新装版 リファクタリング 既存のコードを安全に改善する」

switchを消すメイキング的な話