oinume journal

Scratchpad of what I learned

2014年振り返り

1/3に2014年の振り返りをしている時点ですでに周回遅れになっているわけですが... 技術的な振り返りは2014年に使ってみた技術に書いたので、仕事やプライベートのことを振り返ってみる。

  • 仕事では7月ぐらいにゲーム系じゃなくてメディア系を立ち上げる部署に異動した。Unityを触ったりしたんだけど、やっぱりゲームを作るのは相当な労力がいるし自分には向いてないんじゃないかなぁと思ってメディア系の部署へ。あと今回は第一線でバリバリ開発する立ち位置なので今は産みの苦しみを絶賛味わってます。あとちょっと...
  • プライベートでは、1月ぐらいに車をお義母さんからゆずってもらって15年ぶりぐらいに車を運転してみた。15年間ペーパードライバーだったんだけど、奥さんが妊娠してたので強制的に病院の送り迎えをすることになり、近距離ならなんとか運転できるようになってきた。人だけは轢かないように心がけてる。車種はトヨタのAllionっていうセダン。すでに12万キロ走っているのでそろそろ壊れる気がする。
  • あと人生の一大イベントで4月に息子が生まれててんやわんや。でもとてつもなくかわいくて毎週成長を見るのが楽しい。仕事できる時間が減り、自分の時間もほぼゼロになってしまったけど、息子を育てる方が社会に貢献できている気がするw 出生率があがれば高齢化社会や人口減少問題が緩和されるらしいので、もう一人ぐらい頑張りたいところ。
  • 飼い猫のししまるが2歳に。2014年は年初から誤飲事件が発生して救急病院に通った。おかげでペット保険の必要性を認識して加入。その後ちょいちょい医者にかかっているのでこれは入っておいてよかったなと思う。今はししまる毎日元気に走り回って息子の攻撃からもひらりと身をかわしている。
  • Amazonでモノを買うのを辞めて、yodobashi.comのヘビーユーザーになった
  • ライブは2月にAvril、11月にKnotfestでKORNを見たぐらい。毎年行っていたサマソニも自粛したので今年こそ行きたい。KORNまた今年も来日しないかな。

2014年に使ってみた技術

新年明けましておめでとうございます。2014年内に書き上げるはずの記事がずっと下書きのまま眠ってしまっていた... 2014年は細かいものを含めるといろいろ新しいものを使い始めたのでそのまとめ。

Ansible

Chefがあまり好きではないのでAnsibleを今やっているプロジェクトで入れてみた。

  • DSLを覚えなくてはいけないのはどちらも一緒
  • Ansibleの方が仕組みがシンプルでPlaybookに書いた順に実行されるのでわかりやすい
  • Dynamic Inventory便利
  • AnsibleはYAMLなのでロジックをゴリゴリ書くのには向いていない
    • Chefはその点Rubyのコードなのでなんでもできる

という感じでどっちもどっちだなという印象。個人的にはChefのようにコードが実行される方がフレキシブルでいいと思っているので、Fabric + Cuisineも試してみたい。

Packer

Vagrantで使うイメージファイルを作るのに使った。便利。時雨堂のリポジトリがとても参考になった。

awscli

便利すぎ。AWSのドキュメントは情報量が多すぎて読むのがつらいんだけど、代わりにこのツールのドキュメントを読むとAWSで何ができるのかが大体把握できるので( ・∀・)イイ!!

Go

Cをちょっと今風にした言語。言語仕様としてはJava 1.2ぐらいのレベルのもので正直扱いづらい。ただ、あえて言語仕様をシンプルにしていて、読みやすさを重視しているというのは大規模開発には向いているのでは?と思って導入してみた。今めちゃくちゃ勢いあるし。

導入してよかったなと思う点は、

  • 静的型付け言語なので安心してリファクタリングできる
  • 半年ごとにバージョンアップするしで着実に進化はしている
  • go getなどのツールが充実してる

つらいところは

  • ベストプラクティスがわからないことが多い
  • Webアプリケーションフレームワークやパッケージ管理が乱立し過ぎていて選択が難しい
  • 他の言語で当たり前のようにできることができなかったりする

というところかなぁ。ブログにもちょいちょい小技を書いているのでよかったらどうぞ。

percol, peco

開発環境回りではこれが一番効果があった気がする。サーバーサイドのエンジニアだとターミナルという黒い謎の画面を見て怪しげなコマンドをたくさん打たなくてはいけないんだけど、そのコマンドの履歴の検索とか絞り込みが画期的にやりやすくなる。最初はpercol使ってたんだけど、pecoの方がバイナリもあって楽にインストールできるので乗り換えた。あとはzsh関連のよさ気なヤツを入れてみた。その辺の話はここで。

tmux, tmuxinator

3年前まではscreenを使っていて、その後はMacのiTermで複数タブでしのいでいたんだけどターミナル環境見直しの一環でtmuxを導入してみた。詳しくはターミナル環境を見直す(3) - tmux編を見てもらえればと。

tmuxinatorは

$ mux start sample

ってやるとこんな感じのYAMLの設定ファイルに書いた内容でtmuxのwindowがバババーンと立ち上がるのがすごい便利。

Angular.js

