ぱいぱいにっき

Pythonが好きすぎるけれど、今からPerlを好きになりますにっき

これを聞けばドローンを作れるという発表をYAPCに応募しています #yapcasia

トークはこちら

yapcasia.org

以下は長いので、めんどくさいなら上の詳細のところを見てRTアーンドはてブアーンドいいねお願いします。

何故応募したか

僕にはとにかくハードウェアの話とWeb開発の話を交えて誰かとしたいという思いがあって、そんなわけで去年は以下の様な発表をしたわけであります。

yapcasia.org

この発表は何をやったかというと、「こんだけお手軽になってこんだけ楽しくなっているから君たちも来いよ! カモーン!」みたいな呼びかけです。 概要と触りだけみたいな感じなんですけれど。

じゃあ他に何を話すんだよというわけなんですけれど、まだこれは入り口しか見せてないわけです。入り口さえ見せれば、それだけで入ってくる人もいるでしょう。実際にそういう方を見ましたし、非常に僕はそれで満足なわけです。 でもやっぱり、入口に入った後の話を僕はそう言えばしてないなあと思って、そう思った時に自分に出来る最高のハードウェアの話はなにかといったら、一時期仕事で作っていたドローンの話なわけです。

で、何故ドローンの話をするかというと、やはり人間たるもの目的がないとなかなか一歩が踏み出せないわけで、Arduinoを手に入れたところでそいつだけで出来る事はLEDをチカチカさせることぐらいなわけですね。 目的がないと何も出来ないのはPerlを始めとしたプログラミング言語と一緒なわけで、つまりそこは道具なわけです。道具だけ紹介してじゃあやろっかーっていう人もいるにはいるんですけれど、飛び込んでこいよと言った手前、「じゃあ何が出来るんじゃ」と言われた時に聞いてほしい話がありました。

クアッドコプター

詳細にも書いてあるんですけれど、クアッドコプターっていう機械は僕はもうほれぼれしてまして、動くところは、なんとモーター4つのみっていうシンプルさです。 モーター4つさえあれば前進/後退/旋回/上昇/下降、航空機におけるすべての動きが可能です。これが普通の飛行機だとモーター1つにエルロンとラダーといった可動部分が必要です。 一般的なヘリコプターであればモーターは最低でも1つで済みますが、メインローターのトルクを殺すためのテイルローターテイルローターの可変ピッチプロペラ化もしくはモーターを別に搭載する、または逆回転するローターを追加して二重反転プロペラの形態にする必要があります。また、前進や後退を行うにはスワッシュプレートというこれまた僕がほれぼれしている機構が存在するんですけれど、それをメインローターに組み込まなければなりません。スワッシュプレートの話はたぶんYAPCでも(通れば)すると思うんですけれど、このように従来の航空機というのはめちゃくちゃ複雑な機械なわけです。あ、オートジャイロっていうこれまらやっべーのもありますけれど!!!

それがクアッドコプターだとモーター4つ!!! マジか!!!!

そのかわりにクアッドコプターはただモーター4つ回すだけだと 飛ばない です。飛ぶことひとつをとっても複雑なフィードバック制御が支配しているわけです。でも機械からプログラミングでどうにかなる世界に入ってしまえばこっちのもんじゃあないですか???? で、僕はそれを書こうとしたんですけれどマー大変で、結局諦めたんですよね。もちろんArduinoベースのフライトコンピュータなんてものもあるんですけれど、いろいろな技術的障壁だとかそういうのもありました。 あ、そうそう電波の話も! この話はあたり前ですがフル合法で行くので、それに必須の電波の話をします。いやー電気磁気の話はすごく面白いですよ!!!! なので既存の飛んでいるクアッドコプターを乗っ取ってどうにかこうにかするという方向に走って、「乗っ取り技術」というのを知ったわけです。乗っとるって言うと聞こえが悪いですけれど、既存にあるものを利用して新しいものを作るってCPANモジュールを組み合わせてプログラムを作るのと似ているなって思いました。今はほんとうに便利で、ちゃんと汎用的にちゃんとモジュール化されているものもあれば、少しお下品ですが乗っ取ってモンキーパッチをするように利用するのもこれまた面白いなと思い、今回のトークをしようかなと思ったわけでございます。

優れた機械機構は優れたコードを見た時のように美しいものです。クアッドコプターもそれに類するものだと思っています。

というわけでクアッドコプターを題材に選びました。

機械とPerl

Perlっていうのはこれこの前人から聞いたんですけれど、コンピュータの都合がそこそこむき出しになった言語です。中身はどうなっているのかよくわからないギアボックスを買ってきて組み込むというよりは、自分で歯車から組んでいく様な感覚です。 それでいて感動があります。(何重もの意味の)コンテキストがあります。 そんな僕の大好きなPerlで機械を制御する話をしようと思います。 機械とは物理空間と直接つながっているインターフェイスであり、全てが並列処理、全てがリアルタイムです。 実はこれらをPerlで扱うには少し工夫が必要です。fork、AnyEvent、とまあいろいろキーワードはあるんですけれど、仕組みや何故それを使うのかというものを紐解きながら話していきますし、時には外部のツールや言語、もしくはマイコンやIC、FPGAに逃すなどして協調動作させるような話もしたいと思います。

と思ったらワードサラダ的になってきたのでここらでやめておきます。取捨選択はします。

というわけでまとめ

本音としては機械と電気まじでヤバイすごい美しいみたいな話をするんですけれど、クアッドコプターはその中でもマイホットワードでそれを、普段みんなが使っているPerlで作ってみるよ、ネットで買える部品でね、みたいな感じです。 というわけで落ちてもまあどこかではやるとは思いますが、話したいので応援よろしくお願いします。

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ yapcasia.org

