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

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

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は続かないと思います。

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

 

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

 

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

 

 

 

ブログを統合した

数年前まで、はてなダイアリーでブログを書いていましたが、起業と前後してはてなブログに移行しました。

とはいえはてなブログでは、あまり記事を書いていませんでした。

はてなダイアリーがサービス終了と聞き、同時にはてなブログにブログのインポートという機能があると聞いてこの度統合しました。

特に学びのあるエントリではありませんが、ぼちぼちやります。

プログラミングを教えるときに余計なことを教えすぎ説(またはプログラミングを嫌いにならないコツ)

件名通り。プログラミングの教育をやっていて、本当に余計なこと、、、というか段階に合わないことを一気に教えすぎ。

 

例えば変数を教えるときに、はじめに教えるべきなのは代入と参照の2つでいい。

そこに無理に基本型のサイズとか、参照型とか一気にやりすぎる。

 

ループもとりあえずforを教えて使い方に慣れるようにすればいい。

文法のバリエーションなど問題ではない、最初に学ぶべきは概念。そして手慣れ感。

まるで足し算がわからない時点で掛け算を教えるような感じ。

whileとかdo whileとか教えちゃう。そういうバリエーションはあとでいい。

 

最悪はオブジェクト指向、最初はインスタンス化や、フィールドの参照でいい。

メソッドすらあとでいい。

なのに一気に継承やらポリモフィズムやらをやる。

これは多分生徒からすると、初めて九九を習った次の瞬間に指数をやるようなもので、あまりにも一足跳びすぎる。

 

子供達と学んでいて、本当に思うのは、小学校や中学校までは発達段階に応じた学習段階を踏むが、それ以降はいきなりスピードが上がりすぎる。

 

プログラミングを嫌いにならないコツは、徐々にステップアップすることだ。

Swift 関数とオプショナルの解説を覚書

オプショナルについて

他言語を知っているひとがSwiftを学ぶときに、一番最初につまるのはオプショナルだと思います。

Swiftでは普通の型(IntやStringや自作クラス型などほとんどの型)ではnil (=null)を代入できません。

nilは非常に特殊な状態であると言語仕様で利用を制限し、コンパイラnilチェックを強制してくれることで、「nil安全」なプログラミングを書けるようにしてくれています。


このオプショナルについて、Playgroundで、簡単なサンプルを見てみましょう。
まずは普通の変数や定数を定義して、nilを代入してみます。

import Foundation

// 普通の変数の宣言
var a:Int

//a = nil // 普通の変数にnilを入れるとコンパイルエラー(コメントアウトを外して実行してみてください。)

// Swiftは関数型言語であり、可能な限り定数letを使うことを推奨している。理由は汚染されないから。
// letは定数を宣言するキーワード
// ここでは宣言と初期化を同時に実施
let aLet: Int = 100

// let bLet:Int = nil // let であっても普通の定数にnilを入れることはできない

オプショナル型変数の宣言と利用

普通の変数にはnilが入れられないことが確認できたので、オプショナル型を作ってnilを入れてみます。
オプショナル型の宣言は「Optional<元の型>」とするやり方と「元の型?」とするやり方の2通りがあり、後者の?をつける方が一般的です。

var b:Optional<Int>  // nilが入れるのはOptional型のみ、元の型はジェネリックタイプとして定義
b = nil  // オプショナルなのでnilが入ることができる
b = 10 // オプショナル型にはジェネリックタイプ(今回はInt)の型のデータも入る
print(b) // Optional(10)と表示されるはず、これは単なる10ではなくOptionalに包まれた(wrapされた)変数であることを表す
 
var b2: Int? // オプショナル型の省略記法(こっちの方がメジャー)
b2 = nil // オプショナルなのでnilが入ることができる
b2 = 100
print(b2) 

 

オプショナル型変数・定数から元の型データを取り出す

オプショナル型変数からデータを取り出すには、if let 構文によるオプショナルバインディングを使います。
オプショナルから値を取り出して定数に束縛するということで、オプショナルバインディングと言います。

// オプショナルの解除(アンラッピング)
if let b3 = b2 {
    print(b3)
}


オプショナルバインディングは、新たな名前の定数にバインドするのではなく、元の定数や変数名と同じ名前でバインドすることが推奨されます。
誤ってバインド前の要素にアクセスできないようにするためです。

