IT + X

ITと何かのコラボレーションは時代を変えるかも

Elixirを使ってみたらとても楽しかった

Elixirはマルチプロセスを前提とした関数型プログラミング言語でエリクソンが電話交換機プログラムのために開発したErlangという仮想マシンシステム上で動作します。
Elixirが流行ってきた背景として、CPUが複数コアで構成されるようになり個人のパソコンでも8コアや16コアのCPUが使われるようになってきたのがあると思います。
しかし、CやJava,Pythonなどの現在主流の言語はシングルコアのCPUを前提にした言語なのでマルチコアをうまく扱えません。
そこでGoやRustなど新しい言語が登場してきたのですが、Elixirはその中でも比較的とっつきやすく関数型プログラミングのよさもうまく取り込んだ言語です。
ただ、古いタイプの言語に慣れている人にはそこがとっつきにくい部分かもしれません。

最新の情報を得たかったのでこちらの本で学びました。

Programming Elixir ? 1.6: Functional |> Concurrent |> Pragmatic |> Fun

Programming Elixir ? 1.6: Functional |> Concurrent |> Pragmatic |> Fun

Elixirを使ってみて私がいいなと思ったのはこんなところでした。

  • Lispっぽいリスト
  • mapや再帰を使ってループを使わない
  • 関数シグネチャーを使って条件分岐を行う
  • 関数を複数つなぐパイプオペレーター
  • 複数プロセス間のメッセージ通信が簡単

Lispっぽいリスト

昔、EmacsというエディタでLispという言語を使ったことがありますが、Elixirの配列はLispによく似てると思いました。
例えば、Lispはリスト構造が基本でcarやcdrというリストの先頭やそれ以外を取得する関数があります。
それと同じような機能がElixirにもあります。
例えば、配列の先頭を取得するには以下のように書きます。

iex > [ head | tail ] = [ 1 , 2 ,3 ,4 ,5 ]
iex > head
1
iex> tail
[ 2, 3, 4, 5 ]

ちなみにiexはElixirのシェルみたいなものでRubyでいうirbと同じものです。 この言語を作った人は明らかにLisperですね。

また、mapというデータタイプを使うことができます。

iex> map = %{:a => 1, 2 => :b}
%{2 => :b, :a => 1}
iex> map[:a]
1

mapとはキーと値がペアになっているデータで、他の言語では連想配列と呼ばれているものです。
ちなみに配列の添字に使われている:a や:bはアトムと呼ばれている定数データで見た感じ文字列のように見えますが スキャン処理などを高速に行えるようにハッシュ値のようなデータです。
Rubyのシンボルを同じですね。

再帰を使ってループを使わない

Lispでは再帰呼び出しというテクニックをよく使いますが、Elixirでもよく使われます。 再帰とは関数の中で自分自身を呼ぶことをいいます。
例えば、フィボナッチ数を計算する関数はこんな感じです。

def fib_calc(n) do
   result = fib_calc(n - 1) + fib_calc(n - 2)
end

フィボナッチ数は最初0と1から始まるので停止条件として書いておくべきなのですが上の例では省略しました。
CやJavaで書く場合はforループなどで集計していくことが多いですが、再帰で書くことによってシンプルな記述になるところがいいですね。
ただ、再帰は慣れていないと訳がわからないコードになりがちなのでプログラマーの習熟が必要です。
また、再帰は普通スタック領域をたくさん消費したり実行速度が遅かったりするのですが、Elixirではうまく最適化してくれているようです。

関数シグネチャーを使って条件分岐を行う

例えば、C言語でエラー処理のコードはこんな感じになります。

func1(int val , int error_code){
   if (error == 0){
          do_something(val);
   }else{
         do_error(error_code);
   }
}

Cでコード書いていると条件分岐でエラー処理だらけになることが多いです。
一方、Elixirではこういう書き方ができます。

defmodule m1 do
    def func1( {:ok, val}) do
           do_something(val)
    end
    def func1({:error, error_code}) do
            do_error(error_code)
     end
end

波括弧の引数はタプルと呼ばれているデータ型で変更できない配列です。
上の例では同じ名前で引数の違う関数func1が定義されます。
Elixirでは同じ関数名でも引数を変えることにより別の関数として定義することができます。
したがって、この例では:okを引数に与えると通常の処理をして:errorを与えるとエラー処理が行われます。
このように、Elixirではifなどの条件分岐をできるだけ使わないようにしてコードの見通しをよくすることができます。

関数を複数つなぐパイプオペレーター