GoでMySQLを使ったテストをする

前提

Perlというか、周りの人たちだけなのか、はたまた所属している会社の文化なのかもしれないんですけれど、MySQLを使うWebアプリケーションのテストを書くときに、それ専用のDBを立てるわけでございます。都度立てると重いし、上げたり下げたりスキーマ流しこんだりとかまあそのへんのケアが必要なんですけれど、モックとかやらなくていいし、インデックス張ってなくて重いとかもまあ検知できて便利。賛否両論はあるとは思います。

さて、その時に使うTest::mysqldというモジュールがあり非常に便利なわけですが、さてGoのMySQLを使うWebアプリケーションを書く際に、似たような感じでテスト書けないかなと思っていろいろやってみた次第です。

Go触りはじめてあんまり時間立ってないのでそれ違うとかあればコメントなどで教えていただきたいと思っております。

材料

やり方

めっちゃ雑なコードでそのままは使えないと思うんですけれど、こんな感じ

package hoge_test

import (
    "testing"
    "log"
    "database/sql"
    "os"

    "github.com/lestrrat/go-test-mysqld"
    _ "github.com/go-sql-driver/mysql"
)

var testMysqld *mysqltest.TestMysqld

func TestMain(m *testing.M) {
    os.Exit(runTests())
}

func runTests(m *testing.M) int {
    mysqld, err := mysqltest.NewMysqld(nil)
    if err != nil {
        log.Fatal("runTests: failed launch mysql server:", err)
    }
    defer mysqld.Stop()

    testMysqld = mysqld

    return m.Run()
}

func truncateTables() {
    db, err := sql.Open("mysql", mysqld.Datasource("test", "", "", 0))
    if err != nil {
        log.Fatal("db connection error:", err)
    }
    defer db.Close()

    rows, err := db.Query("SHOW TABLES")
    if err != nil {
        log.Fatal("show tables error:", err)
    }
    defer rows.Close()

    for rows.Next() {
        var tableName string
        err = rows.Scan(&tableName)
        if err != nil {
            log.Fatal("show table error:", err)
        }
        _, err = db.Exec("TRUNCATE " + tableName)
        if err != nil {
            log.Fatal("truncate table error:", err)
        }
    }
}

func TestHoge(t *testing.T) {
    defer truncanteTables()

    // do something
}

解説

go-test-mysqldの使い方

ドキュメント通りにやっているだけなんですが

mysqld, err := mysqltest.NewMysqld(nil)

とやると適当なunix domain socketを作ってくれてmysqlサーバが立ってくれます(skip-networking=trueの場合)。 mysqld.Datasource(dbname string, user string, pass string, port int) stringがDSNを吐いてくれるのでdatabase/sqlでつなげます。

func TestMain(m *testing.M)で安全に終了する

go-test-mysqldにはStop()というメソッドがあり、こいつを叩くとmysqlサーバが落ちてibdataなども掃除してくれます。 というわけで他の言語のテストフレームワークで言うsetupmysqlサーバを起動し、teardownでシャットダウンと掃除をやって欲しい感じがいたします。

というわけでGo 1.4のtestingから使えるようになったTestMain(m *testing.M)という関数をテストファイルに書くことで、テストを実行する前後にやることを記述することが出来ます。 ドキュメントではTestMain(m *testing.M)の中でos.Exit(status int)を呼べと書いてあり、m.Run() intステータスコードを返してくれるっぽいので、ミニマムな実装では、

func TestMain(m *testing.M) {
    os.Exit(m.Run())
}

となります。これもドキュメント通りですが。

だったら

func TestMain(m *testing.M) {
     mysqld, err := mysqltest.NewMysqld
     defer mysqld.Stop()
     os.Exit(m.Run())
}

でええやんとなりますが、os.Exit()はdeferに登録されているやつを破棄して終わるという罠がございまして、掃除されなくてmysqldのプロセスも残ってアレアレ? となっていたのでした。この罠前もハマった気がいたします。。。 というわけでmysqldを立ち上げてRunだけする関数を渡してやってその中でdeferするのがいいかなと思いました。

テスト毎にデータをお掃除

truncateTabls()なる怖そうな関数をテスト毎にdeferして、毎回クリーンな状態にしてるみたいなこともしています。 そうするとテスト間の依存がなくなる(ハズ)なのでテストが書きやすいというわけです。 ただままこれも時間かかるし、場合によりけりかなってお思うけれど、Perlでこういうスタイルでテストを書いていってるのでこうなっているという感じです。

参考

  • qiita.com

  • qiita.com

その他

あとmysqldを作ったあとでスキーマ突っ込んだりとか、場合によってはマスタデータなんかも入れてもいいと思います。消してー入れてーを繰り返すとこれまたテストが長くなるという弊害もありますが。 あとそれから、_test.goファイル毎にmysqldが立ったりしてオッオッとなるので、そこらへんは仕方ないけれど工夫の余地はあるかなーと思いました。

なおこれらの問題への解決としてPerlには

  • datadirをコピーして初期データ作成の時間を短縮する Test::mysqld の copy_data_from
  • mysqldをpoolingする App::Prove::Plugin::MySQLPool
  • dockerでmysqldを立てることによって初期データの作成などの時間を節約する Test::Docker::MySQL

などのソリューションがあります。 あとたぶんマルチスレッドとかあんまり考えていないのでそのへんでバグるかも。

MySQLのXAトランザクションについて調べていた(1)

ドキュメント

英語読めないから5.1の日本語ドキュメントも併用して読んでいる。

検証環境

  • MySQL 5.6.22
  • REPEATABLE-READ

