レベルエンター山本大のブログ

面白いプログラミング教育を若い人たちに

BLOCKVROCKリファレンス目次はこちら

プログラミング学習は、設計を学ぶ科目だと思う

若い人(特に子供)たちにプログラミングやコンピューティングを教えることの意義について、あれこれ行ったり来たりと考えた結果、その意義は「設計の力」を鍛えることを目的にするということで良いんじゃないかと現時点で思っています。

プログラムはそもそも設計図です。

プログラミング=実装という言い方をされることもあるけれど、それは違っていてプログラミング=設計であるということはプログラマーの中では、よく知られたことです。

では、設計とは、与えられた手段(ルールや部品)を使って、目的を具現化することです。

目的があって手段があるところに、プロセスを組み立てるのを設計と呼ぶことにします。

  

手段の数を増やさずに、目的までの組み立てかたに工夫をしてもらう
この設計の習得を目的とすると、いろんな手段を教えることよりも限られた手段で、複雑なものを設計してもらうことを重視した方が学びの効果が高いと思います。

 

これは、まだプログラミングそのものの面白さに興味が持てていないような人たちを対象とした話です。

スキルとしてのプログラミングも大変有意義なので、興味がすでにある人にはもっと具体的なことを教えることが私は大事だと思います。

 

簡易HTTPツール

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<script src="https://code.jquery.com/jquery-3.4.1.min.js"
		integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
		crossorigin="anonymous"></script>
</head>
<body>
	<div>host:<input id="req_host" type="text" value="http://localhost:8080"></div>
	<div>path:<input id="req_path" type="text" value="/bookshop/ajaxtest"></div>
	<div>method:<input id="req_method" type="text" value="GET"></div>
	<div>
		message body:
		<textarea id="req_body"></textarea>
	</div>
	<div>
		<button id="req_button">送信</button>
	</div>
	<div id="response_disp">
	</div>
<script type="text/javascript">
$("#req_button").on("click",(e)=>{
	let host = $("#req_host").val();
	let path = $("#req_path").val();
	let method = $("#req_method").val();
	let body = $("#req_body").val();
	$.ajax({
		url : host + path,
		dataType: "json",
		method: method
	},body).then( e =>{
		console.log(e);
		$("#response_disp").append(JSON.stringify(e));
	}).catch( e =>{
		console.log(e.statusText , e.responseJSON)
		alert(e.statusText + " " + e.responseJSON);
	})
});
</script>
</body>
</html>

Scratch Blockly と Blockly とで違うところ(1)

Blocklyで作ったソフトをScratch Blocklyに対応させている、色々詰まるのでメモ。

 

1) Blocklyのツールボックスのカテゴリには必要な属性がなかったが、Scratch Blocklyには必須属性がある(colour・secondaryColourがないとエラー)そして、ID属性がないとクリックしてもスクロールしない

 

以下のカテゴリは正常に機能する
<Category id="test1" name="test1" colour="#FA8C1A" secondaryColour="#AB6E00" >

</Category>

 

2) 色のフィールドの変更

* FieldColourが現時点でうまく使えていない。Scratch Blocklyで新たに登場したFieldColourSliderで代用。

フィールドに色の名称(red , blue , blackなど)を指定できなくなった。CSSのカラーコード指定のみ。

 

Blockly 

 new Blockly.FieldColour("red");  // Blockly OK . Scratch Blockly Error.

 

Scratch Blockly

 new Blockly.FieldColourSlider("#FF0000"); //  Scratch Blockly OK

 

 

1年が暮れる。この1年はレベルエンターという会社と自分にとって、とても実りの多い1年だった。

 

BLOCK VROCK というサービスを開始した。

産休明けの仲間の復帰を受け入れられた。

提携レベルの協業を実現できた。

障害児童向けのプログラミング教育を定期的に実施できた。

創業1年目に教えた教え子さんをアルバイトとして受け入れられた。