シェルをご存知の方はコマンド同士をつなぐパイプという機能があるのをご存知だと思います。

# cat abc.txt|grep "ABC" | wc -l

Unixのコマンドは一つ一つは単純な処理しかできませんが、パイプで組み合わせることによって様々な処理を行わせることができます。
Elixirにもパイプオペレーターというものがあり、関数をつないで複雑な処理を行わせることができます。

iex> "Elixir rocks" |> String.upcase() |> String.split()
["ELIXIR", "ROCKS"]

上の例では|>がパイプオペレーターで"Elixir rocks"という文字列がString.upcase()関数の第一引数として与えられます。
つまり、String.upcase("Elixir rocks")を呼んでるのと同じことになります。
次のString.split()も同様にデータが流れます。
Unixエンジニアにはあたかもシェルスクリプトを書いているみたいでたまらない機能ですね。

大量プロセスを起動してもオーバーヘッドが少ない

Elixirでは簡単に複数のプロセスを立ち上げて並列で処理させることができます。
ここでいうプロセスとはOSネイティブのプロセスではなくElixirのVM上で実行するプロセスなのでとても軽いものになっています。
プロセスの生成は以下のように行います。

spawn(module_name, function_name, [function_params])

例えば、複数のプロセスで合計するプログラムはこんな感じになります。

defmodule ParalellSum do
    def psum(n) do
        result = Enum.reduce(n, fn(x, acc) -> x + acc end)
        result
    end
    def do_process(n) do
        num_processes = n
        calc_val = [1,2,3,4,5]
        Enum.each 1..num_processes, fn(_) -> spawn(ParalellSum, :psum, [calc_val]) end
    end
    def run(n) do
        :timer.tc(ParalellSum, :do_process, [n])
        |> IO.inspect
    end
end

大まかに説明すると、spawn(..)でプロセスを生成してpsum()という関数を別プロセスで並列に動かしています。
psum()関数はcalc_valの要素を合計します。
このプログラムをプロセス数1000,10000,100000で動かした結果がこちらです。

$ elixir -r myprocess.ex -e "ParalellSum.run(1000)"
{1756, :ok}
$ elixir -r myprocess.ex -e "ParalellSum.run(10000)"
{18173, :ok}
$ elixir -r myprocess.ex -e "ParalellSum.run(100000)"
{156408, :ok}

run関数のパラメータがプロセス数で結果の数値は実行時間をマイクロ秒で出力します。
ご覧の通り、10万プロセスで0.1秒ほどしかかかっていません。
ちなみに実行環境はMacBookPro Corei5 2.3GHzでした。
プロセスによるオーバーヘッドはほぼないと考えて開発できますね。

複数プロセス間のメッセージ通信が簡単

Elixirの一番の売りはプロセス間通信が簡単なことです。
次の例はエコーサーバーを生成してクライアントのメッセージをそのまま返すプログラムです。

defmodule Echo1 do
    def echo_back do
        receive do
            {sender, msg} ->
                send sender, {:ok, "#{msg}" }
        end
    end
end

# client
pid = spawn(Echo1, :echo_back, [])
send pid, {self(), "Hello World !"}

receive do
    {:ok, message} ->
        IO.puts message
end

spawn()関数でエコーサーバーを生成してクライアントから"Hello World!"というメッセージを送信するとサーバーがそのまま返します。
send pid,...がサーバーにメッセージを送信しているところで、echo_back関数のreceive do...のところで受信しています。
{send, msg}->のところは送られてきたメッセージのパターンを記述するところでマッチすればそれ以下の処理が実行されます。
したがって、このパターンを複数持たせればメッセージパターンによって違う処理をさせることができます。 LinuxC言語でデーモンを書くよりはるかに簡単ですね。

ざっと触ったところではこんな感じでした。
また、ElixirにはRailsに似たウェブフレームワークPhenixや組み込み系フレームワークのNervesなどがあっておもしろそうです。
Elixirはマルチプロセスで通信しながら処理を行うのが当たり前なのでRubyPythonとは違った作りにできると思います。
次回ウェブアプリ開発を行うときはElixirを使ってみたいなと思いました。

Vue.jsを使ってみてよかったところ、イマイチなところ

Vue.jsはReact,Angularに並ぶJavascriptフレームワークです。
しばらくフロントエンド開発にはかかわらなかったのでいろいろハマりましたが、備忘録も兼ねてまとめてみました。

Vue.jsのいいところ

リアクティブシステム

Vue.jsはリアクティブシステムになっています。
リアクティブシステムとは、ある変数の値を変更するとブラウザ上の表示も自動でアップデートしてくれるしくみをいいます。
例えば、以下のようなJavascriptのコードの場合、

