家庭での小学生向けプログラミング教育についてまとめと、考察
要約と結論
- 小学生向けプログラミング教育では、実用的なコードが書けるようにはならない。
- そもそも小学生向けプログラミング教育は、プログラミング「技術」の習得が目的ではない。
- コンピュータを目的に応じて、制御できることを知る、体験する、ということが目的。
このような性質上、学習効果が客観的判断がしづらい領域なので、あえて義務教育外でやる(家庭で教材を利用したり、スクールに通わせたりする)場合は、子どもに具体的な技能向上を、過度に期待すべきではない。それよりも、子どもが楽しめることを重視し、その上でそれをやらせるか否かの判断は、各家庭が許容できるコストで考えればよい。
注)2017/11現在の私見です。
背景 - プログラミング教育について、考えはじめる
私には小2の娘がいるのですが、先日、奥さんから、とあるプログラミング通信教材を提示され「2020年からプログラミングが必修になるので、娘にコレやらせてみようと考えてる。はじめたら、みて教えてあげてくれない?」と相談されました。中身をざっと見たところ、簡単なロボットを組み立てて、iPad上のビジュアルプログラミング環境でプログラミングして、ロボットの制御を行うというもの。Web系の職業プログラマやっている自分の第一印象としては「おもちゃとしては面白いが、これでプログラミングができるようになるとは、思えない(のであまり意味がない)」でした。
ところで、よくよく考えてみると、私の考えている「プログラミング」も相当限定的で、例えば私の場合、WebサービスやiOSアプリを作ることはできるが、PS4のゲームや、電子レンジの制御プログラムは作れないわけです。そのような限定された認識で「プログラミングができるようにはならない」という判断をするのは、早計ではないか。さらには昨今の「プログラミング教育」自体について、よく調べたわけでもないのに、教材の良し悪しを判断するのもどうかな、と思ったわけで、ちょっと調べてみました。
小学生のプログラミング教育とは
私は普段プログラミングを仕事にしているわけですが、その立場で考える「プログラミングの勉強」とは、プログラミング言語の習得、アルゴリズムやネットワークプロトコルの理解、具体的な開発ツールの使用方法の習得、などが挙げられます。当然、これらは私個人のコンテキストに強く依存する考えで「小学生のプログラミング教育」とは別なはずです。では「小学生のプログラミング教育」とは具体的にどのようなものか。文部科学省が公開している資料を調べると、以下のようなものが見つかります。
小学校段階におけるプログラミング教育の在り方について(議論の取りまとめ):文部科学省
いくつか興味深い箇所を抜粋します。
プログラミング教育とは、子供たちに、コンピュータに意図した処理を行うよう指示することができるということを体験させながら、将来どのような職業に就くとしても、時代を超えて普遍的に求められる力としての「プログラミング的思考」などを育むことであり、コーディングを覚えることが目的ではない。
(中略)
子供たちが、情報技術を効果的に活用しながら、論理的・創造的に思考し課題を発見・解決していくためには、コンピュータの働きを理解しながら、それが自らの問題解決にどのように活用できるかをイメージし、意図する処理がどのようにすればコンピュータに伝えられるか、さらに、コンピュータを介してどのように現実世界に働きかけることができるのかを考えることが重要になる。
(中略)
小学校におけるプログラミング教育が目指すのは、前述のように、子供たちが、コンピュータに意図した処理を行うよう指示することができるということを体験しながら、身近な生活でコンピュータが活用されていることや、問題の解決には必要な手順があることに気付くこと、各教科等で育まれる思考力を基盤としながら基礎的な「プログラミング的思考」を身に付けること、コンピュータの働きを自分の生活に生かそうとする態度を身に付けることである。
(中略)
プログラミング教育の実施に当たっては、コーディングを覚えることが目的ではないことを明確に共有していくことが不可欠である。
抑えておきたいポイントは
- 具体的なプログラミング技術(コーディング)を習得するものではない。
- コンピュータを制御する体験と、その際の考え方(しばしば「プログラミング的思考」と言及される)を学ぶ。
です。これは算数や国語のように、学習効果がテストによる採点で明確になるものとは、ちょっと性質が違う学習領域です。
体験と考え方の学習
わたしの小2の娘は、オクラを小さな鉢で育てて、収穫するまでを、小学校でやったのですが、これは体験と考え方を学ぶ類の教育だと思っています。つまり、植物が実際にどう育っていくかを体験し、土に植えて、水をあげ、太陽にあてるという手順や、植物栽培の基本的な考え方、を学ぶわけです。
この記事の最初の方に書いた、職業プログラマとして「これでプログラミングができるようになるとは、思えない」というプログラミング教育への第一印象ですが、先程のオクラ栽培に、当てはめて考えてみると「オクラをこんな小さい鉢で育てても、実際の農業ができるようになるとは、思えない」と言っているのに近いわけです。それは当然のことで、初等教育では実践的な農業技術を、習得させる必要なんてないからです。
私たちの生活に、今や当たり前に存在するもの、その成り立ちやしくみを体験を通して知ることは、とても重要です。現代において、その領域にコンピュータシステムが含まれたというのが、プログラミング教育の意義だと理解しました。技能の習得を重視する、より高度な教育は中等、高等教育、あるいは本人がより深く興味をもった時に行えばいいのでしょう。
プログラミング教材、教室など(小学生低学年むけ)
さて、プログラミング教育の意義を認めたところで、プログラミング教室や教材、実践事例などをいくつか調べてみました(私の娘が小2なので高学年向けや中等教育以降を対象にしたものは、基本的に除外しました)。以下は参考にした外部サイトです。
簡単にまとめると
- ビジュアルプログラミング環境の利用が多い。
- 特にScratchの利用がよくみられる。
- ビジュアルプログラミングの入力端末にタブレットを使用するパターンも多い。
- 工作や簡単なロボット制作などと合わせて、物理デバイスの制御をプログラミングで体験させるパターンも多い。
- もっとも簡単な事例では、タブレット上でのビジュアルプログラミングで絵を動かすというもの。
以下が私の雑感となります。
- 前述した文部科学省のプログラミング教育に基づくのであれば、総じて妥当だと思えるカリキュラムが多い(私が奥さんから提示された教材も、妥当だと思いました)。
- 特に物理デバイスの操作をプログラミングするのは、体験として良さそうにみえる(私の娘が工作好きなのと、物理的なものを実際に動かせるというのは、興味を引きそう)。
- プログラミング教育教室の料金(月額1万あたりが多い)は、総じて高額かなと思う。
ちなみに、これを期に簡単な電子工作的なものを自分でやってみて、それを娘に教えてみればどうかな、と思いつき、Raspberry PIを買ってみましたが、1から始めるとなると、他にも初期セットアップ用のモニタやキーボード、マウス、入門書、電子工作用基本パーツセットとかが必要で、すでに2万円ほどかかってしまいました。また自分で、いろいろ調査する時間もかかってしまいます。私の場合は、私自身の趣味と勉強も兼ねているので、いいのですが。
いずれにしろ、前述したように、初等学級の子どもに対するプログラミング教育は、技術習得の場ではなく、体験すること自体が主たる学習内容になるので、そこに明確な成果を求めると、残念な結果になるかもしれません。端的に言うと「プログラミング教室に通ったら、PCが使えるようになって、将来IT系の仕事にこまらなくなる」と考えるのは、間違っているということです。義務教育外でお金を払ってやるのであれば、子どもが楽しんでやれることが、最重要で、そうでなければ、継続してやる必要性はないと思います。本人がつまらないと、体験としては、あまり得るものがないのではないかと思います。
これを踏まえて、あとは金銭コストに親が納得できればよいかなと思います。
それで、どうしたか
結局、私の家ではどうしたかというと、ひとまず今年、2017年内までは保留としてます。私が一度、自分で電子工作してみて、多少なりとも、何か教えられそうなら、まずそれをやらせてみようかな、と思っているためです。それで、うまくいかなかったら(私が教えられそうにないなら)、教材の利用を、わりと前向きに考えています。
ちなみに奥さんに見せてもらった教材はこれです。
組み立てキットが2万5千円くらいします。高いとは思うのですが、私がいま揃えているRaspberry PI関連もすでに2万ちかくになっているので、まあ必要な価格と判断。あと専用のテキストやカリキュラムなどがあることを考えると、月5000くらいなら許容範囲かな、と考えてます。自分でなにか教えるとなると、子どもの興味を引くように、この辺もちゃんと考えなければならないのですし。
ただ、外部のプログラミング教室に通うとなると、月々1万〜と高額、親による送り迎えも必要になると思うので、ウチでは今のところ考えていません。
余談
でも小学校は、プログラミング教育の前に「連絡帳」とかいう物理媒体の運用を廃止して、直ちに電子化してほしい。
最新のGit-2.14.1のRPMを提供するyumレポジトリを立てた (CVE-2017-1000117対策)
cve-2017-1000117への対応として、GitをアップデートしたいのだけどCentOSの公式の対応がよくわからない。とりいそぎ自前でgit-2.14.1のRPM作ってyumリポジトリをgithub pagesで立てた。
以下のコマンドでcve-2017-1000117の対応がなされたgit-2.14.1が入る。
$ sudo sh -c 'echo "[kohkimakimoto-git-update-el7-x86_64] name=kohkimakimoto-git-update-el7-x86_64 baseurl=https://kohkimakimoto.github.io/yumrepo-git-update/el7-x86_64 gpgcheck=0 enabled=0 " > /etc/yum.repos.d/kohkimakimoto-git-update-el7-x86_64.repo' $ sudo yum update --enablerepo=kohkimakimoto-git-update-el7-x86_64 git
RPMの作り方は
CentOSでGit v2系をRPMで作成する | 本日も乙
を参考にさせていただいた。感謝。
Githubのリポジトリをyumリポジトリとして使う
簡単にできた。手順は後ほど。
背景
普段使っているサーバOSはCentOSなので、自作のOSSツールなどをyumコマンドを使ってさくっとインストールしたい。RPMを作るところまではスクリプト化してあって一発でできるようになっている。yumリポジトリをどうするか。今まではbintrayで個人用のyumリポジトリを立てて使っていました。
ところが、先日このbintrayのyumリポジトリから古くてもう使っていないパッケージを削除しようとしたところ「公開後180日たつと削除できない」とエラーになってしまいました。
昔作ったOSSのRPMパッケージをbintrayにホストしてたのだけど、もう使ってないしソースもgithub上から消したので、bintrayからも消そうとしたら、できなくて混乱している。
— こうきん (@kohkimakimoto) 2017年7月16日
パッケージの削除は最初のバージョンをホストしてから180日以内でないとできないってエラーになるのだけど、なぜにこの仕様なんだろうか。普通に不便で、ゴミがたまり続けてしまうのだけど。
— こうきん (@kohkimakimoto) 2017年7月16日
結局この後、bintrayのサポートに問い合わせてみたら、わりとすぐに削除してくれたのですが、今後パッケージが要らなくなって消そうとするたびに、問い合わせしなくてはならないのかな、、、と思うとちょっとツライです。
そんなわけで代替となるyumリポジトリをホストしてくれるサービスを探していたりしました。packagecloud.ioなどを見てみましたが、いまひとつ使う気になれず。。。
そこで昔yumリポジトリを個人サーバに立てたときのことを思い出してみると、結局必要だったのはただのhttpサーバだけだったはずでは。それならGithub Pagesを使えばGithub上にyumリポジトリも立てられるんじゃないかなと思い至り、ちょっとググったら、かなり前にやっぱり同じことをやっている人がいた。
この記事を参考にして、今はgh-pages
のブランチを切る必要もないし、SSLも対応しているので、その辺をふまえて以下のようにやりました。
作業手順
Githubにリポジトリを作る
何でもいいですが、ここではリポジトリ名はyumrepo-example
とします。作成後リポジトリの設定画面からGithub Pagesの設定をします。Sourceをmasterブランチに設定すれば昔のようにgh-pages
のブランチを切る必要もないです。
リポジトリをcloneしてRPMファイルを配置する
上記のリポジトリをローカルにcloneし、サポートするディストリビューションやアーキテクチャなどで、適当にサブディレクトリを作成してその中にホストしたいRPMファイルをおきます。試しに拙作であるプロビジョニングツールのcofuのRPMを
https://github.com/kohkimakimoto/cofu/releases
からダウンロードしてCentOS6とCentOS7用に配置します
$ mkdir el6-x86_64 el7-x86_64 $ curl -L -o el6-x86_64/cofu-0.6.0-1.el6.x86_64.rpm https://github.com/kohkimakimoto/cofu/releases/download/v0.6.0/cofu-0.6.0-1.el6.x86_64.rpm $ curl -L -o el7-x86_64/cofu-0.6.0-1.el7.x86_64.rpm https://github.com/kohkimakimoto/cofu/releases/download/v0.6.0/cofu-0.6.0-1.el7.x86_64.rpm
createrepoコマンドでリポジトリのメタファイルを作る
createrepo
コマンドでyumリポジトリに必要なメタファイルを生成します。Macで直接動作するcreaterepo
コマンドはないのですが、dockerを使えばこのあたりも簡単にできます。以下のようにしてbashスクリプトをcreaterepo
として作成します。
$ echo '#!/usr/bin/env bash docker run --rm -u "$(id -u):$(id -g)" -v $PWD:/build -w /build kohkimakimoto/rpmbuild:el7 createrepo "$@"' > createrepo $ chmod 755 createrepo
そして、RPMを配置したサブディレクトリを指定して実行します。
$ ./createrepo el6-x86_64 Spawning worker 0 with 1 pkgs Spawning worker 1 with 0 pkgs Spawning worker 2 with 0 pkgs Spawning worker 3 with 0 pkgs Workers Finished Saving Primary metadata Saving file lists metadata Saving other metadata Generating sqlite DBs Sqlite DBs complete $ ./createrepo el7-x86_64 Spawning worker 0 with 1 pkgs Spawning worker 1 with 0 pkgs Spawning worker 2 with 0 pkgs Spawning worker 3 with 0 pkgs Workers Finished Saving Primary metadata Saving file lists metadata Saving other metadata Generating sqlite DBs Sqlite DBs complete
後はコミットしてpushすれば完了です。なおRPMを更新したら都度同じようにcreaterepo
スクリプトを実行してメタファイルも更新します。
yumでインストールしてみる
リポジトリができたのでyumでインストールしてみます。以下の例はCentOS7でやった際のもの。リポジトリのパスなどは適宜読み替えてください。
まずリポジトリの設定をして
$ sudo sh -c 'echo "[github-yumrepo-example-el7-x86_64] name=github-yumrepo-example-el7-x86_64 baseurl=https://kohkimakimoto.github.io/yumrepo-example/el7-x86_64 gpgcheck=0 enabled=1 " > /etc/yum.repos.d/github-yumrepo-example-el7-x86_64.repo'
あとは普通にyum installする
$ sudo yum install cofu
以上です。サンプルのリポジトリは以下においておきます。
開発環境用に自己署名SSL証明書をつくるスクリプトを書いた
外部からアクセスできるサーバ環境の場合はLet’s Encryptを使うことで手軽にSSL証明書を設定できるようになったのですが、ローカルマシンにVagrantでたてた開発用VMの場合はそうもいかず、この場合は自己署名のSSL証明書をつかっています。
証明書の発行は普通にopensslコマンドを手作業で叩いてやってたんですが、
- Chromeだと
-extfile
オプションで追加のパラメータを指定しないと、Macのキーチェーンにインストールした自己署名証明書がエラーになるので、すこし作業の手間が増えた - ローカル環境への名前解決をxip.ioなどのワイルドカードDNSを使うようになって、利用するホスト名が
myapp.192.168.0.10.xip.io
,myapp2.192.168.0.10.xip.io
のように多くなった - xip.ioで名前解決する構成上、サブドメインへの階層が深くなりワイルドカードの証明書が使えなくなったため、ドメイン名ごとに証明書を発行する必要がある
などの理由で、作業がちょっと煩雑になってきたのでスクリプト化しました。
Bashスクリプト実装です。引数にドメイン名を指定して(複数指定も可)実行すると
$ selfsigned-crt example.com
以下のように秘密鍵、CSR、証明書を吐き出します。有効期限は100年。
example.com-selfsigned.key example.com-selfsigned.csr example.com-selfsigned.crt
あとはこの生成した証明書をサーバに配置すればいいのですが、自分の場合、開発環境のプロビジョニングツールに、このスクリプトを実行させるようにレシピを書いておいて、証明書の生成もプロビジョニングツールにやらせてます。自作ツールのcofuを使うと以下のような感じ、
execute "generate-self-signed-ssl" { command = [=[ selfsigned-crt -o /etc/nginx/ssl myapp1.192.168.1.10.xip.io ]=], not_if = "test -f /etc/nginx/ssl/myapp1.192.168.1.10.xip.io-selfsigned.crt", }
これで開発環境をセットアップするときに、自動的に証明書も作成できるようなりました。
関連外部リンク
Visual Studio CodeからMacの辞書(Dictionary.app)を開くエクステンションをつくった
SSHラッパーコマンドEsshのv1.0.0をリリースしました
Esshは、zsh補完やLuaスクリプトによる動的なコンフィグレーションなど、便利機能を実装した、sshのラッパーコマンドです。
ドキュメントをまとめたWebサイトも作成しました。
上記Webサイトのトップにasciinemaで撮ったターミナルオペレーションのデモを乗せましたので、そちらを見ていただければ、どういったものか大体のことはわかると思います。
開発の経緯
2015/11に以下の記事を書き、Zsshというコマンドを作成しました。
その後、CentOSのリポジトリにzssh
というパッケージが存在していたため、コマンド名をzssh
からessh
に変え、自分の利用にあわせて、適宜、機能の追加や変更を続けていました。そして、自分が使う上で必要十分な機能がそろって、大きな変更もなくなってきたので、この度これをv1.0.0
としてリリースすることにしました。なお2015/11時点のものとは仕様が大きく様変わりしており、以下に改めて、機能について説明します。
機能
EsshはGoで書かれたシングルバイナリのCLIツールで多機能sshコマンドとして利用できます。実装的には内部でssh
コマンドを実行するラッパーコマンドになっています。標準のsshコマンドでは使えない以下のような機能が利用できます。
- Luaによる設定ファイル。これによりSSH接続サーバの設定(ssh_config)をより動的に構築することができる。
- サーバ接続、切断時に発火するフックコマンドを設定できる。
- サーバにタグをつけられ、一覧をターミナルに出力できる。
- ZshとBash用の強力な補完を組み込みで提供。
- カレントディレクトリごとに設定ファイルの切り替え。
- Capistranoのような複数サーバに並行してコマンドを実行できるタスクランナー。
- 設定用のLuaコードはモジュールとしてGitリポジトリ上で共有できる。
一通りの機能に触れるためのチュートリアルを用意したので、利用の際はここから始めるとよいかと思います。
https://essh.sitespread.net/intro/ja/index.html
利用例
上記のチュートリアルには書いていないが、私個人が使っている機能などを中心にいくつか紹介します。
ログイン時にターミナルの色を変える
接続、切断時のフックコマンドhooks_before_connect
とhooks_after_disconnect
でターミナルの色を変えます。私は本番環境につなぐときは赤にしています。
-- ~/.essh/config.lua -- 事前にmacのターミナル設定でRedとBlackというプロファイルを作っておく local red_screen_command = "osascript -e 'tell application \"Terminal\" to set current settings of first window to settings set \"Red\"'" local black_screen_command = "osascript -e 'tell application \"Terminal\" to set current settings of first window to settings set \"Black\"'" host "webserver-01" { HostName = "192.168.56.32", Port = "22", User = "kohkimakimoto", description = "web server-01", hooks_before_connect = { red_screen_command }, hooks_after_disconnect = { black_screen_command }, tags = { "web", }, } host "webserver-02" { HostName = "192.168.56.33", Port = "22", User = "kohkimakimoto", description = "web server-02", hooks_before_connect = { red_screen_command }, hooks_after_disconnect = { black_screen_command }, tags = { "web", }, }
アプリケーションのデプロイ
リモートサーバにコマンドを実行します。以下はただのサンプルです。実環境ではもっと複雑なスクリプトを実行させています。
host "webserver-01" { HostName = "192.168.56.32", Port = "22", User = "kohkimakimoto", description = "web server-01", tags = { "web", }, } host "webserver-02" { HostName = "192.168.56.33", Port = "22", User = "kohkimakimoto", description = "web server-02", tags = { "web", }, } task "deploy" { backend = "remote", targets = {"web"}, prefix = true, parallel = true, script = [=[ echo "deploy app to $ESSH_HOSTNAME" # your deploy commands... echo "Done." ]=], }
以上です。日々のSSHライフのお供に、どうぞお使いください。m( )m
ReactNativeのiOSアプリをオフラインの実機で動かす
※2017-04-10現在のメモ。
先に結論。以下の#if !(TARGET_IPHONE_SIMULATOR)
で囲った部分のコードをios/AppName/AppDelegate.m
に仕込むといいです。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSURL *jsCodeLocation; #if !(TARGET_IPHONE_SIMULATOR) jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; #else jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil]; #endif RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation moduleName:@"AppName" initialProperties:nil launchOptions:launchOptions]; rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; UIViewController *rootViewController = [UIViewController new]; rootViewController.view = rootView; self.window.rootViewController = rootViewController; [self.window makeKeyAndVisible]; return YES; }
経緯
ReactNativeでiOSアプリを作ってみてます。SwiftやObjective-Cで作ったアプリのように、開発中のアプリをUSBケーブルにつないだiPhoneにインストールして、動作確認してみようとしたら、うまくアプリが立ち上がらない。ドキュメントやGithubのissuesをみるとiPhoneが同じwifiにいないと動作しないらしいです。
「react native offline」とかで検索するとstackoverflowやgithubのissuesで、対処法が書いてあるが、今ひとつうまくいかない。というか、ReactNativeの更新が速いせいか、いまでは通用しない古い情報がまじっていてよくわからないです。で、Objective-Cは以前触ったこともあってソースが読めるので、直接ソースを追ってみました。それでわかったこととして
- 開発中ReactNativeは開発マシン上にhttpサーバを起動し、アプリはこのhttpサーバからJavaScriptコードを取得する。
- この仕組みのおかげで、開発中再ビルドなしで、変更を反映させられる。実機の場合も同様だが、オフラインだとhttpサーバに到達できず、エラーになる。
- ビルド時、リリースビルド用にJavaScriptを一つのファイルにまとめてアプリにバンドルするスクリプトが、XCodeのrun scriptで定義されている。
- リリースビルドの場合のみ、httpサーバからではなくファイルからJavaScriptを読むようにマクロで制御されている。
というわけで冒頭に記載したようにios/AppName/AppDelegate.m
内のコードを
#if !(TARGET_IPHONE_SIMULATOR) jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; #endif
のようにして「シミュレータ以外のとき」という条件で、JavaScriptのロケーションを設定している変数を、リリースビルドのときと同様に、バンドルされたJavaScriptファイルを読みに行くよう上書きすればOKです。この場合当然、実機上で動かすと、再ビルドなしでコードの変更を反映させることはできなくなるので、それが必要なときは都度この部分を削除やコメントアウトするなりして、対応すればいいかな、と。今のところは。