会社的な(経営的な)ピンチを乗り越えられた。

教え子が経営者になるかどうかの悩みを相談できた。

12ヶ月分のScratchのゲームが作れた。

VCから投資の話が受けられた。

新しい教え子が高校生と新社会人でできた。

昔の教え子さんの結婚式に1次会から呼んでもらえた。

2次会もたくさん招いていただいた。スピーチもさせてもらえた。

たくさんの教え子さんたちと飲んだ。

 

新しく起業した会社のCTOになれた。

BLOCK VROCKを中心にしたイベントを大成功できた。

教え子や社員に任せた仕事が大成功した。

社員が思った以上に成長した。

BLOCK VROCK Version 2を用意できた。

アルバイトの仲間が増えた。

賞与をとりあえず出せた。

 

創業当時には思いもしなかったことや、当時目標や夢だったことが、徐々に実現していってる。

来年はどんな年になるか楽しみだ。

Swiftのちょっとしたメモ

PlayGroundでHTTP通信

import UIKit
import PlaygroundSupport

PlaygroundPage.current.needsIndefiniteExecution = true

let session = URLSession(configuration: .default)

var urlComponents = URLComponents(string: "http://localhost/json")!

urlComponents.query = "method=get"

let url = urlComponents.url!

let request = URLRequest(url: url)

let task = session.dataTask(with: request) { (data, response, error) in
    guard let data = data else { print("HTTP通信でエラー"); return  }

    let json = String(data: data, encoding: .utf8)!
    print(json)
}
task.resume()
session.finishTasksAndInvalidate()

オートレイアウトをコードで実装する

import UIKit

class ViewController: UIViewController {

    var sampleView: UIView!
    
    override func loadView() {
        super.loadView()
        sampleView = UIView(frame: .zero)
        sampleView.backgroundColor = UIColor.red
        sampleView.translatesAutoresizingMaskIntoConstraints = false
        self.view.addSubview(sampleView)
        
        let sa = self.view.safeAreaLayoutGuide;
        sampleView.centerXAnchor.constraint(equalTo: sa.centerXAnchor).isActive = true
        sampleView.centerYAnchor.constraint(equalTo: sa.centerYAnchor).isActive = true
        sampleView.topAnchor.constraint(equalTo: sa.topAnchor,constant: 10.0).isActive = true
        sampleView.bottomAnchor.constraint(equalTo: sa.bottomAnchor,constant: -10.0).isActive = true
        sampleView.leadingAnchor.constraint(equalTo: sa.leadingAnchor,constant: 10.0).isActive = true
        sampleView.trailingAnchor.constraint(equalTo: sa.trailingAnchor,constant: -10.0).isActive = true
    }

    override func viewDidLoad() {
        super.viewDidLoad()       
    }
}

URLカスタムスキームでのアプリ連携