if let b2 = b2 { // アンラップするときは同じ定数名を使うことが推奨
    print(b2)
}


!マークはオプショナルの強制解除に利用します。nilが入っていたら実行時例外が発生してアプリが落ちます。
!マークは、Swift言語なかで頻繁に登場しますが、異常があれば実行時例外にするという仕様は一貫しています。
!マークは、オプショナルなどを無視するために記述するキーワードなので、コードレビューで!マークを中心に気をつけて読むということも観点にできると思います。

// オプショナルの強制解除
print(b!) // もしnilなら実行時エラー

// オプショナル宣言だが、参照すると自動的に強制解除になる宣言方法
var c: Int!
c = 20
print(c) // もしnilなら実行時エラー

関数と高階関数クロージャ

オプショナルのルールがある程度わかると、次は関数周りです。
関数型の考え方も随分一般的になったと思いますが、Javaだけをやってきたというような人には馴染みが薄いかもしれません。

関数の定義方法(基本)

Swiftの関数は、引数に「外部名」と呼ばれる「呼び出し側」用の引数ラベルをつけることが特徴的です。
関数は、クラスなどに依存せずに記述できます。

import Foundation 

// func 関数名(外部名 内部名:型, ・・・・)->戻り値型

func point(left x: Int ,top y:Int ) -> String {
    return "ポイント x位置:\(x) y位置:\(y) "
}

// 呼び出し側では、外部名を引数ラベルとして記述する必要がある
var p = point( left:10, top:10 )
print(p)

外部名があることで、呼び出し側のコードだけを見て何をやっているかが、はっきりわかるのがいいですね。
引数が多いときに特に便利です。
 

関数の定義の際に外部名を改めてつけるのがめんどくさいというシーンもあります。
定義側で、外部名を省略すると内部名が外部名を兼ねるようになります。

import Foundation 

// 外部名省略すると、内部名が外部名を兼ねる
func line(top: Int, left: Int, size:Int) -> String{
    return point(left:left, top:top ) + "からSize: \(size)の線"
}

// 呼び出し時、内部名が外部名を兼ねる
let ln  = line(top:10, left:30, size:10)
print(ln)


引数の数が1個だけなどの場合、外部名を書かなくてもわかるようなときには、
呼び出し時の外部名指定を省略可能にすることもできます。
外部名の部分に「_」(アンダースコア)を書きます。

// 呼び出し時の外部名を省略可能にする(同じ名前の関数も外部名が異なれば定義可能 オーバーロード)
func circle(_ x: Int , _ y: Int, _ radius:Int) -> String {
    return "中心(x:\(x) y:\(y) ) 半径\(radius)"
}

// 呼び出し方法
let circle1 = circle(10,20,5)
print(circle1)

関数を変数に代入する

関数がフォーストクラスオブジェクトであり、オブジェクトやクラスなどに依存せずに存在できます。
もっと簡単に言えば、関数を変数に代入できます。

//(続き)

// 前に定義したline関数をdraw変数に代入。
var draw = line;

// 呼びだしかた
// キーワードラベルは消える
let d = draw(10,10,200)
print(d)

