現在、下記のように条件式を積み重ねていく処理があるのですが、
if(a===1){
}elseif(a===2){
}elseif(a===3){
}elseif(a===4){
…
条件式がそれこそ500個など大量になった場合、処理効率が悪い方法だと思います。
※新しく条件が追加された場合、上記のように条件式を追加していくという運用をしています。
通常、このような処理・記述を効率化したい場合、どのような記述方法が考えられますでしょうか?
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/12/13 00:43 編集
2017/12/13 00:51
回答4件
0
ベストアンサー
ポリモーフィズムを使いましょう。
PHPでは一般的に以下の2つの手段が用いられます。
- 値が欲しい: 連想配列のキーとして用意して探索
- 処理を実行したい: オブジェクトを差し替えて同名のメソッドを実行する
1個目はそのまんまです。
PHP
1// こんな感じで想定される値を作っておく 2$results = [ 3 "miyabi" => ["kokugo" => 60, "sugaku" => 75], 4 "realmccoy" => ["kokugo" => 75, "sugaku" => 75], 5]; 6 7function get_kokugo ($results, $name) { 8 // PHPでは存在しないキーを参照しようとするとエラーになるのでissetやarray_key_existsで確認する 9 if (isset($results[$name]["kokugo"])) { 10 return $results[$name]["kokugo"]; 11 } 12 return 0; 13} 14var_dump(get_kokugo($results, "miyabi")); 15// Int: 75
このようにすれば選択肢がどんなに増えてもif文1個で事足ります。
例えばエラーコードとエラー文言の対応表をMySQLに格納して取りに行く設計にすれば、まるでMySQLをIF文の情報置き場であるかのように振る舞います。
2個目はオブジェクト指向(OOP)でよく使われる手法です。
PHP
1class Animal { 2 __constructor($name, $nakigoe) { 3 $this->name = $name; 4 $this->nakigoe = $nakigoe; 5 } 6 public function meu () { 7 return $this->nakigoe; 8 } 9} 10 11$neko = new Animal('mike', 'myao'); 12$inu = new Animal('poti', 'bow'); 13$miyabi = new Animal('miyabi', 'hueee...'); 14 15function cry ($it) { 16 echo $it->meu(); 17} 18 19cry($miyabi); 20// hueee...
こんな感じです。
注意点としては、
処理が分散するので基本的にコード量が増えます。
- 新しく配列やクラスを定義する必要がある
- 持ってくる引数や変数、メソッド等も増える
下手な管理をしていると処理は色んな所に散らかって読みづらくなってしまいます。
このグループはこの点では同じだよね、という共通点を上手く抽出して抜き出す(抽象化)が必要ですし、
抜き出した共通部分が何かに適切な名前付けが必要です。
半年後の自分に、このクソコード書いたのは誰というネタが多くありますが、
大抵は自分の名付けた名前がまずくて連想出来ないからです。
長くやっていれば勘所がつくようになるので、
あれは良かったのだろうか、悪かったのだろうか…という反省を行うようにしてください。
書籍「リーダブルコード」を読むことでもセンスは磨かれると思うのでオススメします。
投稿2017/12/12 11:42
編集2017/12/12 11:53総合スコア21158
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
条件式がそれこそ500個など大量になった場合、処理効率が悪い方法だと思います
処理・記述を効率化したい場合、どのような記述方法が考えられますでしょうか?
数が多い条件式を効率的に記述するには、
まず、配列や連想配列を使うのがよくある手法です。
処理内容も大きく変わる場合には、別オブジェクトに分け、
ポリモーフィズムで分岐させます。
しかし、これらはすでに回答されているので、
難しくなりますが、別の方法も説明しておきましょう。
条件式が500個もあって、仕様上どうしても省略できない前提なら、
(プロダクション)ルールエンジンを作る(使う)ことも視野に入れます。
とくにたとえば、毎月500個の別の条件式を使うとか、
変更が多い場合には、最初の作成コストは掛かりますが、
システムを作ってしまった方が、その後の変更コストは下がります。
というのも、たとえば一ヶ月や一年経って、内容を忘れてしまってから、
また500個の条件式をチェックするのは、非常に労力が掛かるからです。
携帯電話の料金とか、ああいうビジネスルールが非常に複雑な場合、
ルールエンジンが実務で実際に利用されているようです。
ルールエンジンはそこそこ難しいので、実装方法の詳細は省略しますが、
概要だけ言うと、条件分岐をIF文などで直接書くのではなく、
条件分岐させるルールをDSLに分離して、
ルールエンジンがそのDSLを読み取って、代替計算します。
DSLにはIF文などがないので、記述量が減るし、場合によって、
DSLを仕様に対応させて、直接読み下せるようになるのがメリットです。
もし、自力で実装する場合、Prologのような宣言的言語を参考にします。
しかし率直に言うと、Prologは難解です。少なくとも、初心者向けではないです。
だから、JBossなどOSSのBRMSを利用する方法も、ひとつの選択肢でしょう。
(追記)
JBossはJavaなので、PHPで完結させたい場合、どうすればいいか。
「Ruler」というPHPのルールエンジンがあり、
GitHubで公開されているので、
これを使うなり、参考にして実装するなりします。
投稿2017/12/13 11:24
編集2017/12/13 11:41総合スコア5592
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
a,b,c・・・とチェックする要素がかわっていくのであれば
それぞれを排他的な条件設定をしているので
現在のifelseifelseif・・・で問題ないと思います
追記
命題を書き換えるとこういうことです
if(a===1){ 処理1 }elseif(b===2){ 処理2 }elseif(c===3){ 処理3 }elseif(d===4){ 処理4 }
↓↓↓
if(a===1){ 処理1 } if(a!==1 && b===2){ 処理2 } if(a!==1 && b!==2 && c===3){ 処理3 } if(a!==1 && b!==2 && c!==3 && d===4){ 処理4 }
elseの処理は前方の条件の偽をすべて継承していくるわけです。
元の書き方のほうが効率的だとわかりますよね?
投稿2017/12/13 00:43
編集2017/12/13 02:42総合スコア114839
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。