プロジェクトの設定、 info -> URLTypes -> URL Schemes  「myapp」(://とかはいらない)

呼び出しボタンのアクション接続などで

let url = URL(string: "myapp://")!
let app = UIApplication.shared
app.open(url , options: [:] ,completionHandler: nil )

Node.js/Expressサイトを、AWS EC2からfirebaseに移行

コーポレートWebサイトを firebaseに移行しました。

もともと、静的ページで AWS EC2のWindowsサーバにホスティングしていましたが、

色々とメンテナンス性が悪くコストも高いので、段階的にnode.js/Express 化してfirebaseに以降、今週日曜日に移行が終わったので書きます。

 

できればあとで、参考リンクはやめて手順としてまとめます。

 

静的ページをNode.js Expressに移行することについては、割愛。

EC2上で、単なるNode.jsのサービスとして80ポートに公開していたサイトの移行です。

 

 

1.firebaseのアカウントを作る

2. firebase のプロジェクトを作る

3.ローカルの環境作る

 

ぐらいまでは以下のQiitaで調べたら特に詰まることなくできます。

簡単にできることを実感でき、firebaseの好感度が上がります。

qiita.com

 

*リアルタイムデータベースまではやりません。

 

6. Nodeの環境を作成する

7. 旧サイトをfirebase functions の形式でローカル実行する

 

これは以下のQiitaを参考にしました。

qiita.com

 

動くところまでハマりませんでした。

 

ちょっとハマったのは、デプロイです。

8.firebaseにデプロイする

エラーメッセージで「dependencies」にexpressが入ってないと怒られました。

ローカルではnpm i -Dで依存ライブラリをsaveしていたので「devDependencies」にはいっていいました。

firebaseがきちんと怒ってくれていることに気づかず、いろんなことを調べてしまいました。

エラーメッセージを額面通り受け取れなくなったのは主にMicrosoftさんのせいだと思っています。

 

9. リライトの設定

firebase functionsは、RESTなAPIを作ることがメインなのでhostingするには冗長なURL構成になります。

firebase.jsonでリライトの設定をすることで、https://ホスト名/以下がnode.jsの呼び出しと一致するようになります。

{
"hosting": {
"public": "public",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
,"rewrites": [
{
"source": "/**",
"function": "app"
}
]

},
 

"functions": {
"predeploy": [
"npm --prefix \"$RESOURCE_DIR\" run lint"
],
"source": "functions"
}
}

 

以下のNode.jsのappを/**に当てはめるというリライトの記述です(/*だとホスト名以下1階層しか見てくれない)

exports.app = functions.https.onRequest(app);
でexportsのappに、書き出したfunctionsのオブジェクトが、URLのリクエストに応答してくれます。
 
10. imageやcss/jsなどのリソースの配置
 hosting 配下のpublicなどにcssやjs,imgなどは配置します。(functions側 のpublicに置きがち)
 
11.  DNSを書き換えます。(firebaseのhostingにある「ドメインの接続」にしたがってやる)
  →ちょうど2時間待たされたので、ドキドキした。
 
以上です。
 
 
 

プログラミング教育の目的は、職業訓練ではなく課題解決力であるとは本当か?

子供向けのプログラミング教育については特に、職業訓練ではないのだからプログラミングスキルを身につけることを目的にしてはいけない。課題解決力を身につけることを目的にするべきだ。

 

上記のようなことは、子供向けプログラミング教育を義務教育化するなかで、すごく言われていることです。

 

確かに、若い人が「目的」に据えるのはできれば応用の効く抽象的なスキルであるほうがよいでしょう。

だが、教育する側として現場にいると、そんなことで子供は付いてくるだろうかという感覚になります。

 

例え話に引きずられすぎるのはよくないとしても、考える角度を変えるには良いでしょうから、英語教育に例えて考えてみます。

 

プログラミングに関する冒頭の文は英語教育に置き換えると以下のようになるかと思います。

子供向けに英語教育を行う目的は、職業訓練ではないのだから会話スキルを身につけることを目的にしてはいけない。国際感覚を身につけることを目的にするべきだ。

 

この目的をもって英語教育をやった結果、日本の英語教育はどうなったでしょうか。

綺麗な文法にやたらと気を取られて、「会話スキルは全く育っていない。」「外国の人と話すことは怖い」となっていないでしょうか。極論でした。話を戻します。

 

考えたいのは、目的としている抽象概念に到達するためにも、スキルを習得することも大事なのではないかということです。

 

別の角度で、RPGに例えます。

目的は大魔王を倒すことだとして、レベルアップの実感のないRPGは続かないと思います。

「スキル習得」は興味や関心を維持していくための、ゲームでいう魅力付けの要素です。

 

だからプログラミング教育についても、目的は「課題解決力をつける」でよいとしても、時代にあったスキルを適切に身につけていくことを、除外しなくて良いのではないでしょうか。

 

そもそも冒頭の文章で「スキルをつけることを除外しているわけではない」のですが、目的一直線では現実的ではないなと思う今日この頃です。