悪態のプログラマ -9ページ目

悪態のプログラマ

とある職業プログラマの悪態を綴る。
入門書が書かないプログラミングのための知識、会社の研修が教えないシステム開発業界の裏話は、新人プログラマや、これからプログラマを目指す人たちへのメッセージでもある。

情報過多といわれる昨今、自分に必要な情報を見極めるだけでも一苦労である。私も日々発信される IT 関連のフィード をチェックしては、目ぼしいものをブックマークしているが、それだけでも結構な手間が掛かる。

しかし、こうした情報は、ただ集めているだけでは役に立たない。特に、システム開発において、全く新しい技術を採用しようという場合には、ネット等で得られた情報だけでは、導入を決断できないことも多い。

「この技術を採用すれば簡単に開発できるだろう」と思っても、実際にやってみると、色々な問題があった、ということがよくあるからだ。特定の技術が、自分の問題解決に役立つかどうかを判断するためには、それを実際に体験してみなければならないのである。


沢山の情報を仕入れていると、実際に経験していないことでも、なんとなく分かったような気がするものだ。特に、ネットで大量に情報が得られる現代においては、そうした傾向が強くなりがちなのではないだろうか。しかし、経験の不足を情報量でカバーすることはできない。

「情報は検索する時代」である。その人が「いかに多くの情報を持っているか」ということよりも、「いかに多くの経験を積んでいるか」ということの方が重視されるだろう。情報を集めるだけで満足するのではなく、経験を積むための時間も日常的に確保しておきたいものである。






■関連記事
プログラミングは体で覚えろ
頭を使って探せ



低度情報化社会 Ultra Law-level Information Society
コモエスタ 坂本
光文社
売り上げランキング: 10935
おすすめ度の平均: 2.5
2 現象を定義したことには評価
3 題名通り


ソクラテスの弁明・クリトン
プラトン 久保 勉
岩波書店
売り上げランキング: 38214
おすすめ度の平均: 4.5
5 ソクラテスはボクらです。
5 ソクラテスの入門として最適
5 何故ソクラテスは死んだのか
小学生の頃、「漢字練習帳」にひたすら同じ漢字を書かされて、こんなことをしてなんの役に立つのか、と思ったものだ。また、電卓というものがあるのに、どうして暗算や筆算をさせるのか、と思ったこともある。

実際、大人になってみると、IME のおかげで漢字を書くことは少ないし、Excel のおかげで難しい計算をすることもほとんどない。

では、学校の勉強なんて何の役にも立たなかったのかと問われれば、そんなこともないとも思う。


大人の世界では、とにかく結果を出すことが重要だ。なるべく効率よく「答え」が得られる方法を選ぶということは間違いではない。しかし、子供が勉強する目的は、答えを得ることではない(なぜなら、先生は答えを知っているのだから)。本来の目的は「脳を育てる」ことだろう。

例えば、漢字の練習も、野球のバッティング練習で行われる「素振り」と同じようなものだと思えば、その必要性が見えてくる。単に漢字を覚えるというだけではなく、椅子に座る時の姿勢や、鉛筆の使い方を身につけるというような効果だってあるだろう。

あるいは、算数については、「答えの求め方」が理解できればいいのであって、計算をする作業自体は重要ではないと考える人もいるかもしれない。しかし、それも「答えを出すこと」に着目した大人の理屈だ。自分で計算するという行為が脳を鍛えるトレーニングになっているとすれば、それもまた必要なことである(当然、「答えの求め方」を学ぶことも重要なのだが、それとは別の話として、である)。


もちろん、勉強が必要なのは子供だけではない。

今や、プログラミングの世界も、オープンソース等を利用して多くの作業が省力化できる時代である。フレームワークだとか、ライブラリだとか、便利なものが簡単に手に入り、自分でプログラムを書かなくてもよい部分がどんどん増えてきた。

ソフトウェアを作ることだけを考えれば、既存のものを探してきて組み合わせ、効率化するのはよいことだ。そのために、個々のフレームワークの特徴や、ライブラリの使い方を学ぶことは大切だろう。しかし、プログラマの脳を育てるという点では、それだけでは足りない。