使い方

ゆるふわWebアプリケーションエンジニアなもんで、幸か不幸か今までのエンジニア人生で複数DB環境(シャーディング/マスタDB分散)に遭遇したことがない。なのでXAの使い方をドキュメントから読み取っていく。

XAトランザクションの流れ

普通のトランザクションではBEGINで始めるが、XAトランザクションの場合は

mysql> XA START 'xid';

で始める。

で、このxidってやつは何なのかというと、上記ドキュメントでは

xid: gtrid [, bqual [, formatID ]]

とあり、gtridっていうのが必須らしい。グローバルトランザクション識別子というやつなのだけれど、かぶらなければ適当にクライアントで生成してもよいっぽい? uuidでも突っ込んでおくのかな。

とりあえずサンプルでは'xatest'なんていう超適当っぽい文字列を突っ込んでいるのでそんな感じでよしなにやってく。

さてXA START 'xid'した状態はそのトランザクションACTIVEと呼ばれる状態になる。

mysql> XA START 'xatest1';
Query OK, 0 rows affected (0.00 sec)

そこからSELECTだのUPDATEだのINSERTだののSQLを発行しXA END 'xid'なるSQLを発行する。

mysql> INSERT INTO user (name, status, created_at, updated_at) VALUES ("macopy", 1, NOW(), NOW());
Query OK, 1 row affected (0.00 sec)
mysql> XA END 'xatest1';                                                                                                    │
Query OK, 0 rows affected (0.00 sec)

するとトランザクションIDLEと呼ばれる状態になる。 ただしこの時点ではまだ別のトランザクションからは変更が行われていない。そうなるにはここからまだ2段階ほどステップを踏む必要がある。 XA PREAPRE 'xid'というSQLを発行する。すると、PREPAREという状態になる。

mysql> XA PREPARE 'xatest1';                                                                                                │
Query OK, 0 rows affected (0.00 sec)

すると別のトランザクションからもこのトランザクションは反映待ちというような感じで見ることが出来る。これにはXA RECOVERというSQLを用いる。

mysql> XA RECOVER;
+----------+--------------+--------------+---------+
| formatID | gtrid_length | bqual_length | data    |
+----------+--------------+--------------+---------+
|        1 |            7 |            0 | xatest1 |
+----------+--------------+--------------+---------+
1 row in set (0.00 sec)

ただしまだこの状態ではコミットは行われていない。仕上げにXA COMMIT 'xid'とする。

mysql> XA COMMIT 'xatest1';

XA RECOVER;のリストからは消えて、トランザクション内で行われたデータベースに対する変更がコミットされる。これでトランザクションは終わりだ。

疑問点いろいろ

XAトランザクション中の制限

まずXAトランザクション内でBEGINしようとしてみる。

mysql> XA START 'xatest1';
Query OK, 0 rows affected (0.00 sec)

mysql> BEGIN;
ERROR 1399 (XAE07): XAER_RMFAIL: The command cannot be executed when global transaction is in the  ACTIVE state

はい、ごめんなさいという感じである。 じゃあBEGINってどこまで出来ないのかというと、結局XA {COMMIT|ROLLBACK} 'xid'するまで無理なようである。

mysql> XA END 'xatest1';
Query OK, 0 rows affected (0.05 sec)

mysql> BEGIN;
ERROR 1399 (XAE07): XAER_RMFAIL: The command cannot be executed when global transaction is in the  IDLE state
mysql> XA PREPARE 'xatest1';
Query OK, 0 rows affected (0.00 sec)

mysql> BEGIN;
ERROR 1399 (XAE07): XAER_RMFAIL: The command cannot be executed when global transaction is in the  PREPARED state
mysql> XA COMMIT 'xatest1';
Query OK, 0 rows affected (0.00 sec)

mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)

なお、XA ROLLBACKとは普通のトランザクションで言うROLLBACKのことなんですけれど、こいつはACTIVEでは発行できない。XA END 'xid'IDLEにしてトランザクションから一旦抜けてからでないと出来ない。

また、ACTIVEだと「暗黙のコミットを引き起こすステートメント」は実行できないとのこと。なにそれってなりますが、主に我々に関係するのはDDLであったりTRUNCATE文です。

mysql> XA START 'xatest1';
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE t1 (id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY);
ERROR 1399 (XAE07): XAER_RMFAIL: The command cannot be executed when global transaction is in the  ACTIVE state

いわゆるMySQLにおけるトランザクション内に入れても即コミットされちゃうやつ。

あとそれから、普通のトランザクションを始めた後にXAを始めようとするのも怒られる。

mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)

mysql> XA START 'xatest2';
ERROR 1400 (XAE09): XAER_OUTSIDE: Some work is done outside global transaction

なお、他のコネクションもXAを始めた後はXAではないといけないのではと思いましたが、そんなことはありませんでした。

PKでぶつからせる

以下の例ではコネクションの区別をTA/TBとして2つのコネクションがあるケースを扱っていく。

スキーマ

mysql> DESC t1;
+-------+------------------+------+-----+---------+----------------+
| Field | Type             | Null | Key | Default | Extra          |
+-------+------------------+------+-----+---------+----------------+
| id    | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
+-------+------------------+------+-----+---------+----------------+
1 row in set (0.03 sec)

以下は時系列順

TA> XA START 'xatest1';
Query OK, 0 rows affected (0.00 sec)

TB> XA START 'xatest2';
Query OK, 0 rows affected (0.00 sec)

TA> INSERT INTO t1 (id) VALUES (1);
Query OK, 1 row affected (0.02 sec)

TB> INSERT INTO t1 (id) VALUES (1); # ブロックされる

