上達したいのはプログラム?それとも?

増田→JavaBlackというところから補足。
僕はしがない業務エンジニアですけど、プログラマーとしての実力を考えると…並かしらん。でも、ここでいう実力ってのは様々な要素を含んでいるから、上級者である部分もあれば、初心者以下のゴミである部分もあるんですよね。であるならば、実力のあるエンジニアとは何か。僕としては、自分のやっていることをいかに抽象化して横展開できるか+対象についての正しい知識を学ぶ能力(と意志)があるかどうかにかかっていると思っています。
いわゆる「勘」というのはそういうところで培われた何かなんですな。

さて、それを踏まえて。

というのも、多くの人は計算機科学を学び、効率のよいアルゴリズムとデータ構造、美しい階層化・モジュール化されたプログラム、などを作るためにプログラミングするのではない。目の前の問題を解決するためにプログラミングを行うからだ。

プログラミング出来ない奴ちょっと来い

これはJavaBlackの人も言っているけど、目の前の問題を解決する手段として、「効率のよいアルゴリズムとデータ構造、美しい階層化・モジュール化されたプログラム」を用いたプログラミングを行うわけですよ。僕の目の前に今あるプログラム群。効率の悪いなんだかわからない設計と、救いようのないデータ構造、階層もなにもないコピペで量産されたモジュール化の欠片のないプログラム群。これで目の前の問題が解決するか。しません。デスマーチを経験したくなければ、目の前の問題を解決するための手段が正しいことをきちんと検証できる必要がありますな。

このような目の前の問題を解決したい人達が、わざわざ Lisp や Mozart など何の役に立つのか分からない言語を、根気よく勉強するのだろうか。(ちなみにLisp や Mozart は上記の書籍で実際に使われている言語である。)
目的は現在の問題を解決することであって、
新しいプログラミング言語を学ぶことや、プログラミングの種々の概念を獲得することではない。

プログラミング出来ない奴ちょっと来い

目の前の問題を解決するための最適な手段を提案せよ、と言われた時に「HOSTでCOBOLで作ればいいと思いまーす!」とか言っちゃったとしたらどうなるでしょうか。そんな極端な話はあまりないかと思いますが、ここで言われていることの本質はそういうことですよね。もちろん、あえてLispを使えるようにせよ、とは思いませんが、世の中にどういうシステムがあり、どういう思想で言語が誕生しているかを知っていることは、自分の知識を抽象化して一般化するためには非常に重要です。かく言う僕はノマド…じゃなくてモナドあたりで概念学習が止まっていることが我ながらあかんなあと思うところ。

今回はそのような”純粋にプログラミングを楽しんでいる人”に向けた文章でない。
現実の問題をプログラミングを用いて取り組んでいる人に向けて書いた文章だ。
そのような人の中で、なかなかプログラミングが上達しないという人に向けた文章である。

プログラミング出来ない奴ちょっと来い

解決するためのアプローチが正しいかを判別できないと、正規表現を書けば5分で終わる仕事に1週間かかってしまうこともあるわけなので、そういう前提知識をいかにして作るかということが最終的には「プログラミングが上達する」ことに繋がるということだけは押さえておきたいところ。

1. 初心者レベル
・プログラミング歴 半年未満
・使えるプログラミング言語は一つだけ
ただし以下のことは出来ない。
・500行以上のコードが書けない
・エラーが出た時の対処方法が分からない
・写経は出来るが、自分でプログラムが書けない

プログラミング出来ない奴ちょっと来い

僕最近流行っているらしい「写経」という概念がよくわからんのだけど…
それはともかく、500行以上という基準がそもそもよくわからない。なぞるだけなら行数は関係ないだろ…
むしろ、500行以上のコードが読めない、ということか。

2. 中級者レベル
・プログラミング歴 半年 〜 3年
・1つ以上のプログラミング言語は使える
オブジェクト指向は理解している
ただし以下に当てはまる。
・自分が制作しているアプリケーション向けに "実用的なフレームワークやライブラリ" を書けない
・1万行以上のコードだとスパゲッティコードになり、保守不能になる
・重複するコードが多く存在する
・適切なサブルーチン化できない

プログラミング出来ない奴ちょっと来い

展開が早い。3年でこのレベルのプログラマーになってくれるのであれば万々歳である。オブジェクト指向を理解してくれたら超助かっちゃう。理解だよ理解。
なのにフレームワークを書けない?1万行でスパゲッティ?(設計できないの?)オブジェクト指向を理解しているのに重複?サブルーチン?

3. 上級者レベル
・プログラミング歴 3 年以上
・現実の問題に対して適切なデータ構造とアルゴリズムを選択できる
・抽象化について理解し、可変部分と不変部分を考慮した設計ができる

プログラミング出来ない奴ちょっと来い