このブログでは繰り返し書いていることだが、プログラマには、とにかくプログラミングの経験が必要だ。既にある機能を自分で書くということは、無駄に見えるかもしれないが、トレーニングとしては意味がある。効率が重視される実務の中で、個人的にトレーニングをするということは難しいだろう。しかし、このような時代、自分の時間を割いてでもそういった勉強をしなければ、プログラマとしての「脳力」は育たないだろう。


車や電車、あるいはエレベータなどの移動手段が普及して、人間は効率よく移動できるようになった。一方で、運動不足によって体を悪くする人が増えている。健康を保つためには、ただ仕事をしているだけでは駄目で、あえて時間を割いて「体を動かすために体を動かす」ことも必要になってきている。

同じ様に、コンピュータに頼ることで、人間は勉強不足になってはいないだろうか? 近年のコンピュータの普及と「脳トレ」ブームを見るにつけ、「頭を使うために頭を使う」時代の到来を感じてしまうのである。







■関連記事
簡単フレームワーク・プログラミングの罠
プログラミングは体で覚えろ



脳を鍛えるパソコンドリル ~脳力トレーナー特別版が入ってる~
川島 隆太
インプレス
売り上げランキング: 180203


C++トレーニングブック―これから始める人のC++プログラミング練習帳
掌田 津耶乃
ソーテック社
売り上げランキング: 293884
おすすめ度の平均: 4.0
3 『C++』の「トレーニング」としては今二つ…ですが
5 基本ですね


@IT の「キミのコードが汚い理由 」という記事を読んだ(yasuhoの隠れ家 さん経由)。

この記事には、テニスのスコアをつけるための2つの Java コード紹介がされている。「幼稚なスタイル」で書かれたとされる「リスト1」と、それを「クリーン」に書き直したとされる「リスト2」である。記事の中では、これらは単なる「前フリ」程度の扱いなのだが、「読者指向プログラミング 」ということを考える上で、おもしろい題材なので、少し細かく見てみようと思う。

元記事の趣旨に対しては「重箱の隅」的な指摘になるかと思うが、それは承知の上で、別のテーマとして読んでいただきたい。

まず、元のソースコードは画像で公開されているので、テキストにしたものを以下に示しておこう。

リスト1

public class SetScorer
{
private int[] games = {0, 0};

public void gameWon(int i){
games[i-1]++;
}

public String getSetScore(){
if ( games[0] < 6 && games[1] < 6) {
if(games[0] > games[1]){
return "Player1 leads " + games[0] + " - " + games[1];
} else if (games[1] > games[0]) {
return "Player2 leads " + games[1] + " - " + games[0];
} else {
return "Set is tied at " + games[1];
}
}
if (games[0] == 6 && games[1] < 5) {
return "Player1 wins the set " + games[0] + " - " +
games[1];
}
if (games[1] == 6 && games[0] < 5) {
return "Player2 wins the set " + games[1] + " - " +
games[0];
}
if (games[0] == 6 && games[1] == 5) {
return "Player1 leads 6 - 5";
}
if (games[1] == 6 && games[0] == 5) {
return "Player2 leads 6 - 5";
}
if (games[0] == 6 && games[1] == 6) {
return "Set is tied at 6 games";
}
if (games[0] == 7) {
return "Player1 wins the set 7 - " + games[1];
}
return "Player2 wins the set 7 - " + games[0];
}

}

リスト2

public class SetScorer {
private int[] gamesWon = {0, 0};

public void gameWon(int player){
gamesWon[player-1]++;
}

public String getSetScore(){
int leader = gamesWon[0] > gamesWon[1] ? 1 : 2;
int leadersGames = gamesWon[leader - 1];
int opponentsGames = gamesWon[leader == 1 ? 1 : 0];
String setScoreMessage = null;
if ((gamesWon[0] < 6 && gamesWon[1] < 6)
|| (leadersGames == 6 && opponentsGames == 5)) {
setScoreMessage = "Player" + leader + " leads " +
leadersGames + " - " + opponentsGames;
} else if (gamesWon[0] == gamesWon[1]) {
setScoreMessage = "Set is tied at " +
leadersGames;
} else if (( leadersGames - opponentsGames >= 2)
|| leadersGames == 7) {
setScoreMessage = "Player" + leader +
" wins the set " + leadersGames + " - " +
opponentsGames;
}
return setScoreMessage;
}
}