TA> XA END 'xatest1';
Query OK, 0 rows affected (0.00 sec)

TA> XA PREPARE 'xatest1';
Query OK, 0 rows affected (0.00 sec)

TA> XA COMMIT 'xatest1';
Query OK, 0 rows affected (0.00 sec)

TB>
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY' # ブロックされていたのがここで解放

とまあXA COMMITするまで待たされる。普通のトランザクションと同じような挙動である。 なお、ROLLBACK時の挙動はROLLBACKした瞬間に開放される。IDLEになったあとはいつでもROLLBACK可能なので、まあそうなるか。

さてここまでは普通のトランザクションがめんどくさくなっただけな感じだったが、次からはデッドロックとかその辺りの挙動を見て行きたい。普通のトランザクションとどう違うのかが知りたい。

Perlを学んでいるとお得 テキストファイル解析編

どうもマコピーです。

こちらの記事は
Perl入学式 Advent Calendar 2014の13日目の記事です。

12日目は
猫のあずまさんこと@さんのプログラミング言語を学ぶという事についての私見でした。
なるほど興味深い。

今日の記事では「プログラミング言語を学ぶとして、そこでPerlってどうなのよ」みたいな側面からエモとテックを交えて語っていきたいと思います。

以下は個人の意見で僕の帰属している団体や会社とは関係ありません!!!

実用的便利ポイント

ログの解析

サーバの運用をやっているとテキストファイルにガーって数万行のファイルの特定の部分を見たい時があります。
Webサーバというのはアクセスログやデータベースのログが異常を検知するためや後からその時何が起こっていたかを調べたい時のために詳細なログが常にテキストファイルに流れています。
最近ではログファイル自体をデータベースに突っ込んで検索を容易にしている場合もありますが、それはおいといて。

で、アクセスログっていうのは以下の様なやつがいっぱいある感じになっているんですけれど、(これは今僕が個人的に作っているWebサービスの実験中のログです)

xx.xx.xx.xx - - [13/Dec/2014:07:19:56 +0900] "GET /static/bootstrap/js/bootstrap.min.js HTTP/1.1" 304 0 "http://example.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/xx.xx.xx.xx Safari/537.36"
xx.xx.xx.xx - - [13/Dec/2014:07:21:45 +0900] "GET / HTTP/1.1" 200 3736 "http://example.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/xx.xx.xx.xx Safari/537.36"
xx.xx.xx.xx - - [13/Dec/2014:07:21:45 +0900] "GET /static/bootstrap/css/bootstrap.min.css HTTP/1.1" 304 0 "http://example.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/xx.xx.xx.xx Safari/537.36"
xx.xx.xx.xx - - [13/Dec/2014:07:21:45 +0900] "GET /static/css/main.css HTTP/1.1" 304 0 "http://example.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/xx.xx.xx.xx Safari/537.36"
xx.xx.xx.xx - - [13/Dec/2014:07:21:45 +0900] "GET /static/bootstrap/js/bootstrap.min.js HTTP/1.1" 304 0 "http://example.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/xx.xx.xx.xx Safari/537.36"
xx.xx.xx.xx - - [13/Dec/2014:07:22:19 +0900] "GET / HTTP/1.1" 200 3736 "http://example.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/xx.xx.xx.xx Safari/537.36"

よく見たら1アクセス1行になっているようです。
で、例えばこの中からbootstrap.min.jsのアクセスだけ欲しいというときにどうすればいいでしょうか。
そうですね、Perlを使いましょう。

use strict;
use warnings;

my $count = 0;
while (my $line = <STDIN>) {
    if ($line =~ /bootstrap\.min\.js/) {
        $count++;
    }
}

print $count."\n";

以上の様なスクリプトを counter.pl と保存して、上記のログファイルを流し込みます。
catコマンドはファイルの中身を標準出力に流します。それを パイプ"|" でスクリプトに繋げることでスクリプトの標準入力にログファイルを流しこむことが出来ます。

$ cat access.log | perl counter.pl
32

出てきました。32回あったようです。
しかしここまでであれば実は他の言語(RubyPythonPHP)などでも出来る事です。

ここからがPerlっぽいところになります。ワンライナーを使いましょう。
ワンライナーとは.plファイルを作らずにコマンドの中に全部の処理を書いてしまうことです。

$ cat access.log | perl -e 'while (<STDIN>) { $c++ if $/bootstrap\.min\.js/; } print $c."\n";'
32

同じ結果が出てきました。ですが先程の.plに書いたスクリプトに比べたらだいぶダイエットというか……読めなくなってはいませんでしょうか?
例えば while() では my $line = が消えてしまっています。省略すると$_に1行が入ってくるのを利用しています。
また$cの初期化がされていませんが、初期化がされていない変数を++すると0とみなしてインクリメントを行うのを使っています。
さらに言えば正規表現の$_ =~ もなくなっていますが、これも省略可能です。
普段Perl入学式では「他の人にも読めるコードを心がけましょう」みたいなことをいうこともありますがワンライナーは対極にあります。
僕は使い捨てのコードなのでこんなかんじで圧縮して書くのですが、サクッと書けるメリットも有りよく使っています。

ちなみにですが以上の処理はPerlを使わなくてもコマンドを組み合わせると出来ます。
catに加えて、文字列で絞り込みをかけるgrepコマンドと標準入力の行数を数えるwcコマンドを使えばこんな感じです。

$ cat access.log | grep bootstrap.min.js | wc -l
32

でも複数コマンドを組み合わせるよりPerlで書いたほうが簡単に書けるようなケースも多々有りますし、そちらのほうが見やすいみたいなことがあります。
Perlにはgrepやmapもありますし、ハッシュや配列などのデータ構造も利用できます。それを組み合わせていろんな解析の仕方を実現できます。