関数を引数にとる関数(高階関数

関数を変数に入れられるということは、関数の呼び出し時に引数として渡すことも可能ということです。
関数を引数にとる関数のことを高階関数と呼びます。

処理の一部をコールバックとして定義しておくことができます。
または、コマンドパターンを関数だけで実現できます。

// 引数に関数を取る関数(高階関数)
func payment(action calcFunc: (Double) -> Double ){
    let salary = calcFunc(200_000)
    print("支給額は、\(salary)")
}
 
//
func payOrdinal(salary:Double) -> Double{
    return salary * 0.9
}

// 事前定義した関数を渡して高階関数を呼ぶ(関数は第1級オブジェクトなので変数のように使える)
payment(action: payOrdinal )


クロージャーは無名の関数のことです。」とSwiftでは割り切って言い切っています。
高階関数の呼び出し時に、クロージャーは便利です。

//高階関数の呼び出しにクロージャを使う
paymentSalary(method: {(salary: Double ) -> Double in
    let insurance = salary * 0.13;
    return salary - insurance;
})


// 引数の型、戻り値の型は自明なので省略可能、その際、引数の()も省略できる。
// 処理が1行ならreturn も省略可能
payment( action: { salary in salary })
 

// 引数リストの最後の引数がクロージャなら引数の()の外に追い出せる
payment() { salary in salary * 2 }


// クロージャを追い出したあと、引数が残っていなければ()も省略可能
payment { salary in salary * 3 }
 

 

例外を発生する可能性のある関数

try? またはtry! またはdo{ try } catch で処理する必要がある

import Foundation

func devider(a:Int ,b:Int) throws -> Int{
    if b == 0 {
        throw NSError(domain: "zero divide メッセージ", code: -1, userInfo: nil)
    }
    return a / b
}

// try?をつけて呼び出しエラー時はnilが帰ってくるので、受け取る型をオプショナルにする必要がある
let i :Int? = try? devider(a: 1, b: 0 )
print(i)


// try!をつけて呼び出しエラー時は実行時例外が帰る、受け取る型は普通の型でよい。
let i2 :Int = try! devider(a: 1, b: 0 )


// do { try } catch {}で呼び出し 
do{
    let d3 = try devider(a: 10, b: 0)
    print(d3)
} catch let error {
    print("例外処理" + error.localizedDescription );
}

 

コンピュテーショナルシンキングについての学習ルート

最近ずっと僕が取り憑かれているコンピュテーショナルシンキングとは、コンピュータサイエンティストの思考法という解釈がしっくり来ます。

Google for Educationでも重要な指針として認められている考え方です。

 

edu.google.com

 

主なコンセプトは、以下です。(Google for Educationより)

抽象化

主要なアイデアを定義するために関連情報を特定して抽出する

アルゴリズム設計

類似の問題を解決するため、またはタスクを実行するための一連の命令を作成する

自動化

コンピュータや機械に繰り返しの作業をさせる

データ分析

パターンを見つけたり洞察を深めたりしてデータを理解する

データ収集

情報の収集

データ表現

適切なグラフ、図表、言葉、または画像でデータを描き、整理する

分解

データ、プロセス、または問題を小さく管理しやすい部分に分割する

並列化

より大きなタスクからより効率的に共通の目標に到達するための小規模なタスクの同時処理

パターンの一般化

予測された結果をテストするために、モデル、ルール、原則、または観察パターンの理論を作成する

パターン認識

データのパターン、傾向、規則性を見出す

シミュレーション

実世界のプロセスを模倣するモデルをつくる

 

プログラミングというよりも、システム設計の分野で使われている考え方とした方が良いかもしれません。

 

 

 今後は、システム設計の学習方法について考えます。

 

コンピュテーショナルシンキングをSEの世界で考える

コンピュテーショナルシンキングを習得する授業を高校向けにやっていきましょうという話をしていて、コンピュテーショナルシンキングについてシステムエンジニアではない人にどうやって説明するかについて気づきを得たのでメモしていきます。

 

コンピュテーショナルな考え方とは、「システムの設計」的な思考だと言い換えるとわかりやすいと感じました。

 

システムとは、以下のようなものです。

多くの物事や一連の働きを秩序立てた全体的なまとまり。体系。もっと狭くは、組織や制度。

by Goolge 

「体系化」の思考方法と考えるとコンピュテーショナルシンキングも身近になります。

 

システムの設計を教えるときに、入り口のモチーフにしているのは、みんなで使う共有サーバーの「フォルダ構成」を考えることです。

 

学校でいうと、国語、理科、数学などの教科をトップフォルダに並べるのか、

先生の名前で並べるのか、年次で並べるのか、など用途によって使いやすい分類が変わって来ます。

このフォルダ構造の設計には、誰がどのようにどのぐらいの頻度でどのフォルダを利用するのかを分析すると、最適解が見つかりますが、はじめにどのように設計するかは、分析を待たずに論理的に実践する必要があります。

 

詳しい実践の方法はまた別で考えるとしましょう。

 

とにかく、システム化は、ソフトウェアシステムだけではなく、組織・ルールづくり、ひいてはビジネスモデル構築など、応用が大変聞く範囲ですし、高校生でいうと教科横断的な効果があると感じられます。