yasuhoの隠れ家さんも指摘されているように、リスト1の方が分かりやすいと感じる人も多いのではないだろうか。確かに、リスト2は数式的には「整理」はされているのだが、読みやすくはないように思える。

いくつか、その原因を考えてみた。


1. レイアウトへの配慮がない


空行挿入、改行位置、インデントなど、レイアウトについての配慮が甘く、全体的に、目で追いにくい書き方になっている。もっとも、これは Web 掲載上の都合かもしれない。



2. 変数の扱い方の問題


リスト2では、リスト1より変数が多くなっている。ここでは「優勢なプレイヤー」と「劣勢なプレイヤー」の勝ち数を明確にする意図があり、それ自体は悪いことではない。

しかし、せっかく配列の内容を leaderGames、opponentGames という変数に入れ直しているのに、その後も元の配列を参照し続けているので、逆効果になっている部分がある。例えば、「gameWon[0] < 6 && gameWon[1] < 6」は単に「leaderGames < 6」でいいし、「gamesWon[0] == gamesWon[1]」も「leaderGames == opponentGames」でいい。

また、2人のプレイヤーを数値で区別しているのだが、「0 と 1 で区別する場合」と「1 と 2 で区別する場合」が混在していて分かりにくい。そもそも、プレイヤーが2人しかいないのに、配列にする必要があるだろうか? このあたりは、リスト1の書き方に引きずられている印象だ(比較しやすいように意図的にそうしているのかもしれないが)。

更に細かいことを言えば、"set" で始まる変数名があるが、これは一見、関数(setter)のように見えるので、避けたほうがいいだろう。



3. 直感的表現の消失


「幼稚なスタイル」のコードは、幼稚であるが故に読者にとって「直感的」であることも多い。逆に、コードを「整理」すると、その代償として、素直な表現が失われてしまうことがあるのだ。

例えば、リスト1の if 文は処理としては冗長なのだが、条件が馬鹿正直に書かれているので、逆に分かりやすい。

また、return しているメッセージの文字列も、リスト1ではやはり馬鹿正直に書かれているため、「文」として意味を取りやすい。コード内の文字列は、往々にして、そこで何が行われているのかを伝えてくれる。いわば「コメント的な効果」を持っているのだ。リスト2のメッセージは変数で分断されている箇所が多く、この効果が薄れている。

もちろん、私もリスト1のような「幼稚な」書き方が良いなどと言うつもりはない。効率や汎用性、あるいは「他の角度から見た読みやすさ」のために、こうした直感的な表現が犠牲になることは、宿命だろう。しかし、そうした表現の効果について、知っておくということは必要である。「読者指向プログラミング」のテクニックのひとつになりうるからだ(※)



4. 読者層が想定外


これは読者側の問題になるのだが、英語が苦手な読者にとって、変数名が直感的に理解できないという問題もある。個人的には、"leader" や "opponent" といった単語が「優勢なプレイヤー」とその「対戦相手」であると理解するために、変数に代入している式を解読する必要があった。つまり、変数名が「a」や「b」でも同じだったわけだ。

多くのプログラミング言語で、ソースコードはアルファベットと数字と記号で書くことになっている。このため、日本人向けのコードには、より多くのコメントが必要になる(漢字という「表意文字」の効果は絶大である)。しかし、リスト2の作者は日本の読者を想定していなかっただろう。



こうした点を考慮しながら、リスト2を修正してみよう。といっても、全ての問題を同時に解決することはできない。全体のバランスを考えた「落とし所」を見極めることが必要だ。

リスト3