もっと高度なPerlワンライナーは以下の記事が参考になります。
おそらくはそれさえも平凡な日々: awkの代わりにperlを使おう

ExcelというかCSV

「ログとかそういう職業の人だけじゃないの?」という疑問が浮かぶ方がいるかもしれませんが、「Perlでテキスト解析」するのは他のことにも使えます。
例えば現代では多くの方が使われているExcelではどうでしょうか。Excelに数字や項目をパチパチ打ち込んでいる方も多いかと思われます。
PerlExcelのファイルをそのままを扱うには一工夫必用なのですが、ExcelCSVファイルを作ればPerlでも簡単に扱えます。

"買った日", "品目", "数量", "買った場所"
"12/1", "ネギ", "2", "近所のスーパー"
"12/2", "サーボモータ", "1", "秋葉原"
"12/3", "ネギ", "3", "近所のスーパー"
"12/4", "みかん", "5", "近所のスーパー"
"12/5", "USBメモリ", "1", "ヨドバシカメラ"

みたいなCSVがあったとして、やたらネギ買ってるんですけれどネギ何本今まで買ったのかなみたいなときにワンライナーを書くと、

$ cat 買った物リスト.csv | perl -e 'while(<STDIN>) { @cell = split /,/; $c += $cell[2] =~ s/[" ]//gr if $cell[1] =~ /ネギ/; } print $c."\n";'
5

こんなかんじになります。しかしこれはちょっといろいろやらかしていますし、あと現実のExcelはこんなにきれいなCSVを吐いてはくれません。
さらに言えばセルの中にカンマが入ると容易に死ねます。そのときはText::CSVなどを使うと良いのですが、そのあたりのは話はPerl入学式でサポーターの方に聞いていただければと思います。

あとこの辺りの計算、Excelでやればええやんということもあるのですが、Excel普段起動していなくて重いので手元にあるCSVで手っ取り早くやるみたいなことを僕はやります。

エモい便利情報

エモというか主観情報を列挙しようかなと思ったんですけれど、思ったらそんなに「初心者にとって」というのはないかなと思いました。
というのもPerlやろうがRubyやろうがPythonやろうがPHPをやろうが、出来る事は大体一緒です。違うのは使っている人とコミュニティとモジュールぐらいでしょうか。
もしプログラムを仕事にしようとしている方でもどれかやっておけば他をやるときの移行コストはそこまで高くはありません。すくなくとも第一歩を踏み出すときよりはだいぶ低いです。
じゃあPerlを今始める理由は? と問われると「Perl入学式があるから」と答えたいです。だれでも参加できてかつ活発で本当に本当にカジュアルな勉強会は他の言語には見当たらないからです。
とはいえPerl入学しては見たけれど他の言語も試してみたいなという方はサポーターにご相談ください。たいていのサポーターはPerl以外にもやってます。というかPerl界隈の人はPerlだけの人はなかなかいないです。


というわけで「ほんとうに使えるのか!? Perl情報!」でした〜。
あと他のネタで「Perl入学式受講生に向けるサーバの選び方」みたいなのも書こうとしたんですけれど、ちょっとそれは置いときます。

明日は@さんの「モダンPerlを知ってびっくりしたこと書く予定」です。実はPerl入学式でやっているPerlはモダンなんですよ!楽しみですね!!!!

Perlで手っ取り早くArduinoを操作するの巻

どうもこんばんわ。マコピーことマコピーです。
この記事は
Perl Advent Calendar 2014の9日目の記事です。

YAPC::Asia 2014で話したことの復習です

そういえばスライドに書きはしたんですが、詳細なコードなどを晒していなかったのでここいらでまとめてみようかという感じになりました。

何をしたか

ミクさんの紙を切り貼りしてネギふりをしました。Perlで。

どうやってしたか

材料は以下のものになります。

  • Arduino(DuemilanoveでもUnoでもLeonardoでもなんでも) 大体以下を読めば良い


PerlでFirmataプロトコルをしゃべるためのモジュールです。
FirmataはArduinoみたいなマイコンとPCなどのデバイスや他のマイコン同士で通信しあうモジュールで、
ArduinoだとArduino IDEにサンプルコードがはじめからついてくるのでここからはじめるのがお勧めです。

  • GROVEベースシールド

GROVEシステムというのを使うのでArduinoとGROVEを統合するのに必要です。

サーボモータは任意の角度にすることが出来るモータのことでミクさんの腕に使っています。
そんなわけで僕はGROVEスターターキットプラスについてきたやつを使っているのですが、スイッチサイエンスには在庫がないみたいです。
ケーブルはあったので以下のやつを使うのと

秋月電子で以下のサーボモータを買って組み合わせれば出来ると思います。

  • GROVE LEDモジュール

GROVE - LED - スイッチサイエンス
こういうのですね。
どこに使われているかというと、ミクさんの目です。

配線

FritzingにGROVEあるやろって思ったけれど無かったので写真で説明します。

まあこんなかんじでArduinoとGROVEベースシールドをガッチャンコした後に、

サーボをD3に、LEDをそれぞれD2とD5につなぎました。

そのあとお好きな絵を貼った厚紙にこのように雑に張り付けることで完成です。

実装

実装は大きく分けて2つからなります。

  • Webインターフェイスと通信してRedisに状態を書き込むAmon2製のアプリケーション
  • 無限ループの中でRedisの値を読み取ってFirmataでArduinoに送り込む部分

です。

