株式会社はてなに入社しました
机の上に柱と壁を作っていた週末
たまには、というか技術系の記事はQiitaに書いてこっちは日々を晒そうかなとか突然思って書き始めてみる。
んで、最近は家の中に柱と壁作ってました。
柱とは一体
賃貸とは窮屈なもので壁に穴を開けようものなら退去時に多大な支払いを行わなければならないというのは皆さんご存知だとは思いますが、かといって壁に穴を開けたいという衝動に駆られることもしばしば。 ですがそこは、社会的な動物である人間、己の拳ではなくスマートに行こうということでいろいろ調べてみました。
動機といえば机が狭いことに尽きます。我が家は公称8帖であるものの、寝相の悪い自分をフォローしようとセミダブルのベッドを置いている関係上、寝る以外のスペースが狭いです。また自作PCでエオルゼアを楽しむエリアなんてのも設置しており、机を置こうとなったときに使えるスペースはわずかしかありません。
で、これを置いています。
マイデスク ワイド80cmタイプ ナチュラル木目 HDA-8045NM
- 出版社/メーカー: ナカバヤシ
- 発売日: 2010/02/16
- メディア: ホーム&キッチン
- 購入: 3人 クリック: 3回
- この商品を含むブログを見る
椅子は背もたれがあると邪魔なのでこれ。
サンワダイレクト バランスチェア ガス圧昇降タイプ 100-SNC038
- 出版社/メーカー: サンワダイレクト
- メディア: オフィス用品
- 購入: 1人 クリック: 10回
- この商品を含むブログを見る
長時間座るとヒザかケツが痛くなりますがそういうものなので慣れなんだろうなと思いました。
でもこの机はせまくて、奥行き45cmしかないので、Macbook Air 13inchを置くとだいたい終わりです。で、さらにそこから電子工作のためのスペースや飯くったりすると狭くて狭くてどうにかならんもんかと思っていました。 そこで気づいたんですけれど、机の上にものが多すぎるな、と。ドライバーしかりTimeMachine用のHDDだったりUSB充電器だったり。そういうのどっかにやれないかなと思って調べてたらこういうのがあって、
ディアウォールで賃貸の部屋に柱を立てて壁一面のテレビ台&棚を設置。
なるほどなーっと。 まあブコメとかで地震とかには弱そうだなと思ったけれどそうなったときに命ぐらいは助かって上に乗っている奴とかはまあ諦めるかとなって、ベッドまでの距離だと外れても飛んでこないかなという位置に置こうかなと思いました。
実践
とりあえずAmazonでディアウォール頼みました。
Kanaoni 若井産業 ディアウォール 上下パッドセット ツーバイフォー用 DWS90LB ライトブラウン
- 出版社/メーカー: 若井産業株式会社
- メディア:
- この商品を含むブログを見る
そんでもって柱はどうしようかなと思って、最近興味のあったカーシェアを契約してスイフトでシュッと近くのホームセンターへ。
かーシェアで木材を買いに来た
— トーカナイザの守護霊 (@mackee_w) 2016年3月2日
木材を切ってもらっている
— トーカナイザの守護霊 (@mackee_w) 2016年3月2日
1カット32円
— トーカナイザの守護霊 (@mackee_w) 2016年3月2日
いわゆる買ったのはツーバイフォー材というやつで、建築材料コーナーに有りました。ホームセンターはたいてい何センチで切ってくださいと言うとシュッと切ってくれるので、便利です。なんか空気圧でキュイーンって切る機械でした。
そんでもって我が家の天井が何センチでーってのはメジャーで測っていたのでそれでスパっと切ってもらい、端材も机の横幅プラスアルファぐらいだったので、一緒に持って帰りました。
ただ、
みなさん、天井まで届く木材はスイフトだと運ぶのにギリギリすぎてお勧めできません
— トーカナイザの守護霊 (@mackee_w) 2016年3月2日
という感じで、視界も不良ですので、ホームセンターでは軽トラ借りて持って帰ったほうが良さそうです。往復めんどくさいから借りなかったんですけれど、ちょっと次から軽トラ借りようってなりました。
で、家に持って帰ったあとに電動ドライバーをAmazon Prime Nowで購入しまして(ホームセンターのは割高だったので)、2時間後に届くわけですが。
ブラックアンドデッカー(BLACK+DECKER) コンパクトパワーアシスト 3.6V AS36LN
- 出版社/メーカー: Black & Decker
- メディア: Tools & Hardware
- 購入: 1人 クリック: 28回
- この商品を含むブログを見る
まあこれで下穴を空けつつ粛々とやりまして、
そんな感じで一旦便利になりました。
壁とは一体
しかし柱が出来ると人間は欲が出来て壁が欲しくなるものです。まあオッサーレな感じでドライバーを吊るしたいなと思ったんですけれど、調べてたらこんなの見つけまして、
あ、エエなあと思って、またホームセンターに行ったのでした。
前行ったのは島忠ホームズなんですが、次行ったのは木材がいっぱい揃ってるコーナンPROに行きまして、そこでまたカットしてもらいつつ買いました。 端材は使いみちなさそうなので処分してもらいました。
で、こうなりました。
ケーブルが雑なのでまとめたいという感想はありますが、夢が広がる感じはして便利ですね。
まあそんな感じでした。今度近くにホームセンター出来るっぽいので楽しみです。また木材を切りたい。
sqllaというSQLビルダーを書きました。
sqllaというSQLビルダーを書きました。特徴はある程度型安全であること、リフレクションを使用していないこと、既存のクエリビルダよりある程度高速であることです。
使い方
インストールはごく簡単で、goが入っている環境で以下のコマンドを打ちます。
$ go get github.com/mackee/go-sqlla/cmd/sqlla
まず以下の様なテーブル構造を表したstructを用意します。
そして、sqllaに必要なタグを付加していきます。
また後述のgo generate
で必要なコメントも足しましょう。
user.go
//go:generate sqlla //+table: user type User struct { ID uint64 `db:"user"` Name string `db:"name"` }
そしてこのファイルが置かれているディレクトリ内で以下のコマンドを実行します。
$ go generate
すると、user_auto.go
というファイルが生成されます。
このファイルにSQLを組み立てるメソッドが生えています。以下のように使います。
q := NewUserSQL().Select().ID(uint64(1)) // SELECT id, name FROM user WHERE id = 1 query, args, err := q.ToSql() row := db.QueryRow(query, args...) var id uint64 var name string err := row.Scan(&id, &name)
ID(uint64(1))
のところはuint64
の型以外のものを入れるとコンパイル時にコケるようになっているので安全ですし、補完も効くため大量のテーブルや複雑なカラムがあるアプリケーションを書くときに便利です。
またLIMIT句やOrderBy句も使うことが出来ます。
基本的なCRUDについてはサポートしています。
今後やりたいこと
READMEにTHIS IS A ALPHA QUALITY RELEASE. API MAY CHANGE WITHOUT NOTICE.
と書かれているようにまだexperimentalな感じでちょっと常用には耐えない感じですが、いろいろ悩んでいるのでブログを書いてみました。
今後やりたいこととしては、
- 文字列連結に
+
を使っているのをやめる。コレがかなり速度的に足を引っ張っていると思われる。 - IN演算子のサポート。以下の様なものを考えている
NewUserSQL().Select().IDIn(1,2,3,4)
ちなみに演算子周りはちょっとまだ不格好
NewUserSQL().Select().ID(uint64(100), sqlla.OpGreater)
=
のときは省略できるように可変長引数でやっているので、演算子が後置になっている。sqllaの演算子を覚えなくてはならないのでどうしようかなとなっている。
これ書いてて思ったけれどまだint系とstringしかサポートしていなかったのでfloat系とtime.Timeとかをサポートする。あと[]byteでblobぐらいかなあ。
JOIN句のサポート
NewUserSQL().Select().Name("hogehoge").Join(func (r *UserJoiner) { rj := NewUserItemJoiner() r.RelationId(rj.UserId) r.AddColumn(rj.ItemId, rj.Amount) }) // SELECT user.id, user.name, user_item.item_id, user_item.amount FROM user JOIN user_item ON user.id = user_item.id WHERE user.name = "hogehoge";
出来るかどうかはやってみないとわからない。
とまあそんな感じでオレオレDSL的なものを覚えないといけないので、シンプルなやつでええわ〜ってのは、id:motemenさんのsqlfが良いと思います。
また、仕事ではsquirrelを使っており、sqllaのメソッドチェインとかもsquirrelを参考にしています。
そもそもの動機はsquirrelがリフレクションを使っており、goの型がキャンセルされるので型を使うようにしたかったというのがあります。
その他
go-genddlなるものも書いておりました。仕事でこれの改造版を使っております。
上で書いたようなタグ付きstructをCREATE TABLE ~
といったDDLに変換してくれる君です。最近sqlite3もサポートしており、sqllaのテストでも使っております。
github.com
改造点は複合インデックスや複合ユニークキー、複合PKが貼れたり出来るところですが、ちょっと大雑把すぎるのでもっとちゃんとしたいのにしたいところ。
と思っていたらdrone.ioで似たようなのが出たっぽいです。
みんな似たようなこと考えているんですね、、、
また、仕事ではmigrationにGitDDL
を使っております。ちなPerl
metacpan.org
migrationスクリプト的なものを書かずに済むので非常に便利なのですが、いかんせん起動が遅いのでGoで書けないかなと思っていたけれど、SQLパーサーだったりDiffを出すところが非常に複雑というか僕の腕ではとても書けなかったのですが、最近id:soh335さんがschemalexというのを書いていた。
まだ試してはいない。
sqllaにある程度機能が入ったら次はORM(structでは?)だと思いますのでご期待ください。
YAPC::Asia Tokyo 2015に参加&トークしてきました #yapcasia
どうもマコピーです。 昨年に引き続きトークしてきました。
しゃべったこととしては、以下の2つ。
- 過去に行ったプロポと呼ばれるラジコンのコントローラの信号を模倣することで自動制御を行う
- MultiWiiというオープンソースのフライトコントローラが喋るプロトコルをPerlで実装して通信して自動制御を行う
またデモできなかったし、ソースコードは毎度のごとく整理してからアップしますが、去年は12月に公開という遅いスピードでしたので、欲しい方は催促をお願い致します。
聞いたトーク
メリークリスマス!
- Larry WallによるPerl6の機能紹介かなと思いきや、概念トークの香りがしつつ、概念が実体化されてPerl6へと消化されていく過程の話
- 時折ジョークがだいぶ混入してきて同時通訳の人も戸惑っていた気がするw
- 主軸はトールキンのホビット物語をPerl5、指輪物語をPerl6に関連付けて
Second System Syndorome
の話や、Perl5の資産がありながらも夢の様な言語、Perl6を作るのに何を捨てて何を受け継ぐか、という概念的な話でした。すごく物語チック。- 夢の様な言語、というのは僕は強力なGrammerやマルチスレッドなどを見てLL大統一言語(物理学の大統一理論になぞらえて)という言葉を発想してそれからなのだけれど
- 「成功した言語を作れるのは世界を作れる人」という趣旨の発言があったが、言語というのは世界であり、世界もまた言葉で表現されるんだなと、同人小説を書いている身としては感慨深い感じでした。特にLarryは言語学者であり、トールキンもまた言語学者なわけで、言語を作るのに必要な能力が言語を知り尽くす事であるならば、世界を作るのに必要な能力もまた言語を知り尽くすことであるわけで、それぞれプログラミング言語、ハイファンタジー小説と分野は違えど共通する点がいっぱいあるなってなってます。ちょっとグッときてて言葉が散らかっています。
- というわけで、Larryは予防線を張りまくっていたけれど、クリスマスにはベータ版が出るとのこと! それまでにはデカい3つの仕事があるけれどやってくぜ!っていう宣言で締めくくりました
Web由来の組み込みエンジニアの半年間のすべて 〜WebとiOSとBLEとハードウェアデバイスのこと〜
- 仕事でデバイス作るのって想像に容易くないぐらい大変だと思うんですが、聞いていると想像以上に大変だなあと
- 何が大変かというと、これは僕が普段サーバサイドでクライアントアプリを書いている人やデザイナー、ディレクターなど多くの職種がかかわる環境で働いている経験から、分業しつつ1個のものを作るっていうのはめちゃくちゃ大変で、特にまたがる領域なんかはお見合い落球とか押し付け合いとか意識が薄れるゾーンでもあって、でもそこが重要なんだけれど……みたいな感じです
- ハードウェアの場合、分業の領域は kazuphさんの場合だとメカ(機械機構や構造)、エレキ(電子回路)、ファームウェア(マイコンのソフトウェア)、APIサーバと分かれているようですが、漏らしていたのが「エレキの人がもう少しファームを書いてくれれば」というところ。僕は前仕事でやった時は回路引いてファーム書いてファームと通信するライブラリまで書いて、その上を他の方にお任せしたんですが、これはうまくいった。しかしこれはあくまで一般に出回る製品にする仕事ではなかったのでよかったのですが、この話だとAkerunは一般に出回る製品なわけです。相応のクオリティが要求されるし、求められるレベルも高い。のでそれぞれのプロがそれぞれの領域にすごく意識を集中している。そこでまたがる領域、この場合だとおそらく電気回路からの入力をマイコンで受けてそれを上位のレイヤーに引き渡すみたいなところだと思うんですけれど、そこはそれぞれが分からないと書けないので、両方出来る人が1人でやらない限りは、お互い歩み寄って意図を伝えて議論をして仕事しないといけないんですけれど、これがめちゃくちゃ難しい!!!!!!!
- ハード一人でやって来たけれど複数人でやるとこういうのも起こるんだなあという感想をいだきました
Perlで学ぼう!文系プログラマのための、知識ゼロからのデータ構造と計算量
- 僕は高校、大学とガチ理系なはずなんですが、コンピュータサイエンス出身ではなくずっと電気学科で回路図を見て計算をしていた人間なので、このあたりの計算量の話とかデータ構造の話とかはなあなあにしてきた部分ではありました。なあなあだけれどぼんやりでもWebエンジニアは出来るんだなと今思ったけれど、同僚に突っ込まれることはある……
- ほいでこのトークを聞いて連結リストとかB木の計算量がO(n)だったりO(log n)だったりするのは知識では知っていたのだけれどあらためて説明されて納得という形まで落とし込めたのはすごいよい体験だなと思った。
- あとデータ構造はどうすれば理解が深まるかという質問があって、僕の体験を話すと、去年pagerdっていうページャー専用DBなるネタ兵器を作ろうとしてそのときに手でDBを作るようなことをしたのだけれど、DBをイチから作るというのは結構よくて、目的にあった効率的なデータの持ち方というのを調べまくって考えるのでだいぶ良いです。マッチョですがおすすめいたします
PietでLISP処理系を書くのは難しい
- 若干僕はプログラミング言語愛好家的な面もあると思っているんですが、もっぱら実用的なやつを調べるばっかで、難解プログラミング言語に関してはノーマークだったわけですが、Pietはヤバイ。
- Pietって画像がソースコードで1ドット1ドットが命令になってドットの上をプログラムカウンター的な奴が走っていくっぽいんですが、今でも自分が何を言っているのかわからない程度の難解さかつ面白いトークでした
- これがソースコードですと言って、よくわからないドット絵(人間には何が描かれているのか理解できない)を毎回見せられるのがやばい
- さらにその上に独自にLisp処理系を実装しようとしている時点で、かなり先端を突っ走っているホビーと言える。とにかくやばい
- KMCという団体がなかなか謎で京大マイコンクラブと銘打っているのに会場にいる人間に入会を迫ってくるし、トークしている方がもっともおすすめできるPietのエディタがKMCに入らないと入手不可能という権威を誇っている。なおこのあと公開されたようです。
- Pietはやはり人間に難しいので、ニーモニック的なAltPietとも言うべき言語があるらしく、さらにそれを拡張したAltAltPietがあるらしく、ここが地獄の一丁目かと思えるが、ホビーなのでそんな状況でも楽しめる人間は大した種族だなあという発見をした
Perl6 on JVM: It works??
- Perl6は使えるのかどうか?という話
- Perl6の処理系の一つであるRakudo StarはJVM実装とMoarVMと呼ばれる独自のVM実装があり、これらが平行して開発が進められている、というのは冒頭のLarryの話でもありましたが、そのうちJVM実装は現時点で使い物になるのか?という検証
- 結果的に言えばWebアプリケーションでよく使われるであろうパーツ、例えばHTTPクライアントであったりDBであったり、そういったものは(一部難はあるが)ひと通り揃っている
- 一つどうしてもきになるのはやはり起動速度で、
perl6-j -e 'say "Hello"
とやるだけでも16秒ぐらいかかる。ちなみに僕の環境だと最新のRakudo Starでperl6-j --version
とやったら5秒かかる。 - Webサーバは起動しっぱなしなので起動時間がそこまで重要な要素になってくるかと思われるともしかしたら気にならないかもしれないし、多くの人が触っているJVMでJITが効くので起動しっぱなしアプリはもしかしたら速いかも。これは要検証ですね
Parallelism, Concurrency, and Asynchrony in Perl 6
- タイトルの通り並列、非同期、平行を軸にPerl6の機能を見ていくというもの
- Perl6はマルチスレッド言語です!!!! これは驚きとともに歓喜
- Perl5はスレッドを(まともには)扱えない。我々Perl5でアプリケーションを書いている人間でマルチコアを使いたい場合はforkを使っていた。コレはいろいろな面で良くていろいろな面で不利を抱えているのだけれど、そんな理由もあって僕はマルチスレッドを理解しやすく扱えるGolangを最近書いているというのもある。
- 宣言的に処理を書いたら勝手にパイプが組まれてストリーミングプロセッシング的なことが出来るという話があって「!?!?」となった。Perl6のスケジューラ氏が気になる。実用的かさておき夢っぽい。
- C#のasync/await的な機能があるが、もっと抽象化されているsupplyとかreact、wheneverというのがあり、これらは同期的な処理を非同期的な処理に変換しただろうかという発想で出てきたものらしい。wheneverはforループにあたる。PromisesとかChannel的な挙動も出来るのだけれど、わかりやすい、ここは桃源郷か? なおこのあたりがRakudo Starにマージされたのが5日前らしく、今のリリースパッケージには入っていないっぽい。
- このあとPerl6のOO的なコードが出てきてPerl5脳が機能停止したので、だいぶ読めない。class methodあたりはM族ライブラリ(Moose/Mouse/Mooなど)で使えるのでまあわかるが、
%!hash
ってなんだ!?- 調べたところ!がつくとprivate accessorになるっぽい
- 飛行機の席を取るときにマルチスレッドで並行で走ると同時に同じ席をとったりしてやばいよねーという話題で、そのときにメソッドをアトミックに実行する(おそらくarroundして入り口でロックを取り出口で外す)ようなふうにmixinしてくれる(mixinなのかはコードが読めないので憶測)やーつで、いかがそのソースコード。質疑応答で複雑ではないか?というのに対しすごく薄いと言う答えであったが、コード量はそうでもないがPerl6力が足りなくて読めない
- というわけでPerl6にすごく期待が持てるトークでした。たぶんリリースまでにいくつかのシンタックスの最適化とか機能の実装が入ると思いますが、そのあとに皆さん気になっているパフォーマンス改善の話がやってくると思うので、僕は座して待つ。
Profiling & Optimizing in Go
- bradfitz氏のGoプログラムのチューニングのライブコーディング
- 普段仕事でGoを書いているのですがよく「メモリアロケーションがー」とか「文字列連結がー」とか言われて、ふむふむなるほどと思いつつもぼんやりしていた理解なのですが、軽快なライブコーディングでちょっとだけ理解が進んだ気がする。
- 例えば
[]byte
をstringを受ける関数に投げるとき、しかもそれが複数の文字列を連結した渡したい場合ってよくあるんですけれど、お手軽にやるなら[]byte("hoge" + "fuga" + "bar")
みたいな感じにするんだけれどこれだと何回かメモリアロケーションが走ってメモリ確保にCPUがぶんどられてしまうので、それならfmt.Fprintf
でio.Writer
実装しているやつに一気に流し込もうや、って話とか、fmt.Fprintf
はinterface{}
で受けるのでそれだとreflect
が使われて遅いので裏技的にsync.Pool
使ってreflectを回避するとか(この方法はネタなので実際にはやらないでねとのこと)、そういう話でした。 - 便利ツールとしてpprofでcpuを使っているステートメントを見たり、同じくメモリも解析したり、さらに複数のベンチマーク結果を後から比較していい感じに出してくれるツールなどピリッと辛いツールが出てきてGo way〜って感じでした
その他
- YAPC終わりとみんな勘違いしているけれど、あくまで今の体制でのYAPCが終了なわけで誰かが挙手すれば続けられるという状況は実は2013年が終わった時とあんまり変わらないんじゃないかなあと思う。外から見れば
- で、今回の2000人規模がデカすぎて、準備の負荷が高いからもっと小さい規模でやるというのは結構な人から言われている意見で、それをポツポツやるのもいいと思う!!!
- ア、Yokohama.pmやらないと
- Beaconというのもやるらしく期待。僕はWebの人でもありMakerの人でもあると(自分で勝手に)思っているのだけれど、本来これら2つは別に明確に分ける必要はなくて双方が双方で歩み寄って干渉しあう事できないかなーと思っていたので、(もしかしたらそういうことじゃないかもしれないけれど)すごく期待。
以下は闇
今回の目標は「今喋りたいことを今喋る!」ということなんですけれど、それはお概ね達成出来ました。特にアナログスイッチを使った切替回路とかフェイルセーフの仕組みなどは実装した当時からコレをいつかどこかで話したいなーと思っていて、記憶からなくなる前に喋れたので良かったです。
でもちょっと喋りながら反応を見ていて思ったのが、聴衆が期待していたトークともしかしてだいぶ違っていたのでは?という点についてです。 民生のクアッドコプターのうち、やはりParrot社のものがソフトウェアからのハックがしやすく、そもそもLinuxを積んでWiFiが喋られる、さらにSDKまで公開されているものは他にありませんし、今回のトークには持ってこいかと思われます。 そうなんですが、僕はやるとなれば持てる技術を投入して自分が面白いと思える方向に突き進む人間でして、特に趣味となれば合理性をガン無視して面白軸で行くのですが、さてそれがあのタイトルで見に来た方の期待に沿ったトークであったかと言われると、ちょっと自己満足すぎたのではないかなあと思いました。
と長々と反省しておりますが、多くの人がよく分からないが面白く話す人もいるのでそっち方向に鍛えるか、それともこういう尖ったテーマを大勢の前で話すのは控えるか、という話になるなあと思いました。 そんなわけで、今は皆様の感想がなくて僕が卑屈になっていっている一方なので、感想をください。よくわからんかったとかでもいいので・・・
そういうわけで画面汚し失礼しました。
これを聞けばドローンを作れるという発表をYAPCに応募しています #yapcasia
トークはこちら
以下は長いので、めんどくさいなら上の詳細のところを見てRTアーンドはてブアーンドいいねお願いします。
何故応募したか
僕にはとにかくハードウェアの話とWeb開発の話を交えて誰かとしたいという思いがあって、そんなわけで去年は以下の様な発表をしたわけであります。
この発表は何をやったかというと、「こんだけお手軽になってこんだけ楽しくなっているから君たちも来いよ! カモーン!」みたいな呼びかけです。 概要と触りだけみたいな感じなんですけれど。
じゃあ他に何を話すんだよというわけなんですけれど、まだこれは入り口しか見せてないわけです。入り口さえ見せれば、それだけで入ってくる人もいるでしょう。実際にそういう方を見ましたし、非常に僕はそれで満足なわけです。 でもやっぱり、入口に入った後の話を僕はそう言えばしてないなあと思って、そう思った時に自分に出来る最高のハードウェアの話はなにかといったら、一時期仕事で作っていたドローンの話なわけです。
で、何故ドローンの話をするかというと、やはり人間たるもの目的がないとなかなか一歩が踏み出せないわけで、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触りはじめてあんまり時間立ってないのでそれ違うとかあればコメントなどで教えていただきたいと思っております。
材料
- Go 1.4以降
後述する
func TestMain(m *testing.M)
を使うため - github.com/lestrrat/go-test-mysqld lestrratさん作のTest::mysqldを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なども掃除してくれます。
というわけで他の言語のテストフレームワークで言うsetup
でmysqlサーバを起動し、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でこういうスタイルでテストを書いていってるのでこうなっているという感じです。
参考
その他
あと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可能なので、まあそうなるか。
さてここまでは普通のトランザクションがめんどくさくなっただけな感じだったが、次からはデッドロックとかその辺りの挙動を見て行きたい。普通のトランザクションとどう違うのかが知りたい。