• 締切済み

条件判断の記述方法

いつも下記のような記述でまよってしまいます。 どちらがスマートな書き方なのでしょうか。 もしくはそもそもの書き方がおかしいでしょうか。 [記述方法1] foreach( string s in k.keys ) { if( s == "ok" ) goto OK; } //NGな処理 return false; //OKな処理 OK: return true; [記述方法2] bool ok_flg = false; foreach( string s in k.keys ) { if( s == "ok" ) { ok_flg = true; break; } } if( ok_flg ) { //OKな処理 }else{ //NGな処理 } return ok_flg;

みんなの回答

  • anmochi
  • ベストアンサー率65% (1332/2045)
回答No.4

長文です。#1です。 > そのメソッドのためだけに存在する > 変な名前の細かいプライベートメソッドだらけになってしまいます。  これはクラス設計上の問題、つまりどこまでをメソッドに切り分けるべきか、という話なんだけど、実際これはセンスの問題ではないんだよね。あるべきところにあるべきものを配置すればよいだけで。  つまり、長くなったからメソッドに切り分けしようとして変な名前のメソッドが出来上がる場合、それはメソッドに切り出すべきではないという事。分ける理由として「長いから」は不適切だよね。  意味、つまり、「処理単位」で切り分けると、そのメソッドにつける名前は「その処理をあらわす言葉」になる。すごく自然な話だよね。長くなったら、C/C++で言うifなどのブロック単位に分けていくのではなく、ブロック内部またはロジック中で一処理として切り出せないかを分析する。そこで分ける理由が無けりゃ(意味的に細分化できなければ)分けるべきではないんだよ。逆に言やたとえ一行のロジックであってもそれが一つの処理をこなすのであれば分けた方がアルゴリズムは見えやすくなる。 int getMax(int x, int y) { return x > y ? x : y; } なんてその典型例だよね。一行でも、「xとyを比較してxが大きい場合はxを返す、そうでなければyを返す」ではなくて、「xとyの大きい方を返す」という論理的な処理をルーチン化したものだ。  VBでも、こういうプロシージャを作った事あるんじゃないかな。 Public Sub CenterForm(ByRef f as Form) f.Left = (Screen.Width - f.Width) / 2 f.Top = (Screen.Height - f.Height) / 2 End Sub  これも、たった2行なのに分かれているのは、決して「窓の位置を画面の幅-窓の幅を2で割った値にする」という事したいんじゃなくって「窓の位置を画面の中央に」という事をしたいので切り出していて、だからメソッド名がCenterFormになっている訳だ。処理の意味で切り出すという事。  今回のお題だと、キーの中の何かがOKであればというifブロック内を機械的に切り出した場合、メソッド名はOnValidKeyExist()のような名前になるけど、この名前は「処理の内容」を表していないよね。言うなれば処理の状況を説明する名前だ。これは構造化手法の切り出し方。フローチャートの一部分をサブルーチン化しているという事になる。これだったら、逆に有効がキーがあるかどうかを切り出す方が良いでしょう。 private boolean isValidKeyExist() { foreach(string s in k.keys) { if(s == "ok") return true; } return false; }  こっちを切り出すと、「有効なキーがあるかどうか」という一つの論理的な処理を担当する(すべき)メソッドができあがる。呼び出す側は if(isValidKeyExist()) { // OKな処理 } else { // NGな処理 } こっちの方がすっきりしないかな?  この「処理単位の切り出し方」を覚えると、フラグがすごく良い意味を持つようになる。フラグやgotoの悪い側面である、「プログラムの見通しが悪くなる」という事が発生しなくなるんだ。  フラグだから悪、gotoだから悪っていうんじゃなくて、フラグやgotoが大小の処理間にまたがらない事が重要なんだね。 まとめると、 ・意味でプログラムを切り出す(ルーチン化する)事が肝要 ・適切に切り出された一つの処理内であればフラグも綺麗な状態遷移を行う って事です。

ufyooo
質問者

お礼

詳細な回答ありがとうございます。 大変参考になります。 >分ける理由として「長いから」は不適切だよね。 そうなんですよ。 いつも切り出しするときに大きな欲求を占めるのが長くなりそうだなーでした。 それが、特にif文やswitch文のブロックの中だと取りあえず外に出しとけって感じになっちゃてますね。 結果、変な名前のプライベートメソッドが変な階層でできてしまいます。 >・意味でプログラムを切り出す(ルーチン化する)事が肝要 >・適切に切り出された一つの処理内であればフラグも綺麗な状態遷移を行う 上記を意識しながらがんばってみたいと思います。

  • notnot
  • ベストアンサー率47% (4848/10261)
回答No.3