何故このようにプロセスを2つに分けているかの理由を説明します。
Webインターフェイス部分はWebSocketを使っているのですが、コネクションを維持しないといけない関係上、この部分は必然的にAnyEventの上で動くことになります。
ですが、Device::Firmataは普通のブロッキングIOなモジュールなのでここに入れてしまうと問題が起きそうです。
この2つを同時に起動するためにProcletを使っています。
また、この間のプロセス間通信は多分別のものを最適なんでしょうけれど、たまたまRedisがローカルのサーバに立っていたので慣れているRedisに書き込むことにしました。

実際のコードは以下のリポジトリにあげてあります。

WebSocketのメッセージをそのままモデル層に投げててそのまま言われたメソッドを実行するというだいぶ雑な感じです。
Webアプリケーションなのでこのまま自宅の一角において誰かに使ってもらうことも出来る事は出来るのですが、こういう雑な作りなのと、この回路のせいで家が燃える可能性も考えてやめにしました。

完成の様子

Perlでミクさんのネギ振り from Makoto Taniwaki on Vimeo.

よく見たら配線間違えていて、右目と左目が逆ですね。

そんな感じで

YAPC中ではできなかった実演でした。
このデモではMacbookにつないでやっていましたが、YAPC中はRaspberryPiを用いてやる予定でした。RaspberryPiでもPerlは動きますよ〜。あとほかにもデモ用のカメラはRaspberryPiに繋いだRasPiCamからストリーミングで見せる予定だったのですがすべておじゃんになってしまいましたね><。
IoTという言葉も出てきてハードウェア界隈盛り上がっていますので、Perlを使って片足を突っ込んでみるのはいかがでしょうか?

YAPC::Asia 2014に行ってきました&喋ってきました #yapcasia

はい、時間オーバーつらい、マコピーです。

さて、去年一昨年とYAPC::Asiaはこちらに来てからずっと行っていたのですが、今年も行ってきました。

あと喋ってきましたので、スライドは以下。

Perl meets Real World

Perl meets Real World 〜ハードウェアと恋に落ちるPerlの使い方〜 - YAPC::Asia Tokyo 2014

Perl meets Real World // Speaker Deck

  • 結構初歩的な内容とか入り口的な内容をメインにしてどちらかと言うと布教する感じでした
  • ネギ振り出来なかったので何らかの形で皆様にお見せしたい
  • GeekDojoも開いておりますので、興味がある方とかツッコミがある方はTwitterかこちらに是非
  • その他やらなかったネタ

趣味開発のためのVPS/クラウド活用術

趣味開発のためのクラウド/VPS活用術 - YAPC::Asia Tokyo 2014

趣味開発のためのVPS/クラウド活用術 // Speaker Deck

  • 圧倒的時間不足……!
  • この件に関してはいろいろ話し足りない!!!!!
  • yanchaとかに有識者集まって欲しい
  • 皆様VULTRに興味を持っていただけたでしょうか。使ってみたいというあなたにgo-vultrという便利なコマンドを用意したのでぜひお使いください

その他見たトークとか

ウェッブエンジニアのローレベルプログラミング - YAPC::Asia Tokyo 2014

衝撃的だった。
cho45さんは普段仕事ではいろんなCPANモジュールでお世話になっている方なんですけれど、このトークは潜り方が極端だった。
まずアセンブラに始まり、さらにAVRを使いこなして一旦解放されたかと思いきや、Raspberry Piをベアメタルで操作しマジかよと口を開きっぱなしにさせられた後に、アマチュア無線始めました宣言で、「か、勝てねえ……」という思いに至った。
で、その後べろべろに酔ったcho45さんとHUBで初めてお会いした。そんでもって土下座しあったり一緒に飛び跳ねて、
お前は敵だ〜〜〜〜〜〜〜〜〜〜
などと言い合うなどした。非常に興味深い体験でありますが、cho45さんは覚えていらっしゃいますでしょうか。
ともあれ来年もハードウェアでがんばるぞい!という感じになりました。
来年は俺も潜るぞ。

DBIx::Class - what is it and what is it good for? - YAPC::Asia Tokyo 2014

今の仕事ではDBIx::Classを使っていて、なんとこれは5年選手の既存サービスのメンテ業などではなくまだリリースしていない新規サービスなわけでございますが、DBICというものは素晴らしいプロダクトでございます。
ただ重いとかそういうデメリットも有るわけですが、それを補う素晴らしい機能などを知れたのがこのトーク。
DBICのメンテナであるribasushiさんとは2日目の後にtagomorisさんやcharsbarさん、papixなどと一緒に朝まで居酒屋で飲むという貴重な体験をした。
僕は英語が読めず書けず喋れずだったんですけれど、なんかpapixと一緒に艦これをribasushiさんに紹介したり、そういう異文化交流をしていました。ビスマルクの画像見せて「Approve!」と言われたことは一生の思い出になりそうです。
なんか思ったんですけれど、やっぱり英語の、それもすごいプロダクトのメンテナと喋る機会なんてそうそうないわけで、喋らないにしても隣にいるだけでマジかよとかそういう驚き体験など出来るわけで皆もっとやるべきだし、凸するべきだと思う。もちろん迷惑かけたり不快にさせないことは前提として。
xtetsujiさんはすごくてHUBで筆談してた。ああいう方法もあるんだと思った。
YAPC::Asia Tokyo 2014 に参加してきました #yapcasia | #interest_ae
それから、海外スピーカーの方々はツイッター見てももっと日本人と話したかったというふうなことを言っていたようなので、せっかく日本に来たのだから日本でしか出来ない体験(=日本のPerlMongerたちとしゃべること)を出来るようにみんなした方がいいんじゃないかなと思った。
なんかこれは地方pmでも活かせそうな体験で、僕が副リーダーしているYokohama.pmなんかは地方から来た方がもしいたらもっともてなせないかなーとかそういうことを考えるようになった。そういう意味でも貴重な体験が出来た。
それ関連ですが、Dancer2作者のSawyerさんとリアルでuzullaさんとlestrratさんに助けていただきながらお話することが出来た。趣旨としてはawesome-perlはいい活動だからもっとお互いあの場で知っていこうぜということだった。いい人だった。恩に着ます。