public class SetScorer
{
private int[] gamesWon = {0, 0};

public void gameWon(int player){
gamesWon[player-1]++;
}

public String getSetScore(){

// どっちが優勢か
int leader = gamesWon[0] > gamesWon[1] ? 0 : 1;
int leadersGames = gamesWon[leader];
int opponentsGames = gamesWon[leader == 0 ? 1 : 0];

String scoreMessage = null;
if ((leadersGames < 6) || (leadersGames == 6 && opponentsGames == 5)) {
// 試合途中
scoreMessage = "Player" + (leader + 1) + " leads "
+ leadersGames + " - " + opponentsGames;
} else if (leadersGames == opponentsGames) {
// 同点
scoreMessage = "Set is tied at " + leadersGames;
} else if ((leadersGames - opponentsGames >= 2) || leadersGames == 7) {
// 試合終了
scoreMessage = "Player" + (leader + 1) + " wins the set "
+ leadersGames + " - " + opponentsGames;
}

return scoreMessage;
}
}

読みやすさという点において、いくらか良くなっていると思うが、どうだろうか。もちろん、コードの書き方に「正解」はない。私が自分でゼロから書いたとしたら、また違ったコードになるだろう。「読者指向プログラミング」について考えるには、適度な題材である。プログラマの方は、自分ならどう書くか、実際にやってみてはいかがだろうか。






※例えば、これは何をする関数だろうか?

 double func(double r){ return r * 6.28; }

では、これは?

 double func(double r){ return r * 2.0 * 3.14; }

「3.14」と書けば「円周率」だと分かるため理解しやすい。つまり、これらは半径を r とする円周の長さを求める関数である。前者の方が数式としては「整理」されており、効率もよいかもしれない。しかし、後者の方が読者指向である。



■関連記事
読者指向プログラミング
もっとコメント論 ~その1~ コメントとは何か
インデントについて考える 前編
誰のためのコード?
まずは丁寧なプログラミングを
プログラムは二度書け
慣例的コーディングルール



Code Complete第2版〈上〉―完全なプログラミングを目指して
スティーブ マコネル Steve McConnell クイープ
日経BPソフトプレス
売り上げランキング: 2788
おすすめ度の平均: 5.0
5 これは理解できないとヤバイです。
5 我流プログラミングから抜け出す意思のあるひとへ
5 人に勧めたくなる本


続 直観でわかる数学
続 直観でわかる数学
posted with amazlet on 07.01.21
畑村 洋太郎
岩波書店
売り上げランキング: 86453
おすすめ度の平均: 4.0
2 自分で考える覚悟があるか
4 解説と算数授業の批判
5 目からウロコの算数

「叱られて伸びるタイプの人」と「褒められて伸びるタイプの人」がいるという。プログラマだって同じだろう。しかし、プログラミングという仕事では、あまり褒められることはないような気がする。

少なくとも、私はコンパイラに褒められたことはない。どんなに効率的なコードを書こうが、美しいコードを書こうが、何も言ってくれない。そのくせ、ちょっとでも間違えると、文句(警告)を言われるか、駄目出し(エラー出力)されるかだ。

ソースコードをチェックするツールもあるが、同じようなものだ。「良い評価」はしてくれない。そのくせ、全てのバグを教えてくれるわけでもない。自分が気に入らないところだけを指摘してくるだけだ(※1)。


では、人間が褒めてくれるかというと、そんなこともない。開発の現場で、人間がソースコードをレビューをする場合、その目的は、問題点を見つけ出すことである。当然、プログラマは悪い所を指摘されるばかりになる。

もちろん、プロジェクトによっては、教育(OJT)のためにスケジュールに「余裕」を持たせてある場合あるだろう。しかし、そうでない場合、プログラマの教育・指導よりも生産物の品質の確保に重きが置かれてしまうのは当然だ。

プログラマはバグを作れば叱られる。叱られなくても自責の念にかられるだろう。しかし、仕様の通りにバグがないコードを書いたとしても、特に褒められたりはしない。そんなのは当り前のことだからだ。

そう思うと、「褒められて伸びるタイプの人」にとって、プログラマという仕事は厳しいものかもしれない。


そういう私も、今やプログラマを指導する立場であるが、品質確保に追われて、いつも「悪いコード」を探してばかりである。あらためて「良いコードを探す」という行為について考えると、新鮮に感じるほどだ。

私がいつも悪態をついている原因は、実はそんなところにあるのかもしれない。