このケースであれば、goto を使いますね。 一時的変数は出来るだけ使わないに越したことは無いです。 フラグ変数を使う場合は、変数の未定義化が出来る言語ならok_flgを参照した直後で未定義化すればいいのですが、C++ だと、 //これ以降 ok_flg は使わない とかコメントで書くのかな。 goto文の使用については、 STEP1. goto文を使うことを覚える STEP2. goto文を使わない書き方を覚える STEP3. goto文も使うことを覚える と言われています。

ufyooo
質問者

お礼

回答ありがとうございます。 VB暦が長いへぼプログラマーなので ロジックの中にデータベース処理などが絡んでくると フラグとgotoでいつも悩んでいます。

noname#31077
noname#31077
回答No.2

gotoラベルを用いる人は嫌われる傾向にあります。 前者はやめましょう。 後者はフラグを用いた分岐処理ですね。 フラグは多用すると可読性を非常に欠くコードになってしまいます。 しかし、今回の使い方は局所的なのでいいと思います。 よって後者が良いと思いますよ。 人にもよりますけど、私ならフラグは用いません。 foreach( string s in k.keys ) {   if( s == "ok" )   {     //OKな処理     return true;   } } // NGな処理 return false; とします。 参考になりました。?

ufyooo
質問者

補足

回答ありがとうございます。 フラグとはちょっと離れてしまうかもしれませんが、 if( s == "ok" ) { //OK処理がちょっと長い  ・  ・ } となることが多く、切り出しを行うと そのメソッドのためだけに存在する変な名前の細かいプライベートメソッドだらけになってしまいます。 そうなるとラベルを付けてメソッド内で処理してしまいたくなる衝動にかられるんですが、やはり嫌われますよね。

  • anmochi
  • ベストアンサー率65% (1332/2045)
回答No.1

 これって、1個でもOKな奴があったらOKな処理をしてから呼び出し元に制御を返すの? じゃあ foreach( string s in k.keys ) { if( s == "ok" ) { //OKな処理 return true; } } //NGな処理 ここにたどり着いたのであればOKが一つも無かったという事 return false; で良いんじゃないかなぁ。

ufyooo
質問者

お礼

回答ありがとうございます。

関連するQ&A

  • 演算子を使わずに書く

    $sqlを「.=」を使わずに書きたいんですが、複雑でよく分かりません。 どなたか書いてもらえませんか? $sql ="update table set flg=0 where id in("; $flg=true; foreach($_POST["del"] as $val){ if($flg) {$flg=false;} else {$sql.=",";} $sql .="'".mysql_real_escape_string($val)."'"; } $sql .=")"; よろしくお願いします。

    • ベストアンサー
    • PHP
  • javascriptの記述方法おしえてください。

    以前こちらで質問し自己解決に至ったのですが、 もっと簡単スマートにスクリプトを記述したいのですが、 どのような記述をすれば良いかご教授ください。 //ここから var flg1=1,flg2=0,flg3=0,flg4=0   $(window).on('scroll', function() {     if($('#contents01').offset().top <= $(window).scrollTop() && $('#contents02').offset().top-1 >= $(window).scrollTop()) { if(flg1==0){ $('.nav1').stop(true,true).fadeTo(100,0.3).stop(true,true).fadeTo(500,1); flg1=1,flg2=0,flg3=0,flg4=0 } } if($('#contents02').offset().top <= $(window).scrollTop() && $('#contents03').offset().top-1 >= $(window).scrollTop()) { if(flg2==0){ $('.nav2').stop(true,true).fadeTo(100,0.3).stop(true,true).fadeTo(500,1); flg1=0,flg2=1,flg3=0,flg4=0 } } if($('#contents03').offset().top <= $(window).scrollTop() && $('#contents04').offset().top-1 >= $(window).scrollTop()) { if(flg3==0){ $('.nav3').stop(true,true).fadeTo(100,0.3).stop(true,true).fadeTo(500,1); flg1=0,flg2=0,flg3=1,flg4=0 } } if($('#contents04').offset().top <= $(window).scrollTop() && $('#contents04').offset().top-1+$('#contents04').height() >= $(window).scrollTop()) { if(flg4==0){ $('.nav4').stop(true,true).fadeTo(100,0.3).stop(true,true).fadeTo(500,1); flg1=0,flg2=0,flg3=0,flg4=1 } }   }); //ここまで 上記スクリプトは1部ですが、 このスクリプト部分で、 フラグを立てイベントを実行する、 しないの判別をさせています。 参考までに http://www11.ocn.ne.jp/~website/sample2/index.htm

  • Pythonのコードの解説をお願いします

    このコードはスペースが2つ以上ある場合スペースを一つだけにする、そして文の最初と最後にスペースがあった場合そのスペースを消すというものだとういうことは理解出来たのですが、なんでこういうコードを書いたぬぬかついんのか、 def removeExtraSpaces(theString): ans = '' flg = True for s in theString: if s == ' ': if flg: ans += s flg = False continue flg = True ans += s ans = ans[1:] if ans[0] == ' ' else ans ans = ans[:-1] if ans[-1] == ' ' else ans return ans これを解説して

  • アクセスvba if文の記述方法

    検索フォームを作成しました。 入力項目は「氏名」「カナ」で入力チェックをおこなっております。 (未入力)メッセージを表示「未入力です」 (入力有)結果一覧のフォームを表示 未入力チェックは正常に処理されておりメッセージが表示されます。 項目に値を入力した場合フォームが起動しません。 if文から外した場合は正常に実行されます。 この条件の場合if文でどのように記述したらよいのでしょうか。 宜しくお願いします。 Private Sub 検索_Click() Dim mct As Control Dim flg As Boolean flg = False For Each mct In Me.Controls  If mct.ControlType = acTextBox Then   If mct.Tag = "Check" Then    If Not IsNull(mct) Then     flg = True     Exit Sub    End If   End If  End If Next mct If flg = True Then  Dim str As String  str = "[氏名] Like ""*" & Me!氏名 & "*"" And [カナ] Like ""*" & Me!カナ & "*"""  DoCmd.OpenForm "結果一覧", , , str Else  MsgBox ("未入力です") End If End Sub

  • ちょっとした記述に関する疑問

    どちらでもいいような内容かもしれませんが、よろしくお願いします。 ---------------------------------- flag = false; if(num < 0) { num *= -1; flag = true; } //numを使って何かの処理 ~~ if(flag) { //処理 num *= -1; } ---------------------------------- 例として、変数numが負だったらフラグをtrueにして、 最後にそのフラグをもとに処理を行うという一連の動作があった場合に、 if(num < 0) { num *= -1; flag = true; } というふうにフラグを後に記述するのか if(num < 0) { flag = true; num *= -1; } というふうにフラグを先に記述するのか がふと気になったのですが、みなさんはどちらでやっているのでしょうか?

  • コード(Python)の解説をして頂きたいです

    このコードはスペースが2つ以上ある場合スペースを一つだけにする、そして文の最初と最後にスペースがあった場合そのスペースを消すというコードだということは理解出来たのですが、flgはなんの略なのかということと、ans = ans[1:] if ans[0] == ' ' else ans ans = ans[:-1] if ans[-1] == ' ' else ans このコードのelse ansはどのような働きをしているのか分かりません。 もし宜しければ解説をして頂きたいです。 def removeExtraSpaces(theString): ans = '' flg = True for s in theString: if s == ' ': if flg: ans += s flg = False continue flg = True ans += s ans = ans[1:] if ans[0] == ' ' else ans ans = ans[:-1] if ans[-1] == ' ' else ans return ans

  • 「checkText3」が処理されない

    とあるHOWTO本を見ながら、独学でPHPを勉強中です。 サンプルプログラムを動作させようとマニュアル通りに記述してみたのですが、一部分だけが上手く処理されません。 付属CDに収められているphpファイル自体がこのような記述になっている為、マニュアル自体に間違いがあるのかな?と思うのですが、 どこがおかしいのか解らずにいます。 お分かりになる方がいれば、ご教授願えませんでしょうか? 上手く処理されないのは「//テキストチェック3.バイバイされたらバイバイを返す」の部分です。 よろしくお願い致します<(_ _)> <?php $res = ""; if(isset($_POST['text1']) == false) {$res = getAisatsu();} else{$text1 = $_POST['text1']; if($text1 == "") {$res = "え? なんていったの?";} else{$flag =false; //まずcheckTextであいさつ文をチェック $str = checkText($text1); if($str != false) {$flag = true; $res = $str; } //続いてcheckText2で悪口の対応 if($flag == false) {$str = checkText2($text1); if($str != false) {$flag = true; $res = $str; } } //最後にcheckText3でさよならの対応 if($flag == false) {$srt = checkText3($text1); if($str != false) {$flag = true; $res = $str; } } //すべてダメならテキストを分解してチェック if($flag == false) {$arr = bunkatsu($text1); foreach($arr as $str) {if(getWordCheck($str) == true) {$flag = true; $res = $str . "って、なぁに?"; break; } } } //それでもダメなら全文で聞き返す if($flag == false) {$res = delTouten($text1) . "って、なぁに?";} } } //時間によって異なるあいさつ文を返す function getAisatsu(){ $arr = array('……ね、眠い','おはよう!','こんにちは~','こんばんわ',); $d = getdate(); $t = $d['hours']; $t2 = (int)($t / 6); return $arr[$t2]; } //テキストチェック。あいさつ文があれば対応する挨拶を返す function checkText($s){ if($s == ""){return false;} $res = false; $data = array('こんにちは','こんにちわ','こんちは','こんちわ'); foreach($data as $str) {if (mb_strpos($s,$str) !== false) {$res = 'どうも、' . $str . '!'; break; } } return $res; } //テキストチェック2.悪口が書かれていたら文句をいう function checkText2($s) {if ($s ==""){return false;} $res = false; $data = array('バカ','馬鹿','あほ','アホ','阿呆'); foreach($data as $str) {if(mb_strpos($s,$str) !== false) {$res =$str . 'じゃないもん!'; break; } } return $res; } //テキストチェック3.バイバイされたらバイバイを返す function checkText3($s) {if ($s == ""){return false;} $res = false; $data = array('ばいばい','バイバイ','じゃあね'); foreach($data as $str) {if(mb_strpos($s,$str) !== false) {$res = 'それじゃ' . $str . '!'; break; } } return $res; } //句読点を削除する function delTouten($s) {$res = str_replace('。','',$s); $res = str_replace('?','',$res); $res = str_replace('!','',$res); $res = str_replace('.','',$s); $res = str_replace('?','',$res); $res = str_replace('!','',$res); return $res; } //テキストを句読点で分割し、配列として返す function bunkatsu($s) {mb_regex_encoding("sjis"); $res = mb_ereg_replace('[。、?!,.!?]','',$s); $arr = mb_split(' ',$res); return $arr; } //主語や接続詞が含まれているかを調べる function getWordCheck($s) {if ($s == ""){return false;} $res = $s; $data = array('私','わたし','僕','ぼく','俺','おれ','オレ'); foreach($data as $str) {if(mb_strpos($s,$str) !== false) {$res = false; break; } } return $res; } //サニタライズ function getSeftyText($s) {$res = str_replace("<","<",$s); $res = str_replace(">",">",$res); return $res; } ?>

    • ベストアンサー
    • PHP
  • ASP.Net return confirmにて

    お世話になります。 ボタンonclickに return confirm を設定して そのボタンの処理を実行するかどうかを選択できる方法を以前こちらでお教えいただきました。 大変重宝して使わせていただいております。 ところが、ボタンをクリック → 処理1 → ここで選択 YES → 処理2                                   NO → 処理3 のような場合があるのですが、return confirm の戻り値が Boolean ということは 処理の中で、     Dim Flg as Boolean     Flg = return confirm("処理をスキップしますか?");     If Flg = True then      'スキップ処理     else      '通常処理     End if こういうことはできないのかなと思ったのですが、できませんでした。 もしかしたら、文法を無視した無茶苦茶な記述かもしれませんが、ボタン処理にOKを出した後に 再度、何か選択があった場合に ユーザーに選択させるにはどうすればよろしいでしょうか? 根本から考えなおしたほうがいいでしょうか? 何かアドバイスがございまいたら、何卒ご指導いただければと存じます。 よろしくお願い申し上げます。

  • 二つの配列を一つにまとめる(sqlでいうjoin)

    データベースから別々に取得したデータを一つにまとめる方法で、 今やってるのはなんだか冗長な感じでいけてない気がするのですが、 ほかの方法が思いつかないので投稿いたしました。 $artist と $music に music_id というカラムがあって、これが一致するものだけを取得する。 以下今やってる方法。 foreach ($artist as $key => $value) { $flg = false; foreach ($music as $k => $v) { if($value["music_id"] == $v["music_id"]) { $flg = true; break; } if ($flg) { $data[] = $value; } } } やっぱりなんだかいけてないですねーorz いい方法を教えてください!

    • ベストアンサー
    • PHP
  • pythonコードについて

    以下のpythonコードに関して質問があります。なぜ一度Falseになったatsplitがforループ内で再びTrueになるのでしょうか?以下にコードと結果を掲載しております。 def split_string(source,splitlist): output = [] atsplit = True for char in source:    if char in splitlist:      atsplit = True      print atsplit    else:       if atsplit:          output.append(char)          atsplit = False          print atsplit       else:          output[-1] = char return output out = split_string("This is a test-of the,string separation-code!"," ,!-") print out #>>> ['This', 'is', 'a', 'test', 'of', 'the', 'string', 'separation', 'code'] False True False True False True False True False True False True False True False True False True ['This', 'is', 'a', 'test', 'of', 'the', 'string', 'separation', 'code']tsplit = True

専門家に質問してみよう