その手の平は尻もつかめるさ

ギジュツ的な事をメーンで書く予定です

なぜ「プログラムの書けない学生」が出てくるのか

「プログラミング教育が悪いからじゃないですかねえ……」

と結論付けるのは、あまりに責任をアウトソースし過ぎでしょうか。
(なお、以下に出てくるプログラム、及びプログラミングはすべて「命令型(プログラム|プログラミング)」を指しています。)

さて、僕は2つの教育機関でプログラミングを勉強する機会に恵まれまして、
なおかつ幸いなことに一つ目の教育機関で「プログラミングとはこうこうこういうものである」という
プログラミングの基本をみっちり叩き込まれたので、ある程度プログラミングは「知っている」という水準に達することが出来たと思います。
恐らくですが、その学校に通っていた同期は、みんなある程度プログラムは書けるレベルにあったのではないでしょうか。

その後に編入した教育機関で目の当たりにしたのは、相当な数の「プログラムの書けない学生」の存在でした。
講義中、エクササイズとして出題された「フィボナッチ数列を求めるプログラム」は約半数の学生が解く事が出来なかった、という記憶があります。
情報工学専攻の大学で2年間学んでいるはずなのに。
結構なカルチャーショックというか、衝撃を受けました。

で、その教育機関の学生に話を聞けば聞くほど、「なんだかプログラミング教育がおかしいぞう」という印象を受けましたので、
僭越ながらそれに対していくつか。


初学者の為のプログラミング教育の(目的 | 目標)

プログラミング教育の目的及び目標は以下の2つにあると考えます。
  • (1)命令型プログラムの作法を叩き込む
  • (2)アルゴリズムを考える力を身につける

(1)命令型プログラムの作法を叩き込む
例えば…
  • 「命令型プログラムは上から順に実行されますよ」といった命令型プログラミングの基本中の基本
  • 基本的な文法(代入、ループ、条件分岐、関数などなど)
  • インデントの作法
  • コメントの作法
  • 変数名・関数名の付け方
  • 構造化プログラミングの概念
  • OOPの概念
  • 上記2つのプログラミング手法を満足させる為の考え方
等々を教えるといった、プログラムを書く為の下地を作るという意味合いのものを指します。

(2)アルゴリズムを考える力を身につける
これはそのままの意味で、ある問題を与えられたときにそれを如何にして解決に導くか、という一連の処理を考える力を身につける、という意味です。


先ほど例示した「フィボナッチ数を求めるプログラム」だと、for文等のループを用いて解く方法と、再帰を用いて解く方法の二種類が考えられるでしょう。*1
このように「実際にどのように問題を解くか」を考えてソースコードにするのは(2)に当たると思います。

「そもそもどうやって書くんだっけ」という基本中の基本である文法・構文に関する部分の考え方や、
「for文使って解くよりも再帰を使ったほうがスマートだよな」*2だとかの実装方法に関する考え方や、
「この部分の処理は関数にくくりだしたほうがよさそうだ」などの感覚を養うのは(1)に当たると思います。

つまり、
「或る1つのプログラミング言語をある程度使えるレベルになってもらい、それを様々な他の言語に応用できる力を付ける」
というのが初学者のためのプログラミング教育の目的・目標だと考えます。
なので、この場合のプログラミング教育に求められることは
  • 色々な解法・アプローチの提示する事
  • 命令型言語における共通の仕組み・考え方を教える事
なのではないでしょうか。
ですので、特定の言語固有の文法や複雑な仕組みは教えなくても良いのではないか、と思います。


プログラミング教育に必要なこと・もの

以下の5つが挙げられると思います。
  • (1)言語の選択
  • (2)書籍の選択
  • (3)教える順序の吟味
  • (4)厳格さ
  • (5)思考させる事
(1)言語の選択
「どの言語を使って教えるか」という事です。
僕がプログラミングの基礎を学んだ時に用いられたのは、Pascal という教育目的で開発されたプログラミング言語でした。
「教育用」として開発されたPascal はなかなか良い選択だと思いますが、オブジェクト指向をサポートしていないので、
そこら辺が問題になる場合は他の言語を選択したほうが良いかもしれません。
(C言語オブジェクト指向を実装するように、Pascalオブジェクト指向を実装する事は可能なんでしょうか?
もし可能な場合、それを実際にやってみるとかなり力が付く気がしますが。)
ただやはり、教育目的であれば「言語の多機能さ」よりも「言語の簡潔さ・わかりやすさ」が重要なように思います。
なので、Java のように巨大化・複雑化している言語は教育用途では使いにくい気がします。
あと、言語仕様が(命令型言語として)一般的である必要性があると思います。
例えばLua のように「全てのデータ構造がテーブルで表現される」みたいな感じで特殊な言語仕様を持っている言語は、
他の言語に応用を効かせにくいので、教育用としては向いていないのではないでしょうか。

(2)書籍の選択
そのまんまです。どんな書籍を教科書にして教えるかという問題です。
世の中に溢れるプログラムの書籍は玉石混合なので、途方も無いハズレ本*3を引き当ててしまうと、
「プログラミング難しすぎ! 俺には無理っぽいからやーめた」
となりかねません。
逆に当たりの本を読むと、面白いように頭に入っていくので、書籍選びは非常に重要であるように思います。

(3)教える順序の吟味
例えば「いきなりポインタを教えたらみんな死んじゃうよね」っていう話です。*4
プログラミングの基礎は積み上げ学習によって築かれる物であると思いますので、
いきなり話が飛躍したり、まだ教わっていない知識を知っている前提で話を進められたりするとエラい事になります。
(2)にも繋がる話かもしれませんが、ここら辺の順序だても大切だと思います。
(実際に入門書を読んでみると「この順番じゃねーだろ!」っていうのが少なからずありますので。)

(4)厳格さ
例えば「インデンテーションはこのルールでしっかりやれ!」だとか、「コメントはしっかり書け!」だとか、
「読みにくいプログラムは書くんじゃねえ!」だとかを厳しく指導するという事です。
これを最初のうちに厳しくやっておけば、腐ったコーディング習慣は付かないと思うので。
で、後々その基本を踏襲して自分のスタイルが徐々に確立されていくと思うので。

(5)思考させる事
この思考の機会を抹殺しているのが、大学のプログラミング教育が駄目駄目な最たる原因だと思われます。
聞く所によると、大学のプログラミングの授業は終始文法の紹介に徹していて、
「その文法はどういう時に役に立つの?」といった実用例はあまり教えないそうです。
また、演習等もあるにはあるようなのですが、講義の最後には必ず答えのソースコードが提示されるようなので、
学生は自主的にアルゴリズムを考えるという作業を放棄してしまっているのが実状のようです。

「プログラム覚えたきゃ実際に手と頭を動かさなきゃ駄目だ」
というのは僕にプログラムを教えてくれた恩師の言葉ですが、まさにその通りだと思います。

自分で考えて、自分でソースコードを書かないと身に付くものも身に付かないでしょう。
なので、答えを提示せずに、相手に極力考えさせる機会を与える事は、プログラミング教育において
最高レベルに重要なファクタであるように思います。
(個人的には、プログラムが意図しない動きになったときにそれを試行錯誤して直す、という作業で、
実際にプログラムが直った時に「ああ、これはこういう事なのね」という風に理解が深まったように思います。これはアハ体験の一種でしょうか?)


で、

現在のプログラミング教育は、上記の要素をうまいこと満足していないのでは無いかと……


加えて、全体的に抱えている問題

現状に即した教育用プログラミング言語の不在
Pascal という言語は、代入演算子に":="を使っている為、無意識のうちに左辺値と右辺値の概念が身に付く設計になっています。
また、begin とend でプログラムのブロックを表現しているため、中括弧を用いたブロックよりも「ここから始まって、ここで終わる」という感覚が良く掴めると思います。*5
といった具合に、Pascal は教育用を意識して作られているため、こういった(教育用途において)良い言語設計となっています。
ただ、前述のようにPascalOOP 等に対応していないので、現在のニーズを完全に満たしているかと言われると微妙です。
で、そんなニーズを満たしている「教育用」のプログラミング言語はほぼ無いというのが現実です。
一応、Pascal 以降に「教育用」と銘打たれてリリースされたプログラミング言語はあるにはあるんですが、どれもいまひとつといった感じな為、
ナウな教育用プログラミング言語は無いに等しいと言えるでしょう。

教える側の能力の不足
「プログラムを書ける」というのと「プログラミングを教えられる」というのは、全く別の能力であると思います。
いくらプログラムを書くセンスに長けていても、それをそのまま教えられる・伝えられるという人は少ないように感じます。
残念ながら教鞭を取っている方々もその例に漏れず、端的に言えば「教えるのが下手」な教員が多いという印象は拭えません。
ですので、プログラミングを教える場合は、「プログラムを書く技術」に加えて「プログラミングを教える為の技術」を
別に勉強する必要が出てくるのではないでしょうか。


なので、

プログラミング教育を体系化した、「プログラミング教育論」的な存在が必要なように感じます。
その為には新たな教育用プログラミング言語の登場が必要かもしれませんし、
その新しいプログラミング言語を使った効果的な教育カリキュラムが必要かもしれませんし、
それとは別に、既存のプログラミング言語を用いた効果的なカリキュラムの提案が要るかもしれませんし、
「これぞプログラミング教育のバイブル!」と言えるような名著の登場が必要なのかもしれません。

ともかく、プログラミング教育に重点を置いた考え方が求められていると思います。
プログラミング教育が良くならない事には、「プログラムの書けない学生」の数は減らないと思うので。


しかしみなさん、プログラミング教育には興味があるみたいですね

Scratch やSmall Basic といったプログラミング言語で上手いこと若年者を釣って、プログラミングという泥沼に引きこもうぜ! だとか、

ニュース - 松江市が市立中学でRubyプログラミングの授業を開始へ:ITpro
のように、ruby のメッカである松江市の中学校では、中学校のカリキュラムにruby によるプログラムを取り入れてみたり

Pythonがプログラミングの学習に向いているたった一つの理由 | TRIVIAL TECHNOLOGIES @ats のイクメン日記
みたく、Python がプログラミング教育に向いてるんだよ! だとか、

Khan Academy、一番最初に学ぶプログラミング言語としてJavaScriptを推奨 | スラッシュドット・ジャパン デベロッパー
で言われているように、コンパイルレスでレスポンスが早いから、JavaScriptこそが最初に学ぶべきプログラミング言語なんだよ! だとか……

なんだかんだで皆さん、プログラミング教育については興味津々なようです。

ただ、それぞれがそれぞれ、てんでバラバラな方向を向いているから良くないんだよなぁ……
教育用プログラミング言語も、Haskell がそうしたように標準化・共通化を目指して新しいのを作れば良いのに……


てな感じの事を考えたりしました。ツッコミ歓迎です。

*1:もっとあるかもしれませんが。

*2:これには色々意見があるでしょうが、趣味の問題とお考えください

*3:リンク貼ろうとしたけどやめました

*4:死なない人も居るでしょうが

*5:begin とend を使うのは旧時代的だとの意見もありますが