let price = 1000;
let quantity = 10;

total = price*quantity;

totalに計算結果が出力されますが、後でpriceの値を変更(例えばprice = 200)にしてもtotalの値は変わりません。
しかし、リアクティブシステムではpriceの変更にともなってtotalが更新されます。
Vue.jsでは以下のように書きます。

var vm = new Vue({
   el: '#app',
   data: {
     price: 1000,
     quantity: 10
   },
   computed: {
    totalPrice(){
       return this.price * this.quantity
     }
  }
})

<div id="app">
  <div>Price: ${{ price }}</div>
  <div>Total: ${{ totalPrice}}</div>
</div>

ブラウザのデベロッパーツールのコンソールを開いて以上のコードを入力したあと、vm.price = 2000と入力するとTotalが自動で20000に更新されます。 これによりネイティブアプリのようなダイナミックなウェブアプリを作ることができます。
もしリアクティブでないJavascriptで同じようなことをやろうとすると、自分で変数の更新をチェックし変更されたらターゲットフィールドの値を更新するという処理を自分で書かなければいけません。
ダイナミックなウェブアプリを開発するときにとても便利ですね。

UIを部品化できる

Vue.jsは、コンポーネントと呼ばれるしくみによってソフトウェアを部品化して再利用できるようになっています。
例えば、ボタンの押した回数を表示する部品はこんな感じに書けます。

Vue.component('counter', {
  template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})

コンポーネントをVue.jsで利用するためには以下のように書きます。

<div id="app">
  <counter></counter>
</div>
new Vue({ el: '#app' })

counterというタグでクリックすると数えてくれるパーツとして扱えます。

フレームワークがある幸せ

複数のメンバーでチームで開発する場合、フレームワークがあると規約に則って開発することができるのでメンバー間で話し合いながら作るときにはとても役に立ちます。
Vue.jsでは単一ファイルコンポーネントという形式があります。

<template>
  <p>{{ greeting }} World!</p>
</template>

<script>
module.exports ={
  data: functon(){
     return {
        greeting: 'Hello'
     }
 }
}
</script>

<style scoped>
p {
  font-size: 2em;
  test-align: center;
}
</style>

templateタグのところが表示するHTMLで、scriptタグがJavascriptコード、styleタグがCSSコードを記述するところです。
通常、それぞれのタグ部分はHTMLファイル、JSファイル、CSSファイルに分けて記述されますが、一緒に書けるようにすることでモジュール性を強化しています。

さらに、vue-cliを使えば自動的にディレクトリ、ファイルを生成して整えてくれます。
vue-cliパッケージをnpmでインストールしてプロジェクトの雛形を作成してみましょう。

# npm install vue-cli
# npm install -g @vue/cli
# vue create <ディレクトリ名>

vue createでは以下のようなファイルが作成されます。

f:id:anthony-g:20190430123205p:plain

Vue.jsプログラムファイルはsrcディレクトリ下にあり、以下のようなファイル構成になっています。

f:id:anthony-g:20190501154027p:plain

App.vueとmain.jsがプログラムメインファイルで、componentsディレクトリ以下のファイルがコンポーネントのプログラムファイルです。
このようにvue-cliでプロジェクトの雛形が作成されます。

Vue.jsのイマイチなところ

コンポーネント間のデータやりとりが面倒

コンポーネント構造になっていることによってプログラムの規模が大きくなってもプログラムがスパゲッティー化しないのでいいのですが、コンポーネント間で情報をやり取りする必要が出てきて結構面倒くさいです。
コンポーネント間のデータのやり取りは2つの方法があります。

1. propによるデータのやりとり
親のコンポーネントから子のコンポーネントへデータを渡すには子コンポーネントにpropsを定義します。

main.js

// 子コンポーネント
const childComponent = {
   props: ['myMessage'],
   template: '<span>{{ myMessage }}</span>
}

// 親コンポーネント
new Vue({
    el: '#app',
    components: {
         'childComponent': child-component
    }
});

html

...
<child-component v-bind:my-message="こんにちは"></child-component>
...

HTML上では属性名は大文字小文字を区別しないので、タグ名はchild-component、属性名はmy-messageという感じでキャメル形式をケバブ形式に変換しています。 しかし、propsを使う方法は親から子への一方向でしか情報をやりとりできません。
子から親に情報を伝えるためにはemitを使って可能です。 情報の伝達方向でやり方が違うというのもいまいちな感じです。

