わさっきhb

大学(教育研究)とか ,親馬鹿とか,和歌山とか,とか,とか.

プログラミングのセオリー,なのだけど

プログラミングのセオリー

プログラミングのセオリー

副題の「プログラミング価値を高める“定石”を学ぶ」について,なるほどうまくまとめられているなあと感じました.
ある程度プログラミングができると自認していて,一歩上を目指すという人に,おすすめしたい本です.
状態遷移図を描いてからコードを書く話(pp.128-134),正規表現に慣れてしまうと,ああそうでしたそうでしたと納得です.
以下,ネタばれを含みます.
1〜2年間程度のプログラミング経験の,自分の学科の学生には,残念ながら薦められません.小さなところで配慮不十分です.

  • コードサンプルの言語はC言語Java.ほんの少しだけ,C#があります.学習という観点では,一つの言語に集中するか,どうしても複数にするなら,C言語の部とJavaの部に分けてほしいものです.
  • C言語のコード例でも,「//」によるコメントを使用していますが,教育上よくありません.
  • main関数の戻り値(p.38)を定数で表したい場合は,独自に定義するよりも,stdlib.hで定義されているEXIT_SUCCESS,EXIT_FAILUREを使うことを検討すべきでしょう.
  • インクリメント演算子の評価順序について検討するなら,『b = a++;』(p.90)と『b = (a++);』(同)だけでなく,b = ++a;も挙げるべきでしょう.また,インクリメントだけの文(結果を他の変数などに代入したりしない場合)は,「変数++;」が「++変数;」よりも好まれることも書くべきかと思います.
  • 『average = (double)sum / n;では優先順位がわかりにくいので,average = sum / (double)n;と記述したほうがよいでしょう.sumとnのどちらかをdouble型にキャストすれば,演算がdouble型で行われ,演算結果もdouble型になります.後ろにあるnをキャストすれば,見た目にも,除算よりキャストが優先されることが明確になるでしょう.』(p.91)について,見た目や明確さを求めるのであれば,average = (double)sum / (double)n;とも比較しないといけません.
  • p.118で,0と反対の意味を持たせる整数に,-1を使用していますが,エラー判定ならともかく,「論理演算子の適用により,真と評価される値は1になる」というCのルールのもとでは,不自然です*1.それと,プログラミング対象にもよるのでしょうが,複数のフラグを一つの変数に格納し*2,ビット演算子の&,|,^で一部のビットを操作するという例も,知っておきたいものです.
  • すぐ上のこととも関連しますが,『標準ライブラリ関数では,0を正常終了とし,0以外の値をエラー終了とするのが一般的です』(p.138)って,そんなことないでしょう.正の値が返る場合にも,適切か否かを確認する(ようコードを書く)べきです.
  • p.133やp.210のコード例で,定数をずらずらと#defineで定義していますが,enum(列挙型)を使うべきです*3.p.210について,列挙の最後の定数は,-1にするより,他のどの定数よりも大きな値とするほうが自然です.

ここまで,よろしくないところを列挙してきましたが,当日記でも独りよがりなプログラミングアドバイスを書いていて,後になって顔を真っ赤にすることがあります.思いつきですが,プログラミングスキルアップのtips集を作るには,「三人寄れば文殊の知恵」*4を活用するのがよさそうです.

*1:とはいえ,論理値を格納する変数同士の比較をしない限りは,1だろうが-1だろうが,12345だろうが,差支えはないのですが.

*2:そういう変数はたいてい,「なになに_flags」という名前になります.

*3:ついでに,pp.133-134のようなコードでは,関数の中でenum型と列挙定数を定義し,定数を関数内に「閉じ込める」のも定石と言えるでしょう.

*4:ふと,「集合知」を連想しました…google:集合知 文殊の知恵.へえ.