ちょっとした自分向けのツールで使ってみた。あまりJavaScriptが得意ではない自分としてはすごく簡単にdata bindingできるので純粋に便利だなぁと思ったけど、大きめのアプリをAngularで実装しようと思うと覚えることが多くてツラい印象。「こういう時どうするんだっけ?」っていうのをイチイチググらないとAngular way がわからなくてつらい感じ。

Atom

最近はIntelliJで開発することが多いんだけど、ちょっとしたテキストの修正にはGitHub製のAtomを使ってる。

  • Markdownのプレビューがデフォルトでできる
  • CoffeeScriptで拡張できる

のがメリットかなぁ。試しに突然の死ジェネレータのパッケージを作ってみたりしたのと、Qiitaにこんなのを書いたりした。

入門Ansible

入門Ansible

Macで特定のポートを使用しているプロセスを特定する

ターミナルで

$ lsof -i :3000
COMMAND  PID   USER   FD   TYPE            DEVICE SIZE/OFF NODE NAME
go   2087 a11920  269u  IPv6 0x7574d6a56e437f1      0t0  TCP *:hbci (LISTEN)

って打つと3000番ポートを使ってるプロセスが調べられる。

Goで標準出力をキャプチャする

こんな感じかなぁ。http://play.golang.org/p/2DFtYAsFO9

package main

import (
    "bytes"
    "fmt"
    "io"
    "os"
)

type Capturer struct {
    saved         *os.File
    bufferChannel chan string
    out           *os.File
    in            *os.File
}

// 標準出力をキャプチャする
func (c *Capturer) StartCapturingStdout() {
    c.saved = os.Stdout
    var err error
    c.in, c.out, err = os.Pipe()
    if err != nil {
        panic(err)
    }

    os.Stdout = c.out
    c.bufferChannel = make(chan string)
    go func() {
        var b bytes.Buffer
        io.Copy(&b, c.in)
        c.bufferChannel <- b.String()
    }()
}

// キャプチャを停止する
func (c *Capturer) StopCapturingStdout() string {
    c.out.Close()
    os.Stdout = c.saved
    return <-c.bufferChannel
}

func main() {
    c := &Capturer{}
    c.StartCapturingStdout()
    fmt.Println("hello")

    captured := c.StopCapturingStdout()
    fmt.Println("captured:", captured)
}

GoLangでJavaのenumっぽいライブラリ作った話

はじめに

Goでは言語標準でenumという機構がなくてつらかったのでそれっぽいものを作ったよという話。

Goではiotaを使って以下のようにして定数を列挙することはできる。

const (
    Go int = iota + 1
    Python
    Ruby
)

ただし、このやり方だとJavaのenumのように

  1. 値から名前(↑でいう"Java"という定数名)を取得したり、名前からその値を引く
  2. 全ての値を列挙する
  3. 全ての名前を列挙する

というようなことができない。下記のように値→名前を取得する関数を定義することはできるので1.はなんとかなるわけなんだけど、これを毎回書くのは面倒なので goenum というライブラリを作ってみたよという話(ここからが本題)。

http://play.golang.org/p/5nrPOMEQKZ

package main

import (
    "fmt"
)

type Lang int

func (l Lang) String() string {
    switch l {
    case Go:
        return "Go"
    case Python:
        return "Python"
    case Ruby:
        return "Ruby"
    }
    panic("Unknown value")
}

const (
    Go Lang = iota + 1
    Python
    Ruby
)

func main() {
    fmt.Printf("%s: %d\n", Go.String(), Go)
    fmt.Printf("%s: %d\n", Python.String(), Python)
    fmt.Printf("%s: %d\n", Ruby.String(), Ruby)
}

goenum

goenumでは列挙する値はconstではなくstructを使って定義する。

type LangsEnum struct {
    Go     int
    Python int
    Ruby   int
    Haskel int
}

でで、その構造体(↑でいうLangsEnum)に下記のようなEnum()というメソッドを定義しておき、goenum.EnumerateStruct という関数にLangsEnumの実体を渡す。goenum.EnumerateStruct() という関数は goenum.Enum を返すんだけど、これが

  • 値→名前
  • 名前→値

の変換を行ってくれる。

var Langs LangsEnum = LangsEnum{1, 2, 3, 4}

func (e LangsEnum) Enum() goenum.Enum {
    // Make Enum from Langs
    return goenum.EnumerateStruct(&Langs)
}

以下は実際に使ってみた例。

func main() {
    var langs goenum.Enum = Langs.Enum()

    // 名前の列挙
    fmt.Println(langs.Names())
    // --> [Go Python Ruby Haskel]

    // 値の列挙
    fmt.Println(langs.Values())
    // --> [1 2 3 4]

    // 値 -> 名前の取得
    fmt.Println(langs.MustName(1))
    // --> Go

    // 名前 -> 値の取得
    fmt.Println(langs.MustValue("Python"))
    // --> 2
}

本当は構造体で元の列挙値を定義するやり方にはしたくなかったんだけど、自分のGo力が低すぎるのでこういう仕上がりになっているので、もっと良いやり方があったらぜひ教えて欲しいところです。

追記

Big Sky :: Re: GoLangでJavaのenumっぽいライブラリ作った話でstringerというコマンドを使う方法を教えてもらいました。1.4では go generate コマンドもあるし、これ使ってgenerateするのがIdiomatic wayのような気がしますね。mattnさんありがとうございます!