̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ IT ニュース&コラム 2014/ 6/ 9 通巻663号 技術版 ソフトウェアデザイン館 Sage Plaisir 21  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ 計算順序を明示する冗長な括弧は書くな - リーダブル・コード(23) 2つの点の中点の座標を計算するプログラムは、次のようになります。 X 座標と Y 座標のそれぞれで、平均を求める式と同じ式になります。 x = ( x1 + x2 ) / 2 y = ( y1 + y2 ) / 2 掛け算や割り算は優先順位が高いので、計算結果を正しくするには、括弧を 書かないといけません。 小学生レベルの算数です。 常識です。 しかし、 そのことさえ忘れてしまっている大人が(少数派とはいえ)いるでしょう。 そういった優先順位を忘れてしまった大人でも、「計算順序に従って 括弧を書く」習慣があれば、間違ったプログラムを書く可能性は少なくなります。 本体価格が pre_tax_price のサービスを毎月支払うとき、消費税が 4 月に 5% から 8% に上がった今年は合計いくら支払うのかを計算するプログラムは、 次のようになります。 3月までの 3ヶ月分は 5%、4月以降の 9ヶ月分は 8% という式です。 price = 3 * pre_tax_price * 1.05 + 9 * pre_tax_price * 1.08 掛け算の優先順位を知らない人でも読めるようにするには、冗長ですが、 次のように括弧を書くとよいでしょう。 price = ( 3 * pre_tax_price * 1.05 ) + ( 9 * pre_tax_price * 1.08 ) 料金のパンフレットや経済学の本などの一般的な文書を見ると、 掛け算に対して括弧は書かないことが多いです。 おそらく複雑に見えてしまうとか、 補足的な意味合いを持たせる ( ) と混同しないようにするためとか、( ) が要らない 小学生レベルの計算さえ知らない人が書いたと疑われてしまうのが理由と 思われます。 もし、( ) を付けなかったことでクレームが付いたとしても、 小学生レベルの常識を知らなかったクレーマーの方が逆に疑われてしまいます。 そのような一般常識であるにも関わらず、一部のコーディング・ルールには、 掛け算に対してでさえ冗長な括弧を推奨しています。 一見、間違いを未然に防いでいる ように見えるのですが、それが「問題」にまでなることは少ないのです。 なぜなら、 一般常識がある多くの人は ( ) を書かなくても正しく動くプログラムが書けて 問題がなく、一般常識のない一部の人が正しく動かない(バグのある)プログラムを 書いてしまう危険を防ぐ効果しかないのです。 しかも、その問題は、テストすれば 高い確率で見つかるタイプの問題です。 それでも副作用がなければ文句は言いません。 しかし、一般の文書で避けていることを、あえてするという副作用があるのです。 余計なお世話です。 プログラミング言語には四則演算の優先順位だけでなく、いろいろな演算子に 対して複雑な優先順位があり、それを完全に知っている人の方が逆に少数派に なります。 ( ) を付けておけば、複雑な優先順位を多くの人が調べなくて 済むようになります。 たとえば、シフト演算では括弧が冗長に見えることがありますが、この場合の 括弧は、冗長な括弧ではなく、正しい演算結果を得るためには必要な括弧に なります。 シフト演算より + の方が優先順位が高いため、次の2つの式は 計算結果が異なります。 括弧がないと足し算を先に行います。 bits = value_A + value_B << 4; bits = value_A + ( value_B << 4 ); 冗長であると思っても実は必要な括弧であった。 これが、すべての順序が明確に なるように括弧を積極的に付けていこうとする主張の根拠です。 でも、それは、 シフト演算に対して付けようというルールで十分であり、副作用も最小限になります。 乱暴なルールの適用(抽象化)だったのです。 すべての順序が明確になるように括弧を書くルールを厳密に適用していくと、 別の副作用も発生します。 もう一度、消費税も含めた合計を計算する式を 見てみましょう。 price = ( 3 * pre_tax_price * 1.05 ) + ( 9 * pre_tax_price * 1.08 ) この ( ) を付けた式は、冗長ですが、5% である期間と 8% である期間の 2つの要素の足し算からなることが見やすくなっています。 このように、ブロックに分けることを明示的に示す効果も括弧にはあります。 これも括弧を積極的に書こうという根拠の1つです。 だからといって、すべての順序が明確になるように括弧を書くルールを厳密に 適用してしまうと次のように変わります。 price = ( ( 3 * pre_tax_price ) * 1.05 ) + ( ( 9 * pre_tax_price ) * 1.08 ) 違和感がありますね。 なぜでしょう。 その理由は、消費税はそれぞれの月に かかるのに、数か月分の本体価格の合計に対して税率を掛けているからです。 別の例を見てみましょう。 テストの結果を集計するプログラムに、成功した数 (pass_count)、失敗した数(fail_count)、テストしなかった数(skip_count) という変数があったとします。 それらの変数から、全部のテストの数(test_count) を計算するプログラムは、次のようになるでしょう。 test_count = pass_count + fail_count + skip_count すべての順序が明確になるように括弧を書くルールを厳密に適用すると次の式に なります。 test_count = ( pass_count + fail_count ) + skip_count pass_count + fail_count の値と、skip_count の値という、大きく2つに 分けられたように見えます。 しかし、そんな分け方に意味はありません。 動いているプログラムなのだから、何か意味があるのだろうと深く考えてしまうと、 開発コストの増大につながってしまいます。 ( ) を書く式と書かない式を比べて、どちらが見やすいかを比べるときにも 誤った判断をすることがあります。 次の式の中のそれぞれの演算が、 どの順序で行われているのか調べてみてください。 price = 3 * pre_tax_price * 1.05 + 9 * pre_tax_price * 1.08 price = ( ( 3 * pre_tax_price ) * 1.05 ) + ( ( 9 * pre_tax_price ) * 1.08 ) 括弧が書いてある方の式は、括弧を手掛かりに読むことができるため、調べやすかった ことでしょう。 だから、括弧を付けた方が良いのです、と判断するかもしれませんが 間違いです。 この式は前に説明したとおり、違和感がある式です。 順序を調べるとき 以外は、読みにくいのです。 式の意味を読むことに比べれば、順序を調べるのことは レアケースです。 それに、意図と違う順序なら計算結果が違うというハッキリした 問題が出るので対応も簡単です。 それに、括弧があることを前提にして読むくせが ついてしまうと、括弧を忘れたコードを誤って読んでしまう可能性も増えてしまうのです。 もし、静的解析ツールを使って括弧を書くように要求されたときは、( ) の内側に 空白を入れないようにすれば、( ) の存在が薄く見えますし、その括弧は静的解析 ツールで警告されないように対処した冗長な括弧であることを明示することができます。 average = ( a + b + c ) / 3 // a, b, c が並列する式 average = ( (a + b) + c ) / 3 // 警告に対処した a, b, c が並列する式 average = ( ( a + b ) + c ) / 2 // a+b と c に分けたことに意味がある式 ソース: MISRA C 2004 - 12.1 式中におけるC言語の演算子優先順位規則への依存は、 極力制限すべきである。 注目ニュース 一覧 ◇ 日本MS、国内でも Surface Pro 3 を7月17日に発売へ。 http://japan.cnet.com/news/service/35048771/ … ノートPCとしては軽いし薄いが、タブレットとしてはまだまだ。 ◇ 本を読む時間がない人向けの書籍要約アプリ、Quickreads。 http://k-tai.impress.co.jp/docs/news/20140604_651618.html … 要約を作る方法は人力。 ◇ OpenSSLにまた重大な脆弱性、直ちにパッチ適用を。 http://www.itmedia.co.jp/enterprise/articles/1406/06/news034.html … 6件もある。 ◇ H.I.S.のサイト閲覧しただけでマルウェア感染した恐れ、銀行の口座情報盗み取る。 http://internet.watch.impress.co.jp/docs/news/20140530_651100.html … Flash Player を最新に更新し続けていれば感染しない。 ◇ もっと気軽にアジャイルを学べるようにしたい。アジャイルチームを支える会を設立表明。 http://www.publickey1.jp/blog/14/post_242.html … 役に立たないけど使われている CMMI をテーラリングする気迫がないとダメだ。 ◇ 指輪型デバイス Nod。指1本のジェスチャーで端末操作を可能に。 http://japan.cnet.com/news/service/35048324/ … 汎用的な無線の小さなボタン。 ◇ グーグル、リンク削除依頼フォームを公開。忘れられる権利に対応。 http://japan.cnet.com/news/business/35048757/ … 果たしてどれだけ本当にリンクが削除されるのか。 ◇ 3Dプリンターで違法な物を出そうとすると作動停止させるプログラム開発。 http://internet.watch.impress.co.jp/docs/news/20140528_650533.html … 文字認識と同様に、あいまいさをどう克服するかが課題。 ◇ オグたん式 F1の読み方、今年のF1が抱えた矛盾。 http://car.watch.impress.co.jp/docs/series/f1_ogutan/20140530_651124.html … 自動車の環境性能を上げる日本のスーパーフォーミュラ。 ソフトウェアデザイン館 Sage Plaisir 21 ホームページ >>> http://www.sage-p.com/ メルマガ >>> http://www.mag2.com/m/0000083983.html ブログ >>> http://blog.livedoor.jp/sage_p/ ツイッター >>> http://twitter.com/Ts_Neko ダウンロード >>> http://www.sage-p.com/freesoft.htm サポート掲示板 >>> http://www.sage-p.com/kg_ban09/z6037C8.cgi 東日本大震災 >>> http://www.sage-p.com/saigai.html メール >>> ts-neko◇sage-p.com ←◇を@に変えてください 緊急メールは件名に「うどんメール」を付けてください。 このメルマガの登録・解除 - http://www.mag2.com/m/0000083983.htm