まとめ

そんなわけで今年のYAPCは例年に比べてより濃い体験が出来ました。僕自身実は普段はPerlをがっつり触ってる人なんですけれど、今年のYAPCPerl一本で行くで!って言う人も選べばPerlのトークばかり聞けるし、Perlよくわからんからそのコミュニティだけ楽しむぜ!って言う人もイベントホールとか僕みたいな変わり種セッションを聞けば楽しんでもらえるし、そういう意味でTIMTOWTDIYAPCだったと思う。
強いて言えば会場キャパの問題もあるけれど、まあそれは運営の方々も認識していると思うので来年には改善されていると思う。large YAPC::Asiaっていう言葉もあったし。
あと、あと、僕がよりやってほしいなと思うのはTokyo以外のYet Another YAPCなわけですけれど、これは贅沢かな……。ともあれ開催されるなら飛んでいきたい。
まだまだ言いたいことがある。そういえばこれは大事な気づきでした!
!Important!
皆さん前に立ってしゃべるといろんな人から話しかけられます。僕なんかは知らない人に自分から話しかけるの非常に苦手なんですけれど、前に立つとそれをしなくても知らない人としゃべることができるので便利です。おすすめ。地方pmとか他のイベントでもいいと思うんですけれど。皆さんが立っていただけると僕は知見が得られて非常に幸福。自分が喋ることによって他の人が知見を得られたと言っていただけるのも非常に幸福。なのでみなさんやっていただきたい。現場からは以上です。

次回のYokohama.pmに関してはリーダーと相談しますので少々お待ちください

モジュール世界観考

とりあえずメモがてらに記述しておく。

対象読者

LLを使ったサーバサイドWebアプリケーションエンジニア

tl;dr

この記事に結論はない。思いを馳せたことを記述するのみである。
あと長いのでだらだらしたのを読みたくない方はブクマせず閉じるボタンをどうぞ。
ポエムなのでそういう苦手な方はブクマせず閉じるボタンをどうぞ。

ポジション

仕事ではPerlを使ったネイティブアプリケーションのサーバサイドAPIを書く。
趣味ではPerlを使ったWebアプリケーションやGolangを使ったライブラリやミドルウェア等々
Ruby on Railsは触ったことがない。

rapid developmentというコンテキスト

僕がWebアプリケーションフレームワークなるものを初めて触ったのはCakePHPで、それまではPHPでベタッと書いていたのを覚えている。Traditional PHPと言われる手法である。
当時はPHP5系が出始めでclassとかPHPで意味あんの?とか思っていてオブジェクト指向もあまり理解していなかったのだけれど、CakePHPを触ることでオブジェクト意味あるやんって思ったし、あらかじめ用意されている部品を使って素早く見れるレベルのWebアプリケーションを作ることが出来た。なるほど、と思った。
で、CakePHPが「rapid development framework」と当時も掲げていたし今でも掲げているわけで、うりとしては高速に開発できますよということらしい。

micro frameworkというコンテキスト

僕がCakePHPの次に触ったのがPythonのFlaskというフレームワークでこいつはCakePHPのようなフルスタックではなくルーティングとテンプレートエンジンのみを提供したまさにマイクロなフレームワークだ。
Flaskが提供していない部分、例えばORMapper等はSQLAlchemyとかを使っとけとか書いてある。僕はFlaskでDBアクセスをしたことがないのでこのあたりはよく知らない。この文脈から出たRubySinatraなんかもそうだったりするらしい。つまりこれらを使うにはモジュール/パッケージソムリエなる職能もしくは役割が必要である。

Webアプリケーションフレームワークの3要素

ここで僕が思うフレームワークの要素を書き出してみる。もちろん世の中のフレームワークにはこれらを搭載していないものもあるし、僕がいいたいのはそれらが不完全なフレームワークだということではない。

もしかしたらJSONを吐くAPIのサーバはテンプレートエンジンを必要としないかもしれないし、そもそもDBにアクセスをしない場合はORMapperは要らない。先ほどFlaskで必要なかった理由はそれはGoogle App Engine上で開発しており、データベースはCloud Datastoreを使っていたからである。ここでORMapperの定義も必要になってくるかもしれないけれど、SQLをその言語のインターフェイスで組み立てるだけでは不十分で、MapperたるにはそのSQLをDBに投げて帰ってきた結果をその言語に合うObject形式に変換するということろだと思う。

思うところこれはフレームワークとはただの糊である。ルーターやORMapper、テンプレートエンジンは複雑なWebアプリケーションを作るにあたってほぼ必須と言える要素だけれど、なにもこれをフレームワーク内に内包する必要はない。糊としての繋げる仕組みがあれば十分なのである。

仕事

僕が今の職業についてからもっぱらWebフレームワークはPerl5のArkというものを使っている。ArkはCatalystというフルスタックフレームワークを部品に分けて再構成したものである。
ルーター部分にはPath::AttrRouterを使い、テンプレートエンジンはText::MicroTemplate、ORMapperはDBIx::Classを用いている。であるがあくまでこれらは標準構成である。
僕の関わったプロジェクトではテンプレートエンジンをText::Xslateに、ORMapperをTengに置き換えたものが多かった。今ではDBIx::Classを使っているけれど、そこの組み換えも自由である。