困った。「現実の問題に対して適切なデータ構造とアルゴリズムを選択できる」というのはそれを学習した結果として中級者レベルができなくてはならないことだと思う。でなければ、現実の問題を解決するためのプログラムなど一生書けない。上級者というなら「新たに編み出す」くらいは必要だろう。また、抽象化について理解していない中級者がオブジェクト指向を理解できるか?と思うと抽象化の理解はここでは遅い。

というわけで、そもそものレベル設定がいまいち理解不能であります。
その上で。

プログラミングも同様に頭を使うのではなく、こうしたい時はこう書く、という反射神経を育てなければならない。

プログラミング出来ない奴ちょっと来い

うーん、僕は反射神経でプログラムをしたことはないなあ。ということは、初心者だったことは一度もないのかもしれないけど。

このままでは抽象的すぎるので、このような "データベース" や "考える習慣" を自分の中に作るための具体的な指針を以下に挙げる。

1. エラーをたくさん出す
2. デバックの仕方を覚える
3. 小さく動かして確かめる
4. Google を使い倒す

プログラミング出来ない奴ちょっと来い

僕の経験上、エラーは出すものではなく出るものなので、たくさん出すことを指針にしちゃダメよ。エラーをたくさん出すことでルールが染み付くか。つかない。対症療法を覚えるだけだと思う。「とりあえずおまじない的なキャスト」が基本形になったプログラマーを見たことがありますか?
デバック(デバッグのことだよね)の仕方を覚えるのは重要だけど、それ以上に、何をすべきかという理屈を考えられるようになることが重要。デバッグというのは闇雲にやっても仕方ない。printfデバッグだろうがデバッガ使うだろうがアサーションだの単体テストだのまあなんでもいいんだけど、適切なデバッグ方法を選択できるためにはただ闇雲にやることではダメなんだよね。僕は昔printfデバッグくらいしか有効な手段無いだろ〜的な現場でまさにそうやっていたことがあるけれども、今だったらそれはデバッガ(というかIDE上でのデバッグ実行)でよいだろうし、そうじゃないものはそもそもデバッグログ吐いておけよと思う。

これは無益な時間を過ごさないためにも本当に重要な要素なので、面倒くさがらずに開発環境を整えや方法論をマスターすること。

プログラミング出来ない奴ちょっと来い

とは書いているからそれでいいんだけど、なら前段の話はいらねー。

また、小さく動かすのはよいんだけど、小さく作って小さく確かめ部品化というのは必ずしもよくない。ちゃんと設計した結果少し大きいものになることだってあるわけだし、目先の問題を解決するための方法論として、OSを作るようなモジュール化は必要ではないし。
あと、Google先生初心者に本当に必要なことは何も教えてくれないよ。

しがない業務エンジニアの言うことですが。

じゃあ、どうすれば目的を解決するためのプログラムが上達するか。しるか。ごめん、そうじゃないね。
まず、そのためには目標となるプログラムのレベルを設定しなければならない。仮に、僕の今やっている現場で最低限求められるレベルであればどうすれば上達するか。これは答えではないけれども、ひたすら書いて、同時にひたすら勉強するべきだと思う。勉強だけだと身につかないのは確かだけど、ひたすら書いてもやっていることしか学習できない。僕もたくさんの本を読んだものだけど、そこで書かれていることの大半は使ったことがないものだ。でも、それを知っていることによって回避できたこともたくさんある。トライ・アンド・エラーで身につくものと身につかないものがある。まずやってみる、というのはプログラマーにとっての重要な資質だと思うけど、「まず」の部分をいかに早く終わらせて体系的な学習に移れるかが上達の肝だと思う。そういう意味では、お作法というのは最初に叩きこむものではなく、並行して覚えていくことで、そう考えると写経と言われているものにも意味はなくはないかもしれない(すぐ終わらせるという意味で)。という点では参考にすべき書籍はコードのsampleが見やすくて、間違いがないもの。そこで書き写すことに失敗しているようではそもそもお話にならないとは思うし。あとは正しく調べる力を身につけることかな。そのためにはAPIの一つ一つを知る必要はないけれども、大体どういう品揃えがどこにある、というレベルでは覚えてないと時間がかかってしかたがないと思う。一般的に誤解されている点ではあるけれども、リファレンスを調べることのできる力、というのはかなり高等技術なんだよ。どこを調べたらいいかわからない、たどり着いたけど何が書いてあるかわからない、という人が結構多い。知識を外部化できるためには、自分自身が適切なインデックスを保持しておかねばならないという事実を軽視している人が多すぎる。「調べればわかる」と簡単に言ってしまうのは何も知らない人の言でしかないんだよね。

なんかさ、「絵がうまく書けない」って言っている人に「じゃあまず油絵書いてみようか!」って言ってしまっているようにも思えるわけで、本当にプログラムが出来るようになりたかったら前提を疎かにしてはいけないし、とりあえず目の前のことが解決すればい〜やレベルの人はそもそもプログラムが出来ないと悩まない(あるいは悩む資格が無い)。