プログラミングどうやって学ぶといい?(編集中)

1行まとめ

具体的すぎる目標をつくらないとむり。受験的網羅的勉強とは真逆の方向。

背景

自分は去年の春くらいに初めてプログラミングというものに触れた。そこから一年が経って、大した仕事はしていないものの一応コードを書いてお金をもらえることが出来ている。この一年を今振り返ってみると、一年の3/4くらいはプログラミングについて何も理解していないままだった。しかし、後半の1/4で巻き返してだいぶ理解が進んだように思えたので、その感覚を書いておいてみる。 ただ、結局その1/4はバイトにしてみようと思って頑張った、バイトになってから頑張ったっていうのが殆どなので、必要に迫られてやるっていう状況作りは前提として、どういう取り組みをすればしっかりと理解しつつ進めていけるかという具体的なところを書き連ねて行く。

むずかしさ

プログラミングは、要するにパソコンに指示をして思い通りに動かそうということに尽きる。ただ、思い通りに動かせる何かを渡されたとして、いい活用の方法を知らなければどうしようもない。この点で、プログラミングの文法を、動かしたいものもない状態でがむしゃらに学ぶというのは殆ど意味がない、と思う。ここでいう文法を学ぶというのは、いわゆるプログラミングの入門書を隅から隅まで熟読してゴリゴリと勉強することである。もちろん文法がどんなものかを知ることは大切だが、自分が今何をしたくてどんなものを学んでいるのかという自覚もなくそういうことをしていては、いずれ方向を見失ってプログラミングを学ぶのをやめてしまうと思う。 例えるなら、プログラミングの入門書ばかり読んでいるのは、数学の教科書ばかりを読んでいて問題を解こうとしない、TOEICの問題集を解いてばかりいて他に英語に触れていない、みたいな感じである。もちろん、それらが悪いということではないけれど、数学のテストで点を取るため、洋書を読むため、という目的を掲げていた場合ならば、その行動はすこし遠回りになるのは明らかと思う。逆に言えば、プログラミングに何でもいいから触れてみたいだけで、続かなくても構わないということであれば、入門書ばかり読んでいても構わないということだ。 ただ、ここが難しいところで、プログラミングとはなにかというのを何も知らない状態でそういう考え(自分が今何をしたくてどんなものを学んでいるのかという自覚をもつ)にいたるのは殆ど不可能なので、とりあえずどこかで壁にガンッてぶつかる必要はある。というのも、プログラミングとはパソコンを思い通りに動かすための道具なんだけど、そもそもはじめは誰もパソコンがどうやって動いているか、プログラミング言語はそれのどの辺りにどう関わっているのかが分かっていないからだ。何も知らなさすぎて、手がかりがない。 例えば自分の場合は、Pythonにはじめて触れてみたときに、例えばこうやって書いたら二つの数字の足し算が計算できるという事実は分かったけれども、

  def add(a, b):
    return a + b
  
その裏でなにをしているのかが全く分からなかったので途中で読む気をなくして、ゼロからコンピュータに関する知識を遠回りながら身につける方向に走った。その過程で、自分の場合のとりあえずの目的は、パソコンってなんで動いてんの?っていうところを知りたかったっぽいっていうのが分かった。なので、その後はそもそもプログラミングだけの話だけではなくなるのだけど、割とスムーズに目的を叶えようと動くことができた。そうして、裏でコンピュータが結局のところなにをやっているのかというところをある程度自分が納得するまで見てきた上で、長い遠回りをしてもう一度、今度は目的をバイト獲得にして、明確にプログラミング言語を学んでいったところ、結構うまくいっている。(まあただ、Pythonはコンパイラ言語じゃないのでそこらへん素直じゃなくて、そういう意味では初心者向きじゃなさそう) そもそもプログラミング学ぶのにそんな自覚を持つ必要あるのか?というところだけれど、ここでは、プログラミングに途中で挫折してやめてしまうことなく自分の新たなスキルとして身につけたい場合、っていう条件付けをした上での話です。

具体的なところ

で、前提として、そういう明確な目的を持てれば結局うまく行くんだけど、この下ではその中で感じた、はじめからこうやっておけばよかったじゃんと思ったところをメモしておく。

すべて関数にして書けばいい

自分は基本的に全部Pythonを書いてるので、Pythonの話をする。入門書の類は、対話的環境を用意してその中でプログラミング言語の色々な機能を試して行くっていうやり方が非常に多いけど、個人的にあれはよくないと思った。なぜかというと、対話的な環境でこまごまとやっていると最終的な目標が見えにくくなるから。自分のいまやっていることがどこで使われてどう結びついて行くんだろうっていうところが非常にあいまいなまま進められて行く。はじめから、"なになにを達成するため"にこういうものを書きました、この中身はこうなっています。中身についてそれぞれ説明しましょう、これはリストというもので、複数の値を格納しておけるものです・・・。みたいな感じにしてくれたらいいのに。このなになにを達成するためにというところが非常に重要で、そこをあいまいにしたまま文法を解説している本は、目的がなんなのかわかりづらくて困る。もちろん文法を詳しく解説した本も必要だが、世の中の入門書はそればっかりでおもしろくない。 全て関数にして書けばいいっていうのは、関数にしたら目的を考えなくてはならなくなるから。つまり、引数はなにで戻り値はこういう値にする、そうしたいから関数の中身はこうやって書いて行くよね、ということ。文法をはじめから終わりまで薄くさらう入門書の類で一番困るのはここで、例えば辞書の解説をするときにはてきとうな意味のわからんダミーデータを持ってきて、それを「辞書という概念の説明」という目的のためだけに使うところ。そうではなくて、こういうものが作りたくて、それにはこういう機能が必要だからここで辞書を使うとやりやすくて、辞書とはこういうものですよ、ていう説明じゃないと筋がわるいと思っている。その説明だと辞書というもの自体がこういうものであるという説明しかしてなくて、辞書が他でどう使われているかという情報が全く欠けている。辞書というデータ型は使われるために作られたのだから、それがどういうところで使われるのかという情報の方がむしろ重要なのではとすら思う。 そういう書き方をしていくと、例えばPythonだとクラスの説明も割とすんなり行くと思う。つまり、こういう機能とこういう機能とああいう機能が欲しいんだけど、いちいち個別に管理するのめんどくさいから、これらの機能の集合体を作れないかな?っていう目的が背後にあることが理解できれば、すぐに理解できると思う(もちろんそれが全てではないとしても)。そうではなくて、def __init__(self): の__init__なインスタンス作るときに呼ばれるとか、selfはクラス自身を渡しているとかいう説明をしてる入門書、むしろそっちが殆どだと思うけど、それは、本当にわかりづらいと思った。目的がはっきりとあって作られているものの説明に、その目的を省いて説明するのは、なぜなのだ。

ただ、どんな関数を書くねん?というとこは難しい

結局最終的には、どういう機能が欲しいねん?なにを書きたいねん?というところに行き着いてしまうので、ここはつらいところ。自分はここはバイトとしてタスクが降ってくるので、それを達成するための機能を作るっていうところで完全に回っているが、そういう機会もなく自分で学んでいる段階は、ここが一番難しい。 やっぱり、問題集的なのを探してきてそれに取り組むのが一番かな。その問題を解くために、入門書のさくいんを探し回るっていう取り組み。