「if, else, switch, for, while などの条件分岐やループ制御を使わないですむとコードが見やすくなる」
と耳にしました。
if elseの条件分岐はとても頻繁に使用しています。
string[] fruits = new {"apple", "strawberry", "orange"};
foreach(string fruit in fruits){
if (fruit.Contains("apple") || fruit.Contains("strawberry")
MessageBox.Show("color is red");
else if (fruit.Contains("orange")
MessageBox.Show("color is orange");
}
とかです。
これを条件分岐やループ制御なしで書くととってできますか?
もっと見やすいコードがあれば教えてください。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答13件
0
例えば以下とかどうぞ
State パターン
Javaですがオブジェクト指向としての考え方ですので同じです。
if や switch などの分岐なくしてプログラムは書けませんので、必ず使います。
ただ、ここはこれじゃダメだろーという部分はあります。
例えば、
C#
1switch(会員ランク) 2{ 3 case シルバー会員: 4 // シルバー会員用の金額計算 5 break; 6 7 case ゴールド会員: 8 // ゴールド会員用の金額計算 9 break; 10 11 default: 12 // 一般会員用の金額計算 13 break; 14}
プラチナ会員が増えた場合
ランクで分岐してるとこ全部洗い出さないとダメじゃないか。。。
おいおい・・・めちゃくちゃあるじゃねーか!・・・これ全部にcase足していくのかよ。。。
みたいになってきますので、
こういう場合は、Stateパターンを使うべきです。
C#
1GetMember().Rank.GetPrice(定価);
書かれている例で言うと、Fruitクラス作って、中で Color を持てば終わりのような気もします。
C#
1foreach(Fruit fruit in fruits){ 2 MessageBox.Show("color is " + fruit.Color); 3}
投稿2016/03/30 07:02
編集2016/03/30 07:32総合スコア4666
0
9 年前になめらかなコードと名前をつけてみたものの、私以外には流行っていない用語のようです。
それはさておき、ポリモーフィズム自体が特異点を除去し、NUllObjectパターンなどの各種デザインパターンが特異点を除去し、オブジェクト指向以前からある特異点除去方法としてはテーブル化 (連想配列を使うといいよ、と他の回答にあるようなもの) や番兵なんかがあるわけです。
特異点がなくなると見通しがよくなり、潜在的なバグも減りますが、特異時の処理が隠れてしまい、一般的に抽象度が高まるので、慣れていないと逆に理解しにくくなってしまう懸念があります。
if や switch が少ないから読みやすい、というのは必ずしも真ではありませんが、読みづらい≈潜在的なバグの温床になっている≈メンテする気になれない、ようなコードは無駄に if や switch が多い、というのは(経験的に)真です。
あ、あと、たくさんコードを「読んで」、それなりにコードを書いていると、これは駄目だろうという if 文と、これは問題ないだろうという if 文の違いが感覚的にわかるようになってきます。
投稿2016/04/05 10:33
編集2016/04/05 11:56総合スコア2468
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/04/05 11:51
0
こんにちは。
「無駄な」条件分岐を書くことって意外にあるので、それを減らしましょうということではないでしょうか?
バグの主な原因の1つは条件分岐ミスですし。
例えば、a, bがbool型の時、
C#
1if (a && b) { 2 foo(); 3} 4if (!a && !b) { 5 foo(); 6}
よりは、
C#
1if (a == b) { 2 foo(); 3}
の方が良いと思います。
これはちょっと無理やりな例ですが、似たようなケースは身近に転がっていると思います。
投稿2016/03/30 07:28
総合スコア23272
0
何事もそうですけど,「~だからこうした方がいい」というのはある意味正解で,ある意味ハズレだと思うんですよね
すでにたくさん回答があるのであれですけど,この回答群の中から好みの回答を選ぶのだってif ~ then ~ elseでしょうしね.
今回の命題の 「if, else, switch, for, while などの条件分岐やループ制御を使わないですむとコードが見やすくなる」なんてのもその通りで,
使わないでいいならそれに越したことはない
でしか無いと思うんです.
そのためにはコーディングの軽いうちに熟考し,あ,このケースがあるな,こんな感じでパターンが増えそうだな,どうやってまとめとこうかな?といった考え方を常に持つことが重要だと考えます.
たとえばroot_jpさんの解答の例に有る条件が増えたときの対処,なんていうのはすごくわかり易い例でして(+1させていただきました!),このようなケースは実に多くあります.
仕事柄工場の生産管理システムなどに携わっているのですが,品種の追加(新製品に対応するので,新しく生産する品物を増やしたい)なんてことがありますと,以前の品種コードをgrepし,そのコードに関連したところを片っ端から改造していく,なんてことをする羽目になっています(あ,これはベースのソフトの設計が悪くて泣かされているパターンです).
知識がある今ならばこんな風に設計して~,こんなクラスで実装して~,とか言えますけど,今更そんな改造は出来ないですね(動いているコードが正義,なんて皮肉もあります).
ですので,条件分岐やループ制御は自分の知識で十分理解できているところのみ省き,後は普通にコーディングする,というのがおすすめです(それが可読性が良い,ということです).
そもそも条件分岐やループ制御が自在にできるのがソフトウェアの強みです.
(ハードウェアで組まれたシーケンス制御なんてちょっと動作を変えるためにすげぇ改造が必要なんです…)
投稿2016/03/31 01:41
退会済みユーザー
総合スコア0
0
root_jpさんが言われているstateパターンが定石だと思います。
今回の場合、if-elseなどによる条件分岐けが多いとき、もっと保守性や可読性、拡張性の高いコードにするにはどうしたら良いか…という古典的(で、多くの人が遭遇する)問題だと思います。
こういった問題の解決策というのは、多くの場合、先人の方々によってデザインパターンが既に考えだされていることが多いです。
結局、どれだけデザインパターン
を理解して、使いこなせるかが、可読性のある(そして保守性、拡張性もある)コードを書く近道(もちろん命名規則やJavadocの書き方、リファクタリングの技術など色々他にも学ぶべきことはありますが。)だと思います。
デザインパターンについては、書籍などで体系的に一度学習されると良いと思います。
投稿2016/03/31 02:23
編集2016/03/31 02:26総合スコア907
0
Stateパターンはおすすめの方法ですが、サンプルコードにはちょっと大げさかもと感じたので、ほかの方法を紹介します。
「if, else, switch, for, while などの条件分岐やループ制御を使わないですむとコードが見やすくなる」
と耳にしました。
私は、あまり同意できません。分岐が多くなるのはよくないコーディングの結果であって、分岐そのものを問題にするより、ネストが深い(C#の場合、中括弧の数が多い)が問題だと思います。
と言いつつ、ネストがのもよくないコーディングの結果だと思ってます。なぜネストが深くなってしまうのかというと、大きなことを一挙にやろうとしているからです。
それで、色の名前を判定するgetColorNameメソッドといろを表示するshoeColorメソッドを定義して下記のようなコードにしました。
C#
1using System; 2using System.Linq; 3 4public class Hello{ 5 public static void Main(){ 6 Func<string, string> getColorName = 7 fruit => { 8 if(fruit == "apple") return "red"; 9 if(fruit == "strawberry") return "red"; 10 if(fruit == "orange") return "orange"; 11 return "unknown color"; 12 }; 13 14 Action<string> showColor = 15 fruit => Console.WriteLine("Color is " + getColorName(fruit)); 16 17 string[] fruits = new string[]{"apple", "strawberry", "orange"}; 18 19 foreach(var fruit in fruits) showColor(fruit); 20 } 21}
特に見てほしいのは、getColorNameメソッドで、色を判定できたらすぐさまreturnをすることで、コードを単純化しています。メソッドを細かく分けることに慣れていない場合、すぐにreturnをするコードは不安になるとおもいますが、十分にメソッドの機能を小さくできていれば問題にはなりません。
HashTableやDictionaryがコードが単純だとは思います。今回はメソッドを分ける例を出したかったので、あえて使っていません。
投稿2016/04/05 10:33
総合スコア2883
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
LiveScriptで書いてみました。
遷移先の画面で下記のコードを張り付けてrunボタンを押してみてくだしあ
fruits-colors = apple: \red strawberry: \red orange: \orange to-color = (name)-> fruits-colors.(name) or \nothing output-color = (fluits)-> fluits |> to-color |> -> console.log "color is #it" <[apple strawberry orange]> |> each output-color
私は英語力がないのであまり良い書き方は出来ませんが、
英語っぽく書いてみたり、関数型プログラミングを覚えると応用が効きやすいかとおもいます。
How to write a code like English(英文のようにプログラミングをする方法)
C#に応用出来るかはわかりませんが、
私はPHPのみでしたが、LiveScirtを業務で触るようになってからPHPのソースコードも影響うけてカラフルに書けるようになりました。
LiveScriptはマイナー過ぎるので、RubyやElixir、Haskellが良いかもしれません。。。
投稿2016/04/06 06:14
編集2016/04/06 08:32総合スコア21158
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
時と場合と言語しだいじゃないスかねえ。
シンプルにするのと分かりやすいのとは違うと思うし。
// PHPですんませんが…
// if を使わない例として
// $fruit に果物の名前が入ってるとして
$ar = array("apple"=>"red", "strawberry"=>"red", "orange"=>"orange");
echo "color is " . $ar[$fruit];
ループなら高階関数が使えれば一行で済む場合もあるけど、
そういうコーディングに慣れてない人には難解ですしねえ。
投稿2016/03/30 07:07
総合スコア7458
0
Ç#でなくて C++ でのコードになりますが、
この場合は連想配列をつかうことで、条件分岐をなくすことができます。
くだものの種類がふえたり、その色の定義を変更するときに、一番変更量がすくないのは最後に示した方法です。
1.cpp
c++
1// g++ -std=c++11 1.cpp 2 3#include <iostream> 4#include <map> 5#include <string> 6using namespace std; 7 8int main() { 9 string fruits[] = {"apple", "strawberry", "orange"}; 10 11 // 質問文にあった方法 12 for(string fruit : fruits) { 13 cout << fruit << " "; 14 if (fruit == "apple" || fruit == "strawberry") { 15 cout << "color: red" << endl; 16 } else if (fruit == "orange") { 17 cout << "color: orange" << endl; 18 } 19 } 20 cout << endl; 21 22 // 連想配列をつかって条件分岐をなくした方法 その1 23 std::map<std::string, std::string> colors = { 24 {"apple", "red"}, {"strawberry", "red"}, {"orange", "orenge"}, 25 }; 26 for(string fruit : fruits) { 27 cout << fruit << " color: " << colors[fruit] << endl; 28 } 29 cout << endl; 30 31 // 連想配列をつかって条件分岐をなくした方法 その2 (colos だけを使う) 32 for (const auto &pair : colors) { 33 cout << pair.first << " color: " << pair.second << endl; 34 } 35 36 return 0; 37}
実行例
$g++ -std=c++11 1.cpp $ ./a.out apple color: red strawberry color: red orange color: orange apple color: red strawberry color: red orange color: orenge apple color: red orange color: orenge strawberry color: red
投稿2016/03/31 07:25
総合スコア22324
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
「if, else, switch, for, while などの条件分岐やループ制御を使わないですむとコードが見やすくなる」
条件分岐やループってのは構造化プログラミングで必須要素なので、まったく使わないというわけにはいかないでしょうが。。。
(new List<string> {"apple", "strawberry", "orange"}).ForEach( fruit => MessageBox.Show(fruit.Contains("orange")?"color is orange":"color is red") );
コレクションとラムダ式と3項演算子を組み合わせるとこんなものか。
投稿2016/03/30 07:03
編集2016/03/30 07:14総合スコア5572
0
こういうのでしょうか?
C#
1using System; 2using System.Linq; 3using System.Collections.Generic; 4class Test 5{ 6 public static void Main(string[] args) 7 { 8 var fruits = new List<string> { 9 "fuji apple", 10 "wild strawberry", 11 "hassaku orange", 12 "forbidden fruit", 13 }; 14 var fruitColor = new Dictionary<string, string>() { 15 { "apple", "red" }, 16 { "strawberry", "red" }, 17 { "orange", "orange" }, 18 }; 19 fruits 20 .Select(fruit => fruitColor.FirstOrDefault(kv => fruit.Contains(kv.Key)).Value) 21 .Select(color => "color is "+ color) 22 .ToList() 23 .ForEach(str => Console.WriteLine(str)); 24 } 25}
これが「見やすい」かどうかは人それぞれだと思います。Linqや関数型プログラミングに慣れている人はこちらの方がより「見やすい」と感じるでしょうが、そうで無い人にとっては逆にわかりづらく思えるかも知れません。
この書き方は「見やすい」こと以外に利点があります。それは、「書き換えやすい」ことです。たとえば、新たに"lemon"について"yellow"を足したくなったとしましょう。if文の時は分岐を増やして、また同じ事を書く必要がありますが、こちらではfruitColor
というDictionaryに{"lemon", "yellow"}
を追加するだけで終わります。他にも、"color is ..."というところを"色は...です。"に書き換えたいとか、大文字小文字を無視したいとか、表示するのは最初の数個までにしたいとか、表示の方法を変えたいとかいうとき、ほとんどの場合が1行書き換えるか、追加するだけで済みます。
しかし、最初に言ったとおり、これはLinqや関数型プログラミングに慣れていることが前提です。慣れれば簡単ですが、慣れない内は難しいと感じるかと思いますので、全ての人に勧められるわけではありません。
投稿2016/04/06 15:32
編集2016/04/06 22:32総合スコア21735
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
「見やすさ」と言うか、
この先の展開も考慮して考えます
このソースを見て、内容は、リストにある「リンゴ」や「オレンジ」に対して、
その色を表示するプログラムである
「リンゴ」や「ストロベリー」はリストにしている
リストにしていると言う事は、「この後このリストは増えるかもしれない」
さて、「この先、このリストが増えるかもしれない」と考えた時、
リストに項目が増える度に if 文の条件式を治す事になる
if (fruit.Contains("apple") || fruit.Contains("strawberry")
こういう式は避けた方が良いと判断します。
つまり、
フルーツのリストを作るのであれば、
色のリストも合わせて作った方がこの先の展開を考えた場合見やすくなる
だって、
if (fruit.Contains("apple") || fruit.Contains("strawberry")
この後に、 || fruit.Contains(赤い果物) が、永遠と並ぶ事を考えて
みたら判るでしょ
投稿2016/04/19 00:59
総合スコア12
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/03/30 07:21