̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ IT ニュース&コラム 2016/10/10 通巻723号 技術版 ソフトウェアデザイン館 Sage Plaisir 21  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄   レアケースの処理が最初に来る条件式を書くな - リーダブルコード(46) プログラムのソースコードを読むときは、まず、その概要が知りたくなります。 他の人が書いたコードを苦労しながら読んでいくとき、関数の中のいくつかの ブロックのうち、最後のブロックまで読んでようやく概要が理解できてしまうと、 それは最初に言ってくれよぅ、と文句を言いたくなりますね。 関数の最初によくあるのはガード節です。 しかし、関数の概要を知るときは、 ガード節を読み飛ばすことができます。 なぜならガード節は処理を実行させない ために例外的な条件が書かれているわけですから、始めに読む必要はありません。 読む必要がないコードを最初に書いて読ませることはよくないのですが、 正しく処理させるためには、どうしてもガード節は最初に書かざるを得ないため、 しょうがありません。 では、どのようにすればガード節であるかどうかを素早く判断し読み飛ばす ことができるでしょうか。 それは、条件式が真のときの処理の最後が エラーを返す return 文(や最後にジャンプする goto fin )であるかどうかで、 ガード節であるかどうかを判断できます。 if ( object_count <= 0 ) { CloseFile( file ); e = E_NO_OBJECT; // エラーコード return e; } 上記のコードの場合、条件式「object_count <= 0」を読む必要はありません。 if の { } の中の最後を読みます。 エラーコードを設定して return していますね。 よって、このコード全体がガード節の1つです。 どのようなコーディングルールであっても、{ } の中はパターンになっているので、 ガード節(エラーを返すコードの集まり)の最後は、すぐに判断できると思います。 ガード節の条件式を読むことで入力データを理解して、概要を理解できたことを 経験したことがあると思いますが、その概要よりも重要な概要があります。 それは、出力するデータが何かについて説明がある概要です。 プログラミング するときは、関数に入力データを与える作業が多くなりますが、その前に 呼び出す関数を選ぶ必要があります。 目的のデータを得ることができる関数が どれであるかを選ぶということは、目的のデータに一致するデータを出力する 関数を選ぶということであり、概要を知る目的は関数を選ぶためだからです。 よって、概要を知る段階では、入力データを理解する必要はありません。 そもそも、多くの場合、ガード節では例外的な条件しか情報を得られませんし。 条件式に関して、リーダブルコードの本には次の方針が書かれていますが、 あまり良い方針ではありません。  ・条件式は否定形よりも肯定形であるべき  ・単純な条件を先に書く  ・単純で関心を引く条件や目立つ条件を先に書く これらの方針は逆に、概要の理解が遅くなる原因になることがあります。 理由は簡単で、これらは条件式自体の理解がしやすいかどうかで判断する方針 であり、条件式によって分岐した先の処理が概要を知ることに適しているか どうかを判断する方針ではないからです。 因果関係がないんですね。 そもそもリーダブルコードにする理由は理解しやすくするためですから、  ・概要の理解がしやすい順になるような条件式を書く の方針を最優先にすべきです。 リーダブルコードの本の方針は、まさに木を 見て森を見ずな方針なので、優先度を下げた方針にすべきです。 条件式自体は、上記のガード節の説明でも書いたように、概要を知る上で読む 必要はありません。 よって、条件式を理解しやすくすることは、あまり重要では ありません。 また、同じ関数が何度も呼ばれる場合、呼ばれる順番に合わせて上から読める ようなコードであるほうが、理解しやすいです。 これらを、具体的なコードで見てみましょう。 1: if ( IsExistInCache( name ) ) { 2: file_list = GetFileListFromCache( name ); 3: } else { 4: find = FindFirstFileEx( name, FindExInfoStandard, &data, 5: FindExSearchNameMatch, NULL, 0 ); 6: while ( ! done ) { 7: if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) { 8: AddToFileList( file_list, data ); 9: } 10: done = ! FindNextFile( find, &data ); 11: } 12: AddFileListToCache( name, file_list ); 13: } 上記の 1行目の条件式をいきなり理解することは難しいでしょう。何のキャッシュ であるかをまだ理解していないからです。 ですからまずは読み飛ばしましょう。 2行目は、キャッシュから何かを取り出しているようです。 これも、何のキャッシュ であるかをまだ理解していないので読み飛ばすべきです。 しかし、本当に読み 飛ばしてもいいのかどうかは理解が不十分なときでは正しく判断できないかも しれません。 不安になってきました。 では、概要を理解することを優先した結果、条件式を肯定形から否定形に変えた コードを見てみましょう。 1: if ( ! IsExistInCache( name ) ) { 2: 3: find = FindFirstFileEx( name, FindExInfoStandard, &data, 4: FindExSearchNameMatch, NULL, 0 ); 5: while ( ! done ) { 6: if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) { 7: 8: AddToFileList( /*Set*/ file_list, data ); 9: } 10: done = ! FindNextFile( find, &data ); 11: } 12: AddFileListToCache( name, file_list ); 13: } else { 14: file_list = GetFileListFromCache( name ); 15: } 上記の 1行目の条件式をいきなり理解することは難しいでしょう。何のキャッシュ であるかをまだ理解していないからです。 ですからまずは読み飛ばしましょう。 次に、3行目に FindFirstFileEx があります。 これはフォルダーの中にあるファイルを 一覧することを開始する Win32 API 関数です。 続いて、while と if の条件式を 呼び飛ばすと、次は 8行目の AddToFileList です。 この関数は、独自関数で、 file_list に data を追加する関数だとします。 このようなコンテナに追加する 処理から、おそらく file_list が関数の出力に近いデータであることを推測できます。 処理の概要、この関数は結局何をしているか、については、ほどんどの場合、 出力するデータが何かを説明することですから、出力データがどれかを探していきます。 よって、file_list を出力することがこの関数の概要の候補になります。 次に、12行目で、name をキャッシュのキーとした file_list をキャッシュに入れて、 14行目でキャッシュから取り出していることを読みます。 もし、1行目の 条件式が逆なら、キャッシュと取り出すコードを読んでから、キャッシュに入れる コードを読むことになるので、処理の順番が逆になってしまい、理解しにくく なってしまいます。 12, 14行目でキャッシュに対する処理が理解できれば、1行目の条件式の理解は 簡単ですね。 いや、1行目の処理を理解したというより、これらのキャッシュに 関する処理が正しく動くように、つまり、12行目の処理の後に 14行目が 処理されるように合わせたコードが 1行目に書いてあるだけでした。 条件式は、処理の都合に合わせるため以外にもありますが、ほとんどの条件式は、 正しい出力を得るためにあるので、条件式を始めに理解することは難しいのです。 上記のコードより後のコードを読んで、file_list が最終的な出力データであると 分かったら、出力データ file_list の詳細である data の内容を調べましょう。 data を上方向に検索すると、条件式にヒットしました。 この条件式から、 data はディレクトリーに関する情報であることが分かります。条件式以外に ヒットすることもありますが、それでも概要は分かるでしょう。 ちなみに、このコードは、リーダブルコード(45) で説明した「メインの処理の前に 空行を空ける」という方針に従っています。 概要が理解するときに、空行を探して、 FindFirstFileEx と AddToFileList を先に読めばいいということが、よく理解している 書き手によってリード(導くことが)できています。 条件式の前に空行を入れるコードは(昔の私を含め)多くありますが、まず、条件式は 読み飛ばすものなので、条件式の前に空行を入れるコードはあまりよくないです。 同じ理由で、{ や } を新しい行にする BSDオールマンスタイルのコーディング ルールは、 条件式を強調したり、条件分岐したそれぞれのブロックの先頭を強制的に強調して しまうので、理解しにくくなります。 ループには概要の理解に重要な出力データを構成する集合とその要素が表現されて いることが多いため、ループの前に空行を入れると理解しやすくなりますが、 上記のコードのようにループより前で表現されていることもあります。 条件式が重要であることは、前提条件を踏まえなかったために正しい判断ができな かったという痛い思い出があったからだと思いますが、細かい条件であることも よくあります。 回りくどい説明をする IT システムの開発に関わる人が多いのは そのためですが、概要を知りたい一般のユーザーやコードを読む人にとっては、 細かいことはいいんです。 細かいことはシステムや代理人がやってくれるはず ですから。 参考: リーダブルコード - オライリージャパン ISBN-13: 978-4873115658 7.2 if/else ブロックの並び順 https://ja.wikipedia.org/wiki/字下げスタイル 注目ニュース 一覧 ◇ 講談社が Kindle Unlimited に抗議。書籍など全タイトルを一方的に配信停止。 http://japan.cnet.com/news/service/35089960/ … Google YouTube も著作権の価値を学んでほしい。 ◇ TypeScript 2.0正式版が登場。今後も開発者の生産性を加速していくと。 http://www.publickey1.jp/blog/16/typescript_20.html … WSH でも動く js ファイルが出力されるらしいが、デバッグできないのでは。 ◇ Windows 10ならマルウェアに感染しても大丈夫ってホント? http://www.itmedia.co.jp/enterprise/articles/1610/06/news022.html … ウィルス自体のパターン照合ではなく、ウィルスの動きを監視して情報漏えいを防止。 ◇ AI技術の啓蒙と課題解決に共同で取り組む AI団体 Partnership on AI を創設。 http://www.atmarkit.co.jp/ait/articles/1609/30/news087.html http://japan.zdnet.com/article/35089833/ … 論理的思考ではない AI に対してどのように信頼してもらえるか。 ◇ ローソン あきこちゃんは、なぜ「マジで! やば!」などの“女子高生”口調にならないのか。 http://www.itmedia.co.jp/news/articles/1609/30/news141.html … 人工知能に学習させる教材を作るときに、バイト中に使うきれいな言葉に変換しておく。 ◇ iPhoneのパスコード入力制限を突破してデータを抜き出す、NANDミラーリングは実現可能。 http://gigazine.net/news/20160920-nand-mirroring/ … パスワードを間違えることができる回数を厳しくしても、無効にして総当たり攻撃できてしまう。 ◇ 地デジ8局を見放題、全録テレビ見放題SIMプラン発売。 http://www.itmedia.co.jp/mobile/articles/1609/30/news108.html … テレビ視聴に関しては、月々の通信量制限がない。 ◇ 準天頂衛星のセンチ級測位補強サービス対応。2018年に誤差数センチの車用測位チップ実現へ。 http://eetimes.jp/ee/articles/1610/01/news026.html … GPS を強化する CLAS は、2018年からサービス開始。 ◇ 富士通のPC事業がレノボ傘下か。一部報道に、決定しているものではない。 http://japan.cnet.com/news/business/35090135/ … NECに続き富士通も。日本側はブランドを守りレノボは売り上げを得て、両者にメリット。 ◇ ファミコン中に死ぬって言ったら怒られるのは全然納得いかなかった。 http://www.itmedia.co.jp/pcuser/articles/1610/02/news009.html … 歪曲に表現するほうが死に至る状況を誤認識してしまう。 やはり親のTPOのため。 ソフトウェアデザイン館 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