2. Vuexによるデータのやりとり
しかし、コンポーネント間の関係が親子関係であるとはかぎりません。
そういうときはVuexを使います。
Vuexとは、Vue.jsアプリケーションローカルに持つことのできるDBのようなデータ格納領域を作成するライブラリで、全てのコンポーネントからアクセスすることができます。
まず、Vuexのストアを定義します。
store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(vuex)

const store = new Vuex.Store({
  state: {
         myMessage: ""
  },
  mutations: {
   setMyMessage(state,{msg}){
      state.myMessage = msg
   }
})

stateに格納するデータを、myMessageと定義して文字列を持つようにします。 Vuexでデータを更新する場合は、commit()を呼ばなければいけないお約束になっていて、mutationsはその関数を定義するところです。 次に、main.jsでstoreをVue.jsに読み込みます。

src/main.js

...
import store from './store'
...
new Vue({
    render: h => h(App),
    store: store
}).$mount('#app')

次に、コンポーネントでstoreにアクセスしてみます。

src/components/xxx.vue

<template>
<div>
  <span>{this.$store.state</span>
   <input type="text" />
   <button @click="ok()">OK</button>
</div>
</template>
<script>
export default {
  name: "xxx",
  methods: {
     ok(){
         this.$store.commit('setMyMessage",{myMessage: "Hello World"})
     }
   }
}
</script>

これはテキストボックスに入力してボタンを押すとVuexの情報が更新される例です。 これでVuexを介してコンポーネント同士のデータのやり取りができるようになりますが結構面倒ですね。 Vuexについての詳しい解説は以下のURLを参照してください。

vuex.vuejs.org

リアクティブシステムがわかりにくい

リアクティブシステムはリッチなUIを作るには便利なのですが、どのタイミングで更新されるのかがわかりにくいというのがあります。
例えば以下の例の場合、

src/components/xxx.vue

<template>
<div v-if="showComponent">
...
</div
</template>
<script>
export default {
   name: "xxx",
   computed: {
      showComponent(){
         return this.$store.state.showFlag
      }
   }
}
</script>

VuexデータのshowFlagでコンポーネントを表示したり消したりしたいのですがうまく動きません。 (これで結構長い間悩みました。)
VuexストアのshowFlagが更新されたらshowComponentが呼ばれてほしいのですがそうはなりません。
v-ifのほうでリアクティブな変数をモニターしているみたいなのですが、computedメソッドの中までは見てないみたいです。
こういうところが最初とまどうところです。

学習コストがやや高め

通常プログラムは記述した順番に実行されるものですが、リアクティブシステムは何かを変更したらキックされるイベントドリブンなシステムなので慣れるまで少しかかります。
また、モジュール化でソースが複数ファイルに分かれてしまうので、なれないと全体が見えづらいというのもあります。

結論

ちょっと使った感じでは、Vue.jsは規模の大きなフロントエンド開発向けなのかなと感じました。
ただ、うまく動かないときに調べるのが結構大変だったのでデバッグがもう少しやりやすくなるといいと思いました。
Reactも少し触ってみましたが、なんでもかんでもJavascriptのコードにしてしまうReactよりVue.jsのほうがわかりやすい印象でした。
あと、VuexとVue-Routerはほぼ必須で使うコンポーネントだと思います。
最初は少しとっつきにくいですが、慣れれば使って損はないのではないでしょうか。

参照URL:
www.vuemastery.com

CSSグリッドを試してみる

ウェブページでレイアウトするときは、いままではdivでボックス作ってスタイルシートのfloatで並べるというのが一般的な方法でした。 (ちなみに、ウェブ黎明期はtableで全てレイアウトしていました。) しかし、最近はCSSグリッドなるものがあるというので使ってみたら、とても便利だったのでブログ記事にしました。

例として、以下のようなレイアウトをCSSグリッドで作ってみましょう。

f:id:anthony-g:20190308230422p:plain

HTMLは以下のようになります。

index.html

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Grid Test</title>

<meta name="viewport" content="width=device-width">
<link href="https://fonts.googleapis.com/css?family=Raleway" rel="stylesheet">

<link rel="stylesheet" href="style.css">
</head>

<body>
  <header>トップページ</header>
  <section>
    <div id="box1">ボックス1</div>
    <div id="box2">ボックス2</div>
    <div id="box3">ボックス3</div>
    <div id="box4">ボックス4</div>
  </section>
</body>
</html>

divボックスにそれぞれbox1,box2,box3とIDをつけておきます。

次に,CSSファイルは以下のようになります。

style.css

@charset "UTF-8";

/* 基本設定 */

* {
    margin: 0;
}

/* ページ全体の設定 */
body {
    display: grid;
    grid-template-columns: 20px 200px 20px;
    column-gap: 10px;
    grid-template-rows: 
        [head] 50px
        [r1] 200px;
    grid-row-gap: 20px;
    row-gap: 20px;
    font-family: sans-serif;
}

header {
    grid-row: head;
    grid-column: 2;
    justify-self: center;
    align-self: center;
    width: 100px;
    border: solid 1px black;
}

section {
    grid-row: r1;
    grid-column: 2;
    display: grid;
    grid-template-columns: 100px 100px;
    grid-template-rows:
       [sr1] 100px
       [sr2] 100px;
    row-gap: 10px;
    column-gap: 5px;
}

div {
    border: solid 1px black;
}

div#box1 {
    grid-row: sr1;
}

div#box2 {
    grid-row: sr1;
}
div#box3 {
    grid-row: sr2;
}
div#box4 {
    grid-row: sr2;
}