プログラマを褒めるためだけではなく、自分が仕事を楽しむためにも、意識してソースコードの「よかった探し」をやってみてもいいかもしれない(※2)。






※1
JUnit に代表される自動テストツールは、テストにエラーがなければインジケータが緑色になる(エラーがあれば赤だ)。この緑色を「褒めている」と捉えることはできる。確かに、この緑が出ると気持ちいい。

※2
良いコードとはこういうものだ、ということをはっきり認識するためにも重要だろう。例えば、既存のコードの中から新しいデザインパターン を見つけようと思えば、このような視点は必須である。



パターン指向リファクタリング入門~ソフトウエア設計を改善する27の作法
ジョシュア・ケリーエブスキー 小黒 直樹 村上 歴 高橋 一成 越智 典子
日経BP社
売り上げランキング: 29696
おすすめ度の平均: 5.0
5 解説が丁寧
5 デザインパターンに違和感を抱いてる人にはオススメ
5 シンプルで、読みやすいコードを。


1分間マネジャー―何を示し、どう褒め、どう叱るか!
K.ブランチャード S.ジョンソン 小林 薫
ダイヤモンド社
売り上げランキング: 9439
おすすめ度の平均: 4.5
4 もっとも簡単なマネジメント本
5 課題の共有・目標管理
5 有能な管理者になるためには?


年明け早々の仕事はバグの対応だった。まぁ、受け入れテストをしている顧客が年末に送ってきていたバグ報告メールを、年が明けてから受信したというだけなのだが。

「幸先悪いな」
「毎年、同じこと言ってません?」

・・・そうだったかもしれない。

そもそも、ソフトウェア開発の仕事をしていて、「幸先がよい」と感じることがあるとしたらどんなことだろう。「仕事が早く片付いた」とか「いいプログラムが書けた」といった程度では、そこまでは感じないだろう。

例えば、「これから作ろうとしているシステムにぴったりのフレームワークが、ちょうどいいタイミングでリリースされた」とかいったことなら、ラッキーだと思うかもしれない。しかし、そんなことは滅多になさそうだ(というか、滅多にないからこそラッキーなのだ)。

突如として訪れる幸せは、突如として訪れる不幸に比べて少ないのだろう。予期せずバグが見つかったり、予期せずサーバーがダウンしたりするのは日常茶飯事だが、予期せずバグが直ったりはしないし、予期せずサーバーが高速化したりもしない。

だとすると、年始に「幸先が悪い」と感じる確率は、「幸先が良い」と感じる確率よりも高いということになる(もっとも、「良くも悪くもない」というのが一番多いのかもしれないが)。

まぁ、今年もいつも通りのスタートということだ。いつも通り、頑張って行ってみよう。


おまけ。

以前、「プログラマの神頼み 」という記事で「電電明神」を紹介したが、他にも IT の神様は御座した。神戸にある瓦屋山正法寺 の「旗振大明神 」である。このお寺のあたりは、かつて旗振り通信の中継に使われた旗振り山だったということで、情報・通信の守護神とされているそうである(※)。

あと、こちらはご存知の方も多いと思うが、東京の神田明神 には「IT情報安全守護」というのがある(守護・御守のページ を参照)。「秋葉原電気街を氏子にもつ神田神社独自のコンピューター、携帯電話のお守り」だそうだ。「しごとのおまもり」として、大国様御守、IT情報安全守護、名刺入れの3点セットもある。

初詣には遅い情報で恐縮だが、お近くの方はどうぞ。





※旗振り通信
江戸中期から大正前期には、米相場の情報を山から山へ手旗信号や火振り信号で伝えていたそうだ。大正6年頃までは最速の通信方法だった。旗振り通信については、柴田昭彦氏の「旗振り通信ものがたり 」というページに詳しい。



■関連記事
プログラマの神頼み




旗振り山
旗振り山
posted with amazlet on 07.01.07
柴田 昭彦
ナカニシヤ出版
売り上げランキング: 375916


IT時代の宗教を考える
IT時代の宗教を考える
posted with amazlet on 07.01.07
井上 順孝
中外日報社
売り上げランキング: 346819