ときどきプライベートではPerlを使ってWebアプリケーションをさくっと書くことがあるのだけれど、そういうときにはAmon2を使っている。Amon2はText::Xslate + Tengの組み合わせを推奨していて、さらにルーターは過去のバージョンではRouter::Simpleが使われていたが今ではRouter::Boomが使われている。

Mojo

で、最近PerlではMojoliciousというフレームワークが興ってきていて、MojoConfという専門のカンファレンスも開かれたらしい。で、Mojoliciousというのはフルスタック中のフルスタックで、cpanm Mojoliciousとかするといろんなツールが入ってくる。開発用サーバも本番用サーバも入ってくるし、非同期系のモジュールやスクレイピングに使うDOM操作のモジュールまで入ってくる。あとMojo::*空間が広大だ。Mojoに使われることを想定したプラグインやモジュールが大量にある。

Mojoに(モジュール|人)が依存することの是非

で、僕は以前Promisesというモジュールを非同期環境で使おうとしたことがあったのだけれど、そのときのPromisesはMojo::IOLoopに依存しており、Mojo::IOLoopは単独で存在するモジュールではなくMojoliciousに内包されているパッケージだったので、cpanm Promises::DefferedとするとMojoliciousまで入ってきて、お、おうということになったことがある。
WAFは他のものを使っているのにそのモジュールを使いたいだけでMojoliciousを入れるのはなかなか抵抗がある。厳しい。
最新のバージョンでPromisesはMojo::IOLoop依存がなくなっているので思う存分使えるっぽい。ので今度試してみたい。

でもこれはある面から見たMojoの難点であって、他のいくつかの面ではモジュールを内包することがスバラシイという場合もある。
たった一つの依存で #yapcasia のトーク応募ソーシャルランキングをつくる - ゆーすけべー日記
この記事を見たときにそう思った。Mojo入ってたらこういうスクレイピングするアプリケーションがそれだけで書けるのである。テンプレートエンジンやルーター、サーバも入っているのでここではcliアプリケーションになっているのをWebアプリケーション化するのもMojoだけで可能である。
これはすごいメリットで、先ほど言ったモジュール/パッケージソムリエが必要ないのである。

例えばCPANにはXMLを操作するモジュールは以下のものがある。

だいたいXML::LibXML使っとけば良いらしい。XML::XPathは破綻しているらしい。
とまあそんな感じでソムリエの意見を聞く必要がある。もしくは自分で地雷を踏みに行く必要がある。そして地雷を踏み抜いても耐えられる何本かの足が必要である。

で、MojoMojo::DOM使っとけば良い。それだけでたいてい事足りるようである。
そういうわけでフルスタックフレームワークは面倒臭いこと考えずにrapidに開発できる。これは非常に大きいメリット。

しかし、Mojoみたいな全部あるフレームワークを常に使っとけば良いというわけではないのがこの世の中である。

フレームワークが出来ないことがある

フレームワークはスイスアーミーナイフであってもスイスアーミーナイフが金を生み出すわけではない。スイスアーミーナイフはその鋭利な切っ先で物を切ったり缶切りで缶を開けるといった想定されていることにしか利用できない。
フルスタックフレームワークもそうで、当然提供されている機能しか使えない。
そういうときに結局ソムリエが必要になってくる。そういった時に人はどうするか? コミュニティに聞くしか無いのである。もしくはその道のプロフェッショナルを雇ってお金で解決するしか無い。
さもなくは、再発明である。個人的に再発明は悪だと思っている。でも必要悪だと思っている。しかし避けなければならない。その再発明品は自分、もしくは社内にしか目に触れられないのであれば、OSSのものよりもはるかに実績がない。
万人が使えるものは万人に使われるので、それだけの場数をこなしていると僕は考える。もちろん万人に使ってもらわないといけないので、宣伝も必要だし、使われやすい工夫も必要だ。でもそれ以上に様々な環境で使われるプロダクトは強い。
で、強いプロダクトかどうかを判断するのにソムリエが必要で、これまた経験が必要。
自分には経験がない人はどうするか。コミュニティに入ってプロフェッショナルたちとコミュニケーションを取るしか無い。お金は必要ない。TwitterとかYanchaとかLingrとかIRCとか、そういうところで聞けば良い。もしあなたが自分でコードを書く気があって、それをコミュニティのチカラで解決しようと思うなら、それ以上の代償は必要ないだろう。

awesome-*

ではコミュニケーションすら取りたくない人はどうすればよいのか? そういう人はコミュニティで活躍してそうな人のTwitterやらブログを見れば良いと思っている。さらに最近、awesome-*というgithubリポジトリが盛んである。

等々。さらにこんなのも出てきた

というわけでソムリエたちがこうやって見れる場所に貼っていてくれるのでそれに従うという手もあるのではないか。ここに書いていなければ、書いている方々に質問しに行くことになるが。

ところでawesome-perlがない。ので誰が音頭を取ってやって欲しい。僕は切に願う。

追記: お前がやれやということになったのでいかのレポジトリを作りました。異論やこいつも載せてくれという方はPull-Requestをお願いします。

https://github.com/mackee/awesome-perl

結論

  • フルスタックフレームワークは非常に心地がよく考えることが少なくて開発に集中できる
  • だがマイクロな部品を集めてサービスを作るという世界観もある
  • そのときにはソムリエが必要
  • あなたがソムリエではない場合は、ソムリエに聞くか、雇うか、ソムリエの書いたコードや文章を読めば良い

以上。

追記: 合わせて読みたい。
Sinatra frameworkに関する私見 - Beating the Averages(just like me)