まず、bodyのところでdisplay: gridとしてCSSグリッドを使う指定をします。 次に、行方向のグリッドのレイアウトを以下のように定義します。

grid-template-columns: 20px 200px 20px;

これは以下のように両側に20pxの余白をつけて中央にコンテンツを200pxの幅で配置するレイアウトになります。

f:id:anthony-g:20190309113349p:plain

カラムの区切りは左から1,2,3...と番号がふられますので、これでコンテンツを表示する位置を指定します。 このページはsection部分が表示されるコンテンツですので、sectionのgrid-columnを2に指定します。

次に、列方向のレイアウトの指定を行います。 こちらも行と同じように以下のように設定します。

grid-template-rows: 
    [head] 50px
    [r1] 200px;
f:id:anthony-g:20190309114946p:plain

[head]とか[r1]というのが追加されていますが、これは列を番号ではなく名前で指定できるようにするための設定です。 headerで以下のように設定します。

header {
   grid-row: head;
...

表示コンテンツを含むsectionは、以下のように設定します。

section {
   grid-row: r1;
   ...

これで、大枠のレイアウトが完了です。 4つのdivはさらにsectionの中でグリッドを設定してレイアウトしています。

このようにグリッドを使えば、方眼紙の上でデザインするようにレイアウトすることができます。 floatを使うより直感的なので慣れればこちらのほうがデザインしやすいのはないでしょうか。

参考にした本

CSSグリッドで作る HTML5&CSS3 レッスンブック

CSSグリッドで作る HTML5&CSS3 レッスンブック

Firebase使ってみた

FirebaseはGoogleが提供するBaaSと呼ばれるクラウドサービスです。

firebase.google.com

これからは自分でサーバーを構築する時代でもないと思ったので、Firebaseを試してみました。

まずは、firebaseに登録してウェブアプリをデプロイするところまでやってみたのですが、ちょっとハマったところもあったのでまとめておきました。

 

まず、Google Cloud Platformに登録して 新しいプロジェクトを作成します。
作成方法についてはこちらを参照してください。

cloud.google.com

次に、GCP Cloud Shellを開きます。
これはブラウザからクラウドインスタンス上でシェルを使うためのものです。
GCPダッシュボードの右上のプロンプトマークをクリックします。

 

f:id:anthony-g:20190228202922p:plain

すると、下にシェルのターミナルが開きます。

f:id:anthony-g:20190228204726p:plain

サンプルウェブアプリのソースを以下のコマンドでダウンロードしておきます。


# git clone https://github.com/firebase/friendlychat-web

 

次にFirebase(https://firebase.google.com)のサイトにブラウザでアクセスして、プロジェクトを作成します。

f:id:anthony-g:20190301123150p:plain

 

プロジェクトを作成すると以下のようなページが表示されます。

f:id:anthony-g:20190301123331p:plain

 

Firebaseは以下のようなサービスで構成されています。

  • Authentication - 認証機能
  • Database - データベース機能
  • Storage - 静的コンテンツやファイルを保存する機能
  • Hosting - コンテンツの配信やデプロイ
  • Functions - クラウド関数

サンプルアプリを動かすためにAuthentication,Database,Storageを設定します。

左サイドメニューの「Database」をクリックしてRealtime Databaseの「データベースの作成」をクリックします。

f:id:anthony-g:20190301131242p:plain

 

「テストモード」を選択し、「データベースを作成」をクリックします。

f:id:anthony-g:20190301131512p:plain

 

データベース作成完了です。

f:id:anthony-g:20190301132719p:plain

 

次に、認証機能を設定します。
左メニューのAuthenticationをクリックし、「ログイン設定ボタン」をクリックします。

f:id:anthony-g:20190301162816p:plain

 

「ログイン方法」タブを選択した後、ログインプロバイダーとしてGoogleを選択し「有効にする」スライダーをオンにします。「プロジェクトの公開名」はFriendly Chatと入力します。

f:id:anthony-g:20190301165235p:plain

 

Google認証が有効になりました。

f:id:anthony-g:20190301171933p:plain

 

次に、Storageの設定を行います。

f:id:anthony-g:20190301172103p:plain

 

「スタートガイド」ボタンをクリックします。

f:id:anthony-g:20190301172227p:plain

 

「セキュリティルール」ダイアログのOKボタンをクリックします。

f:id:anthony-g:20190301173237p:plain

 

これでFirebase側の設定は完了です。

次に、サービスアカウントを作成します。
サービスアカウントとは、アプリケーションや仮想マシンに属する特別なGoogleアカウントです。GCPからFirebaseにアクセスするには事前に作成しておく必要があります。

GCPダッシュボードのメニュー「APIとサービス」- 「認証情報」をクリックします。

f:id:anthony-g:20190302181612p:plain

「認証情報」の「認証情報の作成」-「サービスアカウントキー」を選びます。

f:id:anthony-g:20190302184907p:plain

 

「サービスアカウント」メニューで「新しいサービスアカウント」を選択し、「役割」メニューは「Project」-「オーナー」を選択します。

f:id:anthony-g:20190302185440p:plain

アカウントが作成された後、暗号鍵が含まれたJSONファイルがダウンロードされますので、PCの適当なところに保存してください。

PC上のエディタでダウンロードしたJSONファイルを開いてテキストをコピーします。
次に、GCPコンソール上でvi等のエディターを開いてペーストしてファイル保存してください。(ファイルパス $HOME/friendly_chat_web/web/fbtest.json)
そして、GCPシェル上で保存したJSONファイルのパスを環境変数GOOGLE_APPLICATION_CREDENTIALSに以下のように設定します。

# export GOOGLE_APPLICATION_CREDENTIALS=$HOME/friendly_chat_web/web/fbtest.json

次に、アプリのディレクトリで以下のコマンドを実行します。

# cd friendly_chat_web/web
# firebase login --no-localhost

ブラウザでアクセスして認証するためのURLが表示されるので
表示されたURLにアクセスしてサービスアカウントのアクセスを許可してください。

そして、以下のコマンドをGCPシェルで実行してください。
# firebase init

f:id:anthony-g:20190302200746p:plain

ラジオボタンになっているところの「Database」と「Storage」に上下カーソルキーで移動しスペースキーでチェックを入れてリターンします。

f:id:anthony-g:20190302201152p:plain

Select a default Firebase project for this directory:で(don't setup a default project)を選びます。

f:id:anthony-g:20190302202129p:plain

その後、何回か聞かれますがリターンで問題ないです。

そして、アプリケーションのデプロイを行います。
# firebase deploy --project プロジェクトID

プロジェクトIDは、Firebaseのプロジェクトの設定で確認できます。

f:id:anthony-g:20190303211521p:plain

 

Hosting URLをブラウザでアクセスするとウェブアプリが動作していることを確認できます。

f:id:anthony-g:20190302204647p:plain

 

GCPとFirebaseの接続設定のところで結構はまりましたが、認証やデータベースをFirebaseに任せられるのはいいですね。
さらに色々いじってみたいと思います。

 

参考URL: 

www.topgate.co.jp

ジョブ理論 ー イノベーションを予測可能にする消費のメカニズム

 

ジョブ理論 イノベーションを予測可能にする消費のメカニズム (ビジネスリーダー1万人が選ぶベストビジネス書トップポイント大賞第2位!  ハーパーコリンズ・ノンフィクション)

ジョブ理論 イノベーションを予測可能にする消費のメカニズム (ビジネスリーダー1万人が選ぶベストビジネス書トップポイント大賞第2位! ハーパーコリンズ・ノンフィクション)

  • 作者: クレイトン M クリステンセン,タディホール,カレンディロン,デイビッド S ダンカン,依田光江
  • 出版社/メーカー: ハーパーコリンズ・ ジャパン
  • 発売日: 2017/08/01
  • メディア: 単行本
  • この商品を含むブログ (6件) を見る
 

 

今はものが売れない時代と言われています。

たしかに、生活の中でものはあふれていて、顧客が何を欲しがっているか見つけるのが難しくなっているのは事実です。

しかし、売れている商品やサービスは今でも存在しています。

trend.nikkeibp.co.jp

では、なぜこれらの商品は売れたのでしょうか?

 

「ジョブ理論」によれば、顧客がものを買うのは自分のジョブを片付けたいからといいます。
ジョブとは、特定の状況で人あるいは人の集まりが追求する進歩のことをいいます。

 

例として、朝のミルクシェイクのエピソードがあげられていました。
あるお店で朝にミルクシェイクがよく売れるようになったそうです。
そこで、お客さんに聞いたところ、朝に仕事先まで1~2時間ドライブするときに空腹と退屈な時間を解消するためだったということがわかりました。
でも、ドーナツだとボロボロこぼれて運転しながらだと食べにくいし、バナナだとすぐ食べ終わってしまうからだめだったのです。
ミルクシェイクを買うことによって、顧客の朝の生活に進歩をもたらしたのです。

 

顧客の本当のジョブを見つけるのは結構難しいと思います。
ミルクシェイクのケースも、まず朝に売れていることに関心をもつ人なんてめったにいないでしょう。
気がついたとしても、おいしいから売れてるんだろうくらいにしか普通は思えないでしょう。
大事なのは人に関心をもって、なぜあんな行動をするのかと疑問を解明しようとする姿勢なのだと思います

 

ミルクシェイクのケースは顧客がいたからわかりましたが、顧客がいない場合もあります。
サザンニューハンプシャー大学にはオンラインコースがあったのですが、リソースもあまり投入していない状況だったので業績はいまいちでした。
そこで、ジョブベースで考えてみたところ志望者のジョブを解決するようなサービスを提供していないことに気がつきます。
例えば、オンラインコースに申し込む人は社会人が多かったのに高校生を対象にした内容になっていたり、奨学金の申し込みも手続きが面倒だったりしてあきらめている人が多かったのです。
それを社会人向けの内容に変え、奨学金も簡単に申請できるようにしました。
入学後も学習のフォローをきめ細かくして、全米で有名な大学になっていきました。
このケースでは、表には現れていない生徒のジョブにフォーカスして解決するサービスを提供することが成功した理由だったのです。

 

ただ、ジョブを機能や利便性の面だけから見るのはまちがいです。
なぜなら、人は感情で判断する生き物だからです。

GMは、自社の車に搭載する車載システム向けにオンスターという情報サービスを提供しています。
オンスターはナビゲーションやリモート診断、ハンズフリー通話など様々な情報サービスから構成されています。
GMは、最初このサービスを高級車オーナーをターゲットにしましたが、エントリーレベルの車種でも売れているのを見て不思議に思いました。
顧客を調査したところ、ドライバーがエンジンランプがついているのを見て不安になったり、道に迷って困ったときの頼れるサービスを求めていたのです。
つまり、心の不安を取り除いてくれるサービスにニーズがあったのです
それを理解したGMは高機能を目指すのではなく、ドライバーの不安に対処するサービスを提供することに方向転換して成功しました。

いくら技術が発達しても相手にするのは人間です。
人間は合理的に判断することは意外と少なく、感情で判断することがとても多い生き物なのです。

今は何でもデータ化して定量的に分析することが正しいとされますが、定性的な情報のほうが重要なことが多いのです。
また、データに頼りすぎると相関関係があるというだけで因果関係に結びつけてしまうまちがいが起こりやすいのです。

昔、ソニーの社長の盛田さんがウォークマンを売り出す時、再生だけしかできない音楽プレーヤーなんか売れないと社内中から反対されたそうです。
マーケティングリサーチでもそういう結果が出てたかららしいですが、盛田さんは必ず売れるという確信を持っていたそうです。
私も昔ウォークマンを持ってましたが、実際に使ってる人でないと本当のよさは感じられない商品だなと思いました。
ウォークマンは、外で歩きながら音楽を楽しみたいというジョブを解消してくれる素晴らしい進歩だったのです。

どんな時代になっても人が片づけたいジョブがなくなることはありません。今の日本だと高齢化や少子化、産業の空洞化などでジョブが山積しています。それらのジョブを見つけて解決しようとすれば今でも売れる商品を開発することができるのではないでしょうか。
 

ソニー 盛田昭夫

ソニー 盛田昭夫

 

 

 

MacでESP-IDFをインストールして使ってみる

遅ればせながらESP32でいろいろ遊んでみようということで、MacBookProにESP-IDFをインストールして使ってみようとしたのですが、いろいろハマったので書いておきたいと思います。

 

ESP32ボードはUSBケーブルで接続できるこちらを使いました。

 

接続USBケーブルは、Mac側がUSB Type CでESP32側はマイクロBになっていますが意外に普通のお店では売っていません。変換アダプタもかったるいのでESP32接続専用に買っておきました。

 

まずは、MacにESP32接続用ドライバーをインストールします。

ドライバーはこちらからMac OS X用ドライバをダウンロードできます。

www.silabs.com

 

ただし、最近のMac OSはセキュリティが厳しくなっててApp Store以外のソフトウェアのインストールはブロックする仕様になっています。

インストーラー実行後、コントロールパネルの「セキュリティとプライバシー」で許可してやればインストールされます。

f:id:anthony-g:20190125170833p:plain

 

正しくインストールされるとデバイスファイル/dev/cu.SLAB_USBtoUARTが作られているはずです。

次に、ESP32ツールチェーンこちらからインストールします。

https://dl.espressif.com/dl/xtensa-esp32-elf-osx-1.22.0-80-g6c4433a-5.2.0.tar.gz

(2019年1月現在。最新のファイルはhttps://docs.espressif.com/projects/esp-idf/en/latest/get-started/macos-setup.htmlを参照ください。)

ちなみに、ツールチェーンとはコンパイラアーカイバなどコンパイルして実行ファイルやライブラリを作るためのコマンド群をいいます。

ホームディレクトリにespというディレクトリを作成し、そこにダウンロードしたファイルを解凍します。

# mkdir ~/esp
# cd ~/esp
# tar xzf xtensa-esp32-elf-osx-1.22.0-80-g6c4433a-5.2.0.tar.gz

 espディレクトリ下のxtensa-esp32-elf以下にツールチェーンが展開されます。

 

 次に、ESP-IDFをインストールします。

Githubからファイルをゲットします。

# git clone --recursive https://github.com/espressif/esp-idf.git

ESP-IDFは、サブモジュールもいくつか含まれているのでgit cloneで--recursiveオプションを指定することによってサブモジュールも合わせて取得します。

ESP-IDFに必要な環境変数を.bash_profileに追加します。

~/.bash_profile

export PATH=$HOME/esp/xtensa-esp32-elf/bin:$PATH
export IDF_PATH=$HOME/esp/esp-idf

環境変数をシェルに反映させておきます。

# source ~/.bash_profile

次に、ESP-IDFに含まれているblinkというサンプルプロジェクトをビルドして実行してみます。このプロジェクトはLEDを点滅させるだけの簡単なプログラムです。

回路としては下の写真のように、LEDと抵抗を直列につないだシンプルなものです。ESP32側はGNDとGPIO23のピンに回路の両端をつないでいます。

 

f:id:anthony-g:20190126115335j:plain

 

 blinkプロジェクトファイルをコピーします。

# cp -r esp-idf/examples/getting-start/blink .
# cd blink
# ls
CMakeLists.txt   README.md   sdkconfig.defaults
Makefile             main

プロジェクトの設定を行います。

# make menuconfig

f:id:anthony-g:20190126130835p:plain

USBのデバイスファイルを設定します。

f:id:anthony-g:20190126130852p:plain

f:id:anthony-g:20190126130856p:plain

GPIO23から出力されるように設定します。

f:id:anthony-g:20190126135258p:plain

f:id:anthony-g:20190126135302p:plain

設定を終了後、プロジェクトをビルドしてESP32にプログラムをロードします。

# make flash

ビルド完了後、"Connecting..."というプロンプトが出たら、ESP32のBOOTボタン(USBコネクタ側に向かって右側のボタン)を押してください。

WindowsではBOOTボタン押しは必要なかったのですが、なぜMacではボタン押ししないとタイムアウトしてしまいました。ひょっとしたらボードがespressif純正でないのが理由かも。)

下のような感じの出力が出ればうまくロードされています。

f:id:anthony-g:20190126135908p:plain

 

いろいろハマりましたが、無事Lチカさせることができました。 


esp32 blink

IT+Xについて

仕事も少し落ち着いたので、久しぶりに技術ブログを再開しようかなとあたらしくはてなにブログを作ってみました。

内容としては、今私の興味のあるIT技術を中心に情報シェアできればいいかなと思っています。しかし、今やITはあらゆる分野でインフラとなっている技術ですので、技術的な面だけでなく、実際に使われているケースやこれから使われる可能性についても書いていけたらいいなと思っています。

いつまで続けられるかわからないですが、とりあえず書いていきたいと思います。