🌟

プログラミング的ゾンビとプログラミングの学習について

10 min read 12

背景

https://togetter.com/li/1610041

こちらのまとめを読んで、「数学的ゾンビ」と面白い考え方だなと思うので、プログラミング的ゾンビというのも考えられないかと考えてみた。そして、同時にプログラミングの理解だとかプログラミングの学習とか、そのところも同時に書いていければなーとかでいろいろ書いてみた。

プログラミング的ゾンビについて

プログラミング的ゾンビとは?

プログラミング的ゾンビというものを考えたとき、それはどういうものか?考えてみると以下の2つの点があてはまれば、プログラミング的ゾンビだと言えるだろう。

  • プログラムを書けるように見える
  • プログラムの内容や意味するところは分かっていない

と考えたとき、どのような人がプログラミング的ゾンビだろうか?と思うわけで、具体例を示していこう。

プログラミング的ゾンビの具体例

こうしたとき、プログラミングゾンビの一番典型的なのが、誰かが書いたコードをひたすらコピペして作る人たちだ。そういう人たちは、たぶんコピペのコードの内容をはっきりと理解していないことが多いと思う。そういう人たちはたぶん、時間がなかったり、そもそもプログラミングについて学習したこと無い、あるいは学習が足りない等の状況下で、何かプログラミングで解決しなければならないときに起こる。

それでそれ以外にもプログラミング的ゾンビの例として、どんな場合があるか考えてみると、解きたい問題と解決のコードをセットで覚えて、コードを書いているパターンだ。つまり、(問題, コード) の集合を覚えているということに近い。そして新しい問題に対して類似の問題を探り、コードをその問題が解決するように変形させていくパターンだ。

たとえば、1 ~ 100まで足すという問題があり、それに対するコードがあったとしよう

(print (do ((i 1 (+ i 1)) (sum 0)) 
        ((> i 100) sum) 
        (setf sum (+ sum i))))

それでももし、1 ~ 10000までの足すという問題があれば、単純に100を10000に書き換えるということをやっていく。これは、Common Lispのdoマクロというのが理解できなくても、1 ~ 10000まで足すという問題を解決するコードが書けてしまう。(本来はcommon lispではloopを使うと思いますが、ここではあえて、違う書き方をしてみました。)実際に、プログラミング教育を私がやっていて、よく出くわす例をしてはこのようなものだ。課題は解ける、プログラミングはできるのだが、実はコードが何をやっているのか、深く説明をもとめるとできないみたいなことがよくあるのだ。(例ではLispを上げたが、私がよく見るのはScratchやJSやC#なのだが。)

プログラミング的ゾンビだなと思うとき

プログラミング的ゾンビだと判断するときの基準はなんだろうか?一つ、私が考えるのはそれは、間違えを犯したときだ。コードの間違えがかなり独特な間違えをする。そしてコードが間違っているとき、プログラミング的ゾンビ間違えを自分で直すことができない。たとえば先ほどの例でいえばこのような間違えのときだ。

(do ((i 1 (+ i 1)) (sum 0)) 
        ((> i 100) sum) 
        (setf sum (+ sum i)))
(print)

これは極端な例だが、しかし実際にこれを似たような間違えを犯している人が案外多かった。この例では、ループもしくはprint式を書く場所が違うのだが、彼らは平気な顔をして書いて、「なぜ間違っているかわからない」ということを言いだすのである。

先ほどの回答をみると何が間違っているか一目瞭然だが、考えてみると写経でコードを書いて学習している等だったとして、彼らにとっては、コードの意味よりも、写経して正しいコードと間違え探しをしながらコードを書いてきたので、そもそもコードを構文的にとらえることができていないのでは?と考えるのである。

もう一つある、それは全く新しい問題を出したときである。たとえば、先ほどの問題から、「1 ~ 100の偶数のみを足せ」の場合、解答できないパターンだ。もし、彼らに類似するパターンがあれば、回答することができるが、彼らが経験したことがない問題に出くわした場合、彼らは解答することができないのだ。

一方では、問題を解くのがめちゃくちゃ早いという特質もある。過去のパターンをそのまま思い付くことができればいいため、分かる問題はすぐできるのだ。これはもちろんプログラミング的ゾンビのみの特質ではなくて、一般のプログラマーでも解きなれた問題はすぐ書けるというのに近い。

プログラミング的ゾンビができないこと

と考えたとき、プログラミング的ゾンビができないこと、というのはつまりこういうことだと私は考える

間違えた問題を直すことができない。これはプログラミングの理解が足りていないということだろうと考えている。

自分で思いつくことができない。パターンからコードを生み出すという点ではプログラミング的ゾンビはコードを生成することができる。むしろ、その方が高速に生み出せる。しかしながら、パターンに適合しない問題に当たったときに、プログラミング的ゾンビはその問題を解決することができなくなるのだ。つまり、自分でコードのパターンを思いつくことができないと言ってもいいかもしれない。

この2つのことについて順番に考えていこう。

プログラミングの理解とは

とここまで書いていくと、そもそもプログラミングの理解するということはどういうことか?という疑問が出てくるだろう。たとえば先ほどのコード

(print (do ((i 1 (+ i 1)) (sum 0)) 
        ((> i 100) sum) 
        (setf sum (+ sum i))))

というコードを理解するというのはいったいどのようなものだろうか?ということである。また、理解していくというのはどこまで理解するのだろうか?というコードの理解の深さもあるだろう。

私としての意見を述べていこう。ざっくりを私が考えるのは、

  1. そのコードを構文的に把握し、コードを部分に分解できること
  2. コードの部分が何を意味するのかを部分的に説明できること
  3. それらを統合してコードの挙動が把握できること
  4. コード全体の挙動からどうしてその問題が解けるのか理解できること

この四点である。もう少し具体的に説明していこう。

まず(1)についてだが、構文的に把握するというのは、たとえば、上記において(print ...)とあるが、printというのは関数名であり、(do ...)というのはdoマクロであることを把握する。もっと深く行くと(do (ループ変数について書く) (ループが終わる条件を書く) ループする式)を書くみたいな、形を捉えて、更に言えば、(do ((i 1 (+ i 1) ...と書いたとき、iはdoループ内で使う変数、1が初期値、(+ i 1)が更新する時の式、そして、((i ...) (sum 0)) ...と書いてあるので、sumもループで使う変数で初期値が0であることがわかる...というようなことだ。

ここで注意したいのはあくまで「構文的」に把握する段階である。それが何を意味するのかまではいかない。printという関数名、doマクロの文法的な構造は分かるが、それがどのような挙動をするか?等はまだ把握していなく、それを把握するのは次の段階である。その前にこのようなコードの文法を捉えていく、そのような段階があるのだ。

(2)の段階について、つまりコードの部分が何を意味するんか?といのうことであるが、例えば、(print ...)とあるのは、printの後方に掛かれた式を評価して、その値を標準出力へ書き出すというものであるとか、(do ((i 1 (+ i 1)) ...とかけば、ループ変数iの初期値で初期値は0で、ループが継続するときiに1を足したものをiに代入して、次のループに進むみたいなそのような理解ができるとかそのようなことである。

(3)の段階にて、たとえば、先ほどの式の例でいえば、「このコードはつまり、変数iと変数sumという2つのループ変数を用意して、最初、iが0、sumが0で、ループが一つ進むと iは1で、sumが1、また次はiは2で、sumは3になって...そしてiが101になったらループが止まって、その時のsumの値が返されるのか~」等を把握することである。こうやって文章で書いているが、私の場合は実際に機械が動いているのをイメージしている。しかしここではまだ、機械の動作のイメージだったり、コード全体については把握しているが、じゃあなぜそれが目的のためのコードかという段階に至っていない。ただ、例えばコードの順番が分かるみたいなものである。

(4)の段階だと、どのようなコードがなぜ、正しく答えを出せるのか?という問いに答えていくところである。上記の例でいえば、大雑把だが、簡単に説明すると、
n回ループを回るとき、iはnとなり、また、sumは前回のsumにnを足されたものになる。sumは初期値0なので、つまり

(ループ0回目のsum) = 0
(ループn回目のsum) = (ループn-1回目のsum) + n

となるので、ループ100回目に、sumが0 ~ 100まで足されたものとなり、iが100になるとループから脱出し、sumの値をこのループは返すため、1 ~ 100を足した問題に解答できる。わざわざ数式を書いてみたが、実際のところこのようなイメージを持っているだけであって、頭の中で数式を入れて検証しているわけではない。ただ、ある程度このようなものに近い、説明ができるみたいなものである。コードの挙動がどうして、その問題を解決するかということである。

上記のことはわたしが、思うコードの理解を大雑把に説明してみたが、たぶん人によって違う理解をしているのかもしれない。もっと雑にとらえていたり、もっと細かく正確に厳密に考えて書いているかもしれない。4つのプロセスを踏んだが、人によって、理解の順番も違うかもしれない。でも私の頭の中ではおそらくこのような段階を得て、理解しているような気がするのである。順番は異なるかもしれないが、ざっくり意識的にも無意識的にもプログラミングを読むとき、把握するときにやっているような気がするのである。

プログラミングの内容を把握していないとは?

つまるところ、上記の段階のどれかが理解できていないということである。つまり

  1. コードの構文を把握できず、部分に分解することができない
  2. コードの部分が理解できていない
  3. コードを統合することができない。
  4. なぜそのようなコードが正しいのか理解できない

ということである。プログラミング的ゾンビというのは考えてみるとこれらの工程をすっとばして、コードを書く人なのかもしれない。

ほとんどの場合、1ができていないことが多い。つまり、シンタックスを捉えきれていないパターンが多いと私は感じている。例えば、先ほどの間違え

(do ((i 1 (+ i 1)) (sum 0)) 
        ((> i 100) sum) 
        (setf sum (+ sum i)))
(print)

というものはそもそも構文の理解ができていないと判断することができるだろう。

2,3,4の場合はどうだろうか?ほとんどの場合構文が理解することができれば、2と3、4への理解が速い。ただたまに1が分かっても、2,3,4がよく分かっていないという例に出くわすことがたまにあるように感じる。それは、コミュニケーションをとっていくとだんだんわかっていくのだ。

たとえば「doループはどこ?」と聞くと、そのコードの部分はどこにあるか?というのは分かっている。しかし、じゃあ、このループは何しているの?と答えられない場合だ。これは2のパターンだなと思う。

3の場合は、全部のことを脳内でやっちゃって、ぐちゃぐちゃになっている場合である。その場合、処理をいったん紙に書いてごらんと言ったら、分かったとなる人が多い。ほとんどの場合、ワーキングメモリが足りなくて、全てのことが考えられないのである。

4の場合は、プログラミングを分解して、各自がどのように動いていくか、それについては納得してもらえるが、でもそう動いたからといって、なんで問題が解決するのかが分からない人である。それは数学的な理解だったり、アルゴリズムの理解だったり、コード以上に、背景だとか理論がわからない人だったりする。例えば、底辺に高さを掛けて、2で割るとどうして、三角形の面積ができるか?わからないみたいなものに近い。

つまり、プログラミングの理解というのは、このように様々なことがあると、私は思っている。

どうして、そのコードが創造できるのか?どのようにして、そのコードが思いつくののか?

一方、プログラミング的ゾンビは、過去のあるパターンを引き出す以外のことで、コードを思いつくいというのができないと述べた。一方で、コードを思い付くって、どのようにしてやっているのだろうか? そのところを述べて行く。

先ほどのコードの別解について

そういえば、先程のコード、これらのコードは違う解決の仕方もあるだろう例えば、

(print (do ((i 1 (+ i 1)) (sum 0 (+ sum i))) 
        ((> i 100) sum)))

と書いてもいいし、loopマクロを使って、

(print (loop for i from i to 100 sum i))

とも書いてよい。またまたループ等を使わず、簡単な数学の知識を使って

(print (let ((n 100)) (* n (+ n 1) (/ 1 2))))

などやって良いのだ。
たまたま、いくつかある正しい回答の選択肢から適当に選んだというだけである。

基本的なプログラミングの理解が前提

さて、これらのコードをどうして私は思いつくことができるのだろうか?組み立てることができたのだろうか?頭のなかで何をきっかけとして、どのように展開して、どのようにこのコードを構築したのだろうか?

まず、私が考えるに、先程のプログラミングの理解が前提となるのは間違いないだろう。(1)文法的な構文的な理解、(2)各構文や式がどのような意味を持つのか、(3)各構文の意味を統合し把握、(4)背景的な理論の理解はまず前提となるだろう。これらの理解がなければ、プログラミングのコードを書くことはできなりだろう。

どうやってアイディアを創造するか?

しかしながら、それだけでは、プログラミングの理解だけでは新しくコードは創造することはできないだろう。例えば、釘とトンカチと木材で、釘を打つことや、鋸で木を切ることを、覚えたとしても、テーブルがいきなりつくれるわけではないだろう。そこに、テーブルというアイディアがあって始めて、テーブルをつくることができる。

つまりここで議論したいのは、そのようなアイディアはどのように作っていくものだろうか?という問いに近い。1 ~ 100の合計を求めるというのはどのように、コードへのアイディアが思いつき、コードに落し込むことができるのだろうか? (このようなアイディアを思いつく作業を、設計と呼んだりする人がいるだろうが、今回は敢えて、このような書き方をした)

これと似たような議論に「数学の解放というのはどうやって思いつくのだろうか?」それととても似ているように思える。私は、数学がある程度できる人間はプログラミングの素質があるように思うのだが、それは、このような思考ととても似ているからだと思っている。数学の解放を思いつくことと、プログラムで問題を解く思考はとても似ているように感じる。

さてどのように思いつくのだろうか?いろいろ説明してもいいのだが、結局のところいろいろ考えてみたらその思いついた というのが私の感覚で、なにか意識的にこうすれば、解法やアイディアを思いつくといことは無いように感じる。もちろん、「このような道筋をたどっていけば、このように思いつける」みたいなものはあるかもしれないが、結局のところそれは後付けであって、実際のところ何かひっかりやら、怪しいところについて考えていたら、そのアイディアが出てきたというのが正直なところ。

たとえば、先ほどに関しては、「1 ~ 100を足すのだから、沢山計算しないといけない。だから、ループ使おう。100回足すのだから100回ループ回す、その時のループカウンタを足していけば1~100の合計が分かるんじゃね?」みたいな思考になっているとする。でも、その思考はどこからやってきたのだろうか?。おそらくこの思考にならないから根本的にプログラミングができないみたいなのがあると思う。

もちろん、すごく大きい問題だったりする場合とかは、問題を分割したりみたいなことなことをやったりするものだ。しかしながら、根本的には、いろいろ考えたら行きつく先みたいなところであるように感じる。ループをこのように回して、if式を書いて、なんかデータ構造はこのようにして、と考えてみたいなものだ。

おそらく解法が思いつ方法がもしあったとすれば、そもそも世の中の問題は大抵解決するのであろう。しかし、残念ながらそのようなものはないと思っている。ただし、考えて、いろいろ試していけばいつか解答できるやろみたいな、そのようなものがプログラミングだって思っている。

アイディアを考えるとはどういうことか?

さて、いろいろ考えてたら、思考してたらできた。と書いたが、じゃあどのようなことを考えていけばいいのだろうか?というのが最後に思うことである。私はどのようなことを思考するのか。おそらく私はこの2点について考えていることが多いとおもう。

  1. 可能性について考える
  2. 問題について調べてみる

可能性について考えるとは

まず、私が思うところは、あるプログラミング言語機能だったりするものを学習したりするだろう。そこで、その言語機能について、いったいどんなことができるだろうか?という可能性を考えていくのでる。たとえば、ループという道具、if文という道具があったとき、どのように使うか?を考えていく。

ここでセンスがある人は、「いろんなことができそうだ!」とワクワクしだす。一方、センスがない人は、「でなにができるの?」とまったくそのことに関心を持たない。その違いがある。いろんなことができると考えた人は、おそらく既に、「あれもできる」「これもできる」といったことを自分で考えだす。センスがない人は、その道具で解ける問題でも、「いやこんなつまらない道具だと解けないでしょ」となって、その可能性を信じていないから解けないのである。

できれば、ある発明や技術などが出てきたとき、どんな応用例があるんですか?と聞く人ではなく、「こういったものに使えそう!どうですかね?」と提案できる、そういう人がプログラミングに関してセンスがあるように思う。

問題について調べてみる

2つ目は、結局のところ、問題に関して、どれだけのことを理解できるか?ということである。その問題について多くのことを知っていることが有利ではあるが、それだけでなくて、その問題からどれだけ多くの情報を引き出せるか?というのが大事になってくるだろうと思うのである。

問題についてひっかかりを調べていくと、類似の問題がみつかりそれで、ああこれを使えばわかるみたいなことがあると思うのだ。問題しらべていくとどうやら、いくつかの部品に分かれるのが分かったりとかそういうことだ。

どのようにしてプログラミングを学ぶべきか?

とまあここまで書いてきた。プログラミング的ゾンビに関心がありいろいろ考えをまとめるために書いてきたが、結局なぜそのような関心があるかといえば、私の経験とプログラミング言語についてやプログラミングの教育や学習についてここでいろいろ整理しようと思ったからである。

最後に、プログラミング学習について書いていこう。プログラミングはどのように学習すればよいのだろうか?プログラミング的ゾンビにならずに済むのだろうか?

私は以下の点が重要だと考えている。特に2つ目の点が重要だ。

  • プログラミングの基礎的な理解に努める
  • 自分の関心事についての課題について考えていく。自分のための問題を解いていく。

まずプログラミングの基本的な理解というのは、日々技術書を通読したり、だれかに教わったりして、「プログラムの書き方」を覚えていくことである。これは、そこまで問題にならない。(この時点で挫折する人はおおいのだけれども)

そして、そのあと通読した後、「プログラムの書き方」が分かった後が非常に大切である。自分にとっての関心事についてプログラミングで創造的に取り組むことである。なぜ大切かと思うのかというのは、まず自分自身の課題というのは大抵の場合、新しい問題の場合が多い。そして、自分自身のことだからこそ、興味をもって考えつづけられるということである。そして、問題を自分で展開ができる。自分自身の問題は再現がないのだ。それは次々に可能性を見つけられるということにつながる。

S.パパートは「構築主義」といったが、その学習についての理論は非常に正しいような気がするとふと思うのである。

最後に

ここまで書いたが割と不完全燃焼であり、私の考えていること、まとめておきたいことはすべてかけた、そして正しく書けたとは到底おもえない。しかしながら、今後ともこの内容に近いことがあれば、このにまとめていこうかなと考えている。

Discussion

面白い記事ですね!
いくつか思ったことを書きます。こんな考え方をする人もいるんだな、というぐらいの事かなと思います。

プログラミング的ゾンビは、実装はできるが"本質的な"意味がわからない人の事をさすのでは?

本来の哲学的ゾンビは、外見的・物理的には一切の区別ができないものの、その内的に感じる感覚が無い人のことを指すと思います。
プログラミング的ゾンビとされる人が、実装をできない場面があるとすれば、その人は内面的な理解以外で差が露出してしまっているので、少しゾンビの意味が異なるのでは?と思いました。
元ネタの数学的ゾンビの場合、問題は解ける、つまり操作的な理解はありながらも、"本質的"な理解がないという事を意味していたと思います。

プログラミングの理解とその順序について

筋の良いプログラミングの理解の仕方がどうあるべきか?という事はさておき、以下のような理解/コードリーディングはあり得ると思います。

  • あるコードを実行すると、なんらかの文字列が表示された後に停止するので、その文字列を出力している命令を探す
  • printという文字列や、出力している文字列を探す
  • 文字列を出力している箇所を特定する
  • 周辺を読みすすめる

ひょっとすると、屁理屈のように思われるかもしれませんが、世間で人気のあるプログラミングの本にリーダブルコードという本があり、この本の中では名前の重要性がしばしば説かれています。
言い換えると、多くの人間はその構造ではなくて、プログラムの中における意味ですらない、言葉の意味を元にしてプログラムの意味を理解しようとする、という事が示されています。
これは、記載された理解の順序とは異なる理解の順序ではないかなと思いました。

特に、関数の名前などから処理内容を把握しようとする場合、むしろ記載の4→1の順序で理解が進んでいるのでは、と思います。

また、この時に1〜4のそれぞれの理解が多少浅くても、プログラムを書く事はできると思います。
厳密な意味を理解していなくても、なんとなく単語の意味から類推して書けば、理解していないけれども結果的に正しく動くコードを書くことはできてしまいます。

※それが"正しい"在り方か?ということは、ちょっとわかりませんが...私の場合は、何も理解していない状態で適当に書いたコードがはじまりでした。
中学生の頃、本を通読するどころか、400ページほどあるVBの入門本のうち、自分に本当に必要な部分20〜30ページぐらいをつまみ食いして、神経衰弱のプログラムを書いたというのがスタート地点でした。
その時は構文の規則などほとんど理解しておらず、適当に書いてはコンパイルエラーを繰り返して、とりあえず動いたらあーできた、そういう感じでした。
これは、動いてはいるが"本質的"な事を理解している訳ではなかったかもしれないな、と思いました。

コメントありがとうございます。興味深く、拝見させていただきました。コメント内容について一つ一つ私なりの考えを返させていただきます。

プログラミング的ゾンビは、実装はできるが"本質的な"意味がわからない人の事をさすのでは?

哲学的ゾンビの本来的な意味としては、私もその通りだと思いますし、そのところはいろんな考えがあるんじゃないかと思います。ただし、ここでは、私が日常的に体感している出来事の有用な説明として、「プログラミング的ゾンビ」としています。もし、本来的な哲学的ゾンビ意味合いに沿うものだとすれば、その存在自体を議論することが難しいもので、あまり有用でないなと思います。

また、元ネタ数学的ゾンビに関しても、「問題は解けるが数学の意味を理解していない」に関しても、「(これまで解いてきた)問題は解ける」と私は、解釈してます。流れ的にも「今後困ることになる」というのは、今後解けない問題が出てくるものと思います。つまり、数学的ゾンビも内面的以外の差異はでてくるだろうということです。プログラミング的ゾンビも同様で、これまで実装してきたものに関しては一般のプログラマーと遜色なく実装できる(その特定の状況においてはプログラマーとの内面以外の差異が見られない)が、とある問題ができない、という人を指して「プログラミング的ゾンビ」としました。

プログラミングの理解とその順序について

わたしの本分においても、「プログラミグの理解」の終わりあたりに、

「上記のことはわたしが、思うコードの理解を大雑把に説明してみたが、たぶん人によって違う理解をしているのかもしれない。もっと雑にとらえていたり、もっと細かく正確に厳密に考えて書いているかもしれない。4つのプロセスを踏んだが、人によって、理解の順番も違うかもしれない。でも私の頭の中ではおそらくこのような段階を得て、理解しているような気がするのである。順番は異なるかもしれないが、ざっくり意識的にも無意識的にもプログラミングを読むとき、把握するときにやっているような気がするのである。」

というのがそのまま解答になるような気がします。つまり、順序自体は重要でなく、また理解の程度はあまり重要でなく、理解にはそのような要素がありうると認識していただければいいかなと思います。

また、この時に1〜4のそれぞれの理解が多少浅くても、プログラムを書く事はできると思います。
厳密な意味を理解していなくても、なんとなく単語の意味から類推して書けば、理解していないけれども結果的に正しく動くコードを書くことはできてしまいます。

それこそ、私が表現したかった「プログラミング的ゾンビ」のもう一つの形態であると私は思います。「なんとなく単語の意味から類推して」とありますが、これは、もともと参考にするソースコードがあり、その単語の意味を類推していると思いますが、つまりこれはあるとあるコードを参考にしているという点において、(問題、コード)パターンだと思います。本分にも、

「つまり、(問題, コード) の集合を覚えているということに近い。そして新しい問題に対して類似の問題を探り、コードをその問題が解決するように変形させていくパターンだ。」

とだけ書きなかなか表現しにくかったのですが、そういった風にコードを書いているのも含有しています。

一方で、そのような参考にするストックがゼロの場合、参考にできるものがなにもない場合で、コーディングする場合はそのように書くわけにはいかず、(1500字制限に引っ掛かりました次に続きます)

そのような状況においては、ロジックを生み出す必要があり、つまり、それこそが後半に書かれていることであります。

※それが"正しい"在り方か?ということは、ちょっとわかりませんが

何が正しいかはそれこそ人による価値観でしょう。わたしは「プログラミング的ゾンビ」だからといって正しくないあり方とは思いません。一部の問題を解決できる状態ですから、とても有用なことだと思います。むしろ、全体としてはある意味、「フレームワーク」として機能しているような気もします。

だいたいの私の考えを返させていただきました。興味深いコメントありがとうございました。

丁寧に回答ありがとうございます。
以下、感想というか個人的な意見であって、何かに対する攻撃等を意図したものではないので、念の為。

プログラミング的ゾンビという言葉が指す意味については、そもそも一般的な定義が存在するものではないので、ここで記載頂いた通りの定義をするという事であれば、そのとおりかなと思います。

後半部分に関してですが、私の書き方が順序についての指摘のような書き方になっていたのが良くなかったかなと思いましたが、そもそもの要素として「各語の意味」に相当する部分が欠落しているのかな、と思いました。(構文の意味ではなくて、単語の意味)
これは結構本質的な事かなと思っていて、

一方で、そのような参考にするストックがゼロの場合、参考にできるものがなにもない場合で、コーディングする場合はそのように書くわけにはいかず、そのような状況においては、ロジックを生み出す必要があり、つまり、それこそが後半に書かれていることであります。

ということですが、私が自分にとって全く新しいもの(神経衰弱)を作り出したとき、全体の構造のようなものについては一切参考にするものはありませんでした。一方で、例えば画像を表示するとか、画面にボタンを配置してイベントをハンドルするとか、そういう個別の方法は本に記載がありました。
私がこのような取組をして、私自身の記憶・経験の中において例題の存在しない全く新しいものを作り出す過程でいうと、次のようなものでした。

1.まず私の中で「この要素を組み合わせる事で、特定のパターンを構成できる」という事を"プログラミングとは関係なく"構成する。
2.構成したパターンで"設計"をし、それを具体的にプログラミングしていくことで実装をする。

この2の過程で、プログラミングを理解していないとプログラムを書けないかというとそれは嘘で、私はプログラミングを表面的にしか理解していない状態で、自分の思う通りのものを作ることができました。多少不格好ではあるにしても。

そのような観点では、

自分の関心事についての課題について考えていく。自分のための問題を解いていく。

という事が、プログラミング的ゾンビでない理解を生み出すかというとハテナかなと思います。私の場合は通読をしていないというそもそもの問題点(?)はありますが、仮に通読をしていたとしても、本質的な理解が深まっていない状態では、同じようにプログラミングの理解は置き去りにして物を作る事ができるのかなと思います。
実際、私は業務で、作業者に対して、あるWebアプリケーションフレームワークを用いた開発の具体的な手順やコードの意味を解説するマニュアルを作る依頼をした事があるのですが、その時には公式の記載を通読(以上)しているはずでも、理解が足りていない部分が多々ありました。
これは、構造や構文の理解という事とは関係のない、例えば単語の意味とか、そのようなレベルでの理解に基づくことなのかなと思っています。続きます。

※一度コメントを消してしまいました

また、「参考にするストックがゼロ」という状況ですが、そのような状況にあっても普通は断片的には何らかの参考にするものは存在しているはずだと思います。逆に、本当にある問題に関して参考にできるものが全くのゼロであったとすれば、「それはそもそも人間のパターン認識的な操作の限界を超えていて、何も作れないのでは?」という事を思います。
というのも、科学に関する発展の歴史を紐解いた時に、相対性理論はその下敷きになる理屈・材料が一通り揃ってはじめて出てきたとか、群論は方程式の解(根)の性質を考察するという前提があってはじめて数学の対象になったとか、どんな天才であってもその発想は必ずそれまでに存在した理論・知見に基づいています。そのような観点においては、一人の人間が全くのゼロから想像できるという事は非常に少なく、仮にゼロから作っているように見えるとしても、実際には過去の知見に多く依存しているのかな、という事を思う次第です。

これらの私の意見の根底にあるのは、「構文や構造とは無関係に、単語としての意味があり、人間の認知はむしろそちらに基づいている」というような事かなと思います。
もともと思った「理解の順番が逆では?」という事もそうですが、この記事に記載された理解の方法は非常に論理的というか、説明ができるような形での理解の仕方に基づいているなと思いますが、私が実感する理解というのはもっと違う形のような気がするな?というのが、ここにコメントを書こうと思ったモチベーションでした。
それは、私自身も、本質的に理解をしていない/間違った理解をしている人に対して、よりよいプログラミングの学び方みたいなものを提供できると嬉しいな、というような思いに基づいたものでした。そのため、実際に試して失敗した事なども書きながら、理解の在り方とはどういうものでしょうね、という問題を提起したかったのでした。

丁寧に回答ありがとうございます。
以下、感想というか個人的な意見であって、何かに対する攻撃等を意図したものではないので、念の為。

はい。こちらこそご回答ありがとうございます。
私としても、攻撃的な意図は感じられないのでご安心ください。むしろ、コメント全体として、とても建設的な意見だと思い、好意的に捉えています。

そもそもの要素として「各語の意味」に相当する部分が欠落しているのかな、と思いました。(構文の意味ではなくて、単語の意味)
これは結構本質的な事かなと思っていて、

なるほど。この点は欠落していました。私としても、私が書いたことが要素がすべてのことだとも思っていなく、ただ私が現時点で考えられることを書き連ねてきましたが、この指摘はなるほど妥当のように思えます。ただし、私はさらに意味だけではなくニュアンスやイメージも含むだろうと考えています。

1.まず私の中で「この要素を組み合わせる事で、特定のパターンを構成できる」という事を"プログラミングとは関係なく"構成する。
2.構成したパターンで"設計"をし、それを具体的にプログラミングしていくことで実装をする。

私もソフトウェアを設計、開発するとき、プログラミングの前提となる点に要素、組み合わせを組織するということは行います。私としては、プログラミングの理解の「コード全体の挙動からどうしてその問題が解けるのか」という点を最初にある程度、仮説を立てるというのに近いと思います。それこそが「アイディア」と私が書いたわけです。

次のことは若干引用が前後してますが

この2の過程で、プログラミングを理解していないとプログラムを書けないかというとそれは嘘で、私はプログラミングを表面的にしか理解していない状態で、自分の思う通りのものを作ることができました。多少不格好ではあるにしても。

ということですが、私が自分にとって全く新しいもの(神経衰弱)を作り出したとき、全体の構造のようなものについては一切参考にするものはありませんでした。一方で、例えば画像を表示するとか、画面にボタンを配置してイベントをハンドルするとか、そういう個別の方法は本に記載がありました。

実際、私は業務で、作業者に対して、あるWebアプリケーションフレームワークを用いた開発の具体的な手順やコードの意味を解説するマニュアルを作る依頼をした事があるのですが、その時には公式の記載を通読(以上)しているはずでも、理解が足りていない部分が多々ありました。
これは、構造や構文の理解という事とは関係のない、例えば単語の意味とか、そのようなレベルでの理解に基づくことなのかなと思っています。続きます。

この点は、なるほど私と違うなと思います。
私としては、そもそも納得できない面、理解できない面があること自体がそもそも自分自身で許容し難いということの、自分の開発はある程度自分の思考を通したものでないと納得できないという点において、理解が足りないところを残しておくことができない人間でした。それが職業的なエンジニアとなりより一層強くなったように思います。自分が書いたコードは全部理解できるようにしておかないとという責任みたいなものがあったように思います。

すいません。続きます。

その意味では、私としては思わず、「プログラミング自体の本質的な理解」を前提において話がちという面はありなるほど、理解が浅くても、ある程度はプログラミングは可能というの点は抜けていたように感じます。

そのような観点では、

自分の関心事についての課題について考えていく。自分のための問題を解いていく。

という事が、プログラミング的ゾンビでない理解を生み出すかというとハテナかなと思います。私の場合は通読をしていないというそもそもの問題点(?)はありますが、仮に通読をしていたとしても、本質的な理解が深まっていない状態では、同じようにプログラミングの理解は置き去りにして物を作る事ができるのかなと思います。

これは一部その通りです。
ただし、というかだからこそ

プログラミングの基礎的な理解に努める
自分の関心事についての課題について考えていく。自分のための問題を解いていく。

という2点を置いたということがあります。プログラミングの基本的な理解をしなくて、ものをつくることができる、だからこそ後者の点のみを意図しているわけでなく、前者の点も併記しているわけです。

では、前者だけでもいいかとそうでもなく、「自分自身の主体性をもって考える」という点が非常に理解に大切であると考えていて、その意味で後者なわけです。

おそらく、プログラミングの学習には大きくわけで2通りのやり方が考えられ、A.プログラミングの構文、文法を把握してから、自分の課題を解くタイプと、B.最初に解かなければならない課題があり、その目的のために、目的に適うものを見つけ出し、とりあえず当てはめていくタイプです。

A.のルートの場合、何が問題になるか?といえば、問題を解くものはそろっているが、問題を解くための、ものをどのように繋げ、構成していくか?ということが身につかない問題があります。多くの場合、人から「答え」を教えてもらうことで、問題を解くことをやってきた人で、とても素直な人が多いように感じます。だからこそ、「自分で主体性をもって考える」というものが重要で、ですから、「自分のための問題を解く」が重要だと考えているわけです。

一方Bのルートですが、これらはすでにクリアされていることが多いのです。(一方では、プログラミングの基本的な理解に関しては問題になることが多いと思いますが)

私が自分にとって全く新しいもの(神経衰弱)を作り出したとき、全体の構造のようなものについては一切参考にするものはありませんでした。

とありますが、A.のルートの人はこれをすること自体ができないのです。だからこそ、「自分の関心事についての課題について考えていく。自分のための問題を解いていく。」というものも重要だと考えているわけです。

また、「参考にするストックがゼロ」という状況ですが、そのような状況にあっても普通は断片的には何らかの参考にするものは存在しているはずだと思います。逆に、本当にある問題に関して参考にできるものが全くのゼロであったとすれば、「それはそもそも人間のパターン認識的な操作の限界を超えていて、何も作れないのでは?」という事を思います。
というのも、科学に関する発展の歴史を紐解いた時に、相対性理論はその下敷きになる理屈・材料が一通り揃ってはじめて出てきたとか、群論は方程式の解(根)の性質を考察するという前提があってはじめて数学の対象になったとか、どんな天才であってもその発想は必ずそれまでに存在した理論・知見に基づいています。そのような観点においては、一人の人間が全くのゼロから想像できるという事は非常に少なく、仮にゼロから作っているように見えるとしても、実際には過去の知見に多く依存しているのかな、という事を思う次第です。

この点おいては、私の経験を話しておくと、私はC言語でGCのようなものを制作したりしたことがありました。当時、C言語のメモリ管理が大変だったので、私はなんとか楽にできないかと考えた結果、不要なメモリを集めて解放するというアイディアを思いつきました。そして実装した後で、先生から、それはCGというものだよと指摘されたことがあります。また、グラフィックライブラリからなにかGUIを作ろうとして自分で、イベントハンドリングの仕組みも自分でつくった経験があります。(これもあとから、フレームワークあるじゃんって知りました。)

この点において、参考にしたものはなにもありませんでした。ただ、自分の問題があり、自分で少し考えて、自分で解決できたというだけです。

おそらく私が考えるに意識的に「参考」にしたということの意味合いが違うように思います。「参考」というものは他人の似たような目的に対して他人の解答を自分の目的の問題を解く手がかりにするものだと思います。

一方、科学的や数学的な知見、蓄積、理論を基づく、「参考」というものとは異なるものだと考えます。それらは、言葉であり、土台であるようなものです。それらは何かの問題の「答え」ではなく、「素材」であり「手がかり」となりうるものです。前提に「似た課題」という文脈がないのです。参考と違うのは自分が解こうとしている「課題、目的、問題」との関係性が薄いといことです。

以上から

逆に、本当にある問題に関して参考にできるものが全くのゼロであったとすれば、「それはそもそも人間のパターン認識的な操作の限界を超えていて、何も作れないのでは?」という事を思います。

という点は、明確に私は異なる立場をとります。

丁寧な回答ありがとうございます。
全体を通じて、考え方/立場に関しては理解が深まりました。
総じて2点、感じた事を書きます。

  • A/Bのルートに関して

私はBのルートを意図した「自分で主体的にテーマを考えてWebアプリケーションを作る」という課題を、会社の内定者に対する教育として受け、また内定者に対して教育した事があります。これは、人によって一定の効果はあったかなと思う一方で、

  • 自分が興味を持てる課題・テーマを見つける事ができるか
  • その課題・テーマが教育の範疇にうまく収まるボリューム感のものか

という2点において、難しいなと思いました。
というのは、自分自身が実際にWebアプリを作ったとはいえ、なんかイマイチだなと思ったり、テーマが壮大過ぎて最終的に脱落する人が出たりしたからです。

前述のように、私自身が、全くの自分の興味だけであれば"本来"目的に見合ったものを見つける能力があり、かつ実際にそのような経験をしている立場にあっても、あまりうまく行かないという場合があった、ということでした。
また、私自身がA/Bの教育を受ける前からB相当の事ができた事を振り返ると、実はBの能力を作る方法はプログラミングの教育・学び方と必ずしも関係ないのでは、という事も思っています。
プログラミングを手段とすれば、プログラミングを通して主体的に物を作るという教育が自然に発生しますが、例えばその前段階としては別の方法を通じて教育をする事がより効果的だったりするかもしれません。
(例えば、NHKの番組のテキシコーというものが、"プログラミング的思考"とされるものを伝える事を目的として作られていますが、類似のアプローチがあり得るのかもしれません。)

  • GC(完全にゼロから仕組みを考えるということ)に関して

私自身も、スマートポインタの基礎的な仕組みみたいなものを自前で実装した事はあるので、"独立"な車輪の再発明自体を否定はしないのですが、既に我々の周りにはGCを使っている物やその考え方の説明がたくさんあり、また便利な道具も沢山揃っているので、それらに影響を受けて自然にGCを発想したという事かな?と私は思いました。(ただ、これはメカニズムや影響を受けたものを定量的に具体的に示す方法が無いので、私が個人としてそうかもなと思った、というぐらいの話です。)

返信ありがとうございます。だいたい議論の収束が見えてきた感じですかね。全体的に読んでて私も、なるほど、という感じで、理解できてきました。コメントに対して私の意見を述べておきます。

自分が興味を持てる課題・テーマを見つける事ができるか
その課題・テーマが教育の範疇にうまく収まるボリューム感のものか

これは私も同じ問題を抱えています。なかなか難しいですね。

現状、プログラミング教育や、プログラミングの学習は、学校的に教科書的に体系的になにかを学ぶというより、なにかを開発を通して、学ぶというのが主流になりつつあるように感じます。

それは、目的のひとつとして開発全体の流れを体験させ、プログラミング全体の輪郭を収めていくというのがあると考えます。

全体を体験させるのであれば、すでに事前に設計、計画された「開発体験」を用意すればいいという発想になりますが、それは、開発工程の補完、穴埋め作業であり、「全体を俯瞰」するには至らないのでしょう。電子工作キットみたいな、半田付けして終わりで回路の設計はしないみたいなものになりがちです。

じゃあ、出来合いの開発工程を踏ませるというのは意図した効果が出ないとなる(まったく効果がでないというわけではないです)。じゃあ、どうするかとなると、先ほどの「自分のテーマを決めて作る」って話になるかと思います。

この問題点として、結局、「開発を学ぶには、開発をするしかない」「開発できないのに、開発できるようになるには、開発するしかない」みたいなある意味矛盾した状況だなと感じます。開発することができないのに、「自分の関心の中で開発できそうなテーマで開発する」ってのは非常に難しいでしょう。

ですので、まずは体系的に学ぶ方がいいとなる人もいると思います。わたしはもっと別の道はあるだろうと模索中です。「如何に自分事としてプログラミングを学習」できるのか?というのが私にとっての最大の課題です。

(続きます

続き)

また、私自身がA/Bの教育を受ける前からB相当の事ができた事を振り返ると、実はBの能力を作る方法はプログラミングの教育・学び方と必ずしも関係ないのでは、という事も思っています。
プログラミングを手段とすれば、プログラミングを通して主体的に物を作るという教育が自然に発生しますが、例えばその前段階としては別の方法を通じて教育をする事がより効果的だったりするかもしれません。
(例えば、NHKの番組のテキシコーというものが、"プログラミング的思考"とされるものを伝える事を目的として作られていますが、類似のアプローチがあり得るのかもしれません。)

アンプラグドコンピューティングという学習の手法があります。コンピュータを介さないで、プログラミングを学ぶみたいなものですが、おそらくテキシコーと類似の事例でしょう。ちなみに、テキシコー以前にもいろんな手法で、プログラミングに直接触れず、その思考を学ぶというのはありました。

そのような手法は一定の意味はあるかもしれません。しかしながら、最終的にプログラミングに触れるということをやっておかないと効果が無いように思います。あの番組やこのような手法だけしても、プログラミングができるようになるとは思えません。私はああいうのは、やった後が大事で、そのような手法をやったあと、プログラミングに落とし込んで評価するというところまでいかないと意味がないように思います。

一方で、「教育を受けなくてもB相当のことができた」「実はBの能力を作る方法はプログラミングの教育・学び方と必ずしも関係ない」その指摘はよく分かります。プログラミングを通さずしても、その能力は培うことができるのでは?というものは私も考えます。「創造的思考」のことだと私は思っています。これらはそもそもプログラミング独自の思考ではなく、むしろ様々な人が持ち得る思考だと思っています。

実のところ、私もそもそもプログラミングに限定していません。それらは電子工作でもいい、なにかからくりを作るのでもいい、DIYしてもいい。ですが、そこに自分に関心があるなにか「つくる」という行為を経験させることが大事だと思っています。そこには新しい技術を単に学ぶのではなく、それらを用いて表現するということがBの教育の一つの目的だと考えています。

小学校でプログラミング教育が話題になっていますが、子どものプログラミングの本来の目的としては「創造的思考」を身につかせるというものがありました。それは「プログラミングのスキル」を学ばせるものではないのです。私は、プログラミングの「能力」というのは、「創造的思考」「スキル」両方の含まれています。もちろん「スキル」も重要なファクターでありますが、ここの「創造的思考」というのはもっと重要です。

創造的思考は、プログラミング以外でも重要性があると感じます。今後いろいろな人に使え、重要性が増してくるだろうと思います。だからこそ、プログラミング以外でも学ぶことは可能だと思いますが、一方で、プログラミングはそれを学ぶ手段であり、またプログラマーはそれを学ばないと真に「プログラミング」していると言えないのではないかと思っています。

もともと思った「理解の順番が逆では?」という事もそうですが、この記事に記載された理解の方法は非常に論理的というか、説明ができるような形での理解の仕方に基づいているなと思いますが、私が実感する理解というのはもっと違う形のような気がするな?というのが、ここにコメントを書こうと思ったモチベーションでした。

もちろん記事にするにあたって、ある程度説明というか論理的に整えている面は否めません。(でない限り、記事が書けない)。「ここまで書いたが割と不完全燃焼であり」というのは私も、理解に関する「現実」はもっと遠くにあるものだと考えているわけです。形にならないかもしれないが、一応形に強引に捉えてみようと思って私も記事に書きました。ですので、こういったコメントを頂けるのはとても喜ばしいことのように思います。

それは、私自身も、本質的に理解をしていない/間違った理解をしている人に対して、よりよいプログラミングの学び方みたいなものを提供できると嬉しいな、というような思いに基づいたものでした。そのため、実際に試して失敗した事なども書きながら、理解の在り方とはどういうものでしょうね、という問題を提起したかったのでした。

私はプログラミング学習や教育について携わっています。そういった意味で、理解のあり方というのは非常に重要な課題のように思えます。

以上、コメント返しとなります。ご回答ありがとうございました。

ログインするとコメントできます