ミラン・クンデラ『冗談』

年明けすぐのマニラへの出張で読もうと思って持ってバッグに入れていきました。

行きの飛行機で引き込まれ、マカティの若干黴臭いホテルの部屋でサン・ミゲルを飲みながら読みふけり、帰国してすぐ自分の部屋で読了。

最後のページで全てが完成する。作品としてのあまりの美しさに感動して、しばらく言葉が出なかった。僕が今まで読んだ小説の中でも最高のものの一つでした。

あまりに印象に残る箇所が多かったので、抜き書きをしました。しかし、僕の抜き書きを見てしまうことで、それぞれと正しい形で、つまり作品の中で出会うという、人生で一度しかない機会を奪ってしまうという事は、凄まじい罪悪に感じられます。このインスタグラムの下から抜き書きです。見るのは読了後でお願いできればと…。

Kundera in Manila

A photo posted by fujimura (@ffu_) on

p.58

いくつもの顔をもっていたのは私が若かったからで、じぶんが何者で、どういう人間になりたいのかじぶんでもわからないからだった。

p.58

愛というものの心的・身体的な機制は複雑極まるものだから、若い男は人生の一時期、もっぱら自力を集中しなければならない。そのため愛の対象、つまり愛する女性を取り逃がしてしまう(これはちょうど、若いヴァイオリン奏者が演奏中に指使いのことを考えなくてもいいほど達者にならないかぎり、作品の内容に集中できないのと同じことだ)。

p.124

それから彼女は手を上げたのだが、その上げ方と言えば、これまで一度もそんな仕種をしたことがなく、どうやっていいのか分からないのに、ただ別れのしるしに手を振ることだけは知っていて、不器用ながらもそんな動作をしてみようと決心した人のようだった。

p.138

おのれの悲惨を自覚したところで、それで同類達の悲惨との和解が生じるわけではない。めいめいが他人のうちにみずからの卑俗さを見て仲よくするときほど、嫌なことはない。私はそんなべたついた友愛をどう扱っていいのかわからないのだ。

p.216

「王様!あんたには眼は要らないさ!おれが全部話してやる」

p.303

新聞はかさばらず、なんならゴミ箱に捨てることだってできる。同じようにつまらないものでも、ラジオにはそのような情状酌量の余地はない。カフェやレストランにまで私たちを追いかけてくるばかりか、耳に絶え間なく音の栄養をあたえないと、生きている気がしない人々の家を訪問しても変わりないのだ。

p.390

手に持ったカンテラを激しく振りかざしながら海岸をうろつく者がいれば、それは精神が錯乱した人間かもしれない。しかし夜、針路を失った小舟が大波に弄ばれるときなら、その者は救い主になる。

p.474

延期された復讐は奸計に、個人の宗教に、神話に変わり、日に日に当事者自身から離れていく。当事者たちは復讐の神話のなかで不変でも、じっさいには(動く歩道はたえず動いているから)、もはや以前の彼らではなくなっている。

新しいリリースプロセスをデプロイした

今やっているサービス、ちょっと障害が増えてきたので、リリースプロセスを変えました。 ざっくり言うと、今までmasterを全部デプロイしていたのを、金曜日以外の毎日一回、手動の確認をしてリリースするようにした。実際のドキュメント(Wikiです)を日本語にしてダイジェストで紹介してみようと思います。

ちなみにこのサービスは複数のアプリケーションがあって、今回対象にしたのはそのうちの主要な3つのみです。

ブランチ戦略

  • developを本流として、そこにトピックブランチからプルリクエストを出す。masterは常に本番環境に自動的にリリースされる*1
  • 急ぐときはHotfixとしてmasterに直接プルリクエストを出してもOK*2

リリース手順

  • HipChatで「リリースするよ」ってアナウンスする
  • developからmasterにプルリクエストを出す
    • HipChatでHubotに頼むと、Jenkinsが必要なリポジトリにプルリクエストを出してくれる
    • ついでにWiki、テストケース、チェックリストのURLなど必要な情報をHipChatに投稿してくれる
  • 手作業でテストして、チェックリストを埋める
    • 問題があったら課題管理システムに起票
    • 凄いやばそうな問題があったら相談する
  • プルリクエストをマージして本番環境にリリースする
  • HipChatで「終わった」ってアナウンスして終わり

リリースチームについて

  • 開発者&非開発者のペアを一週間でローテーション
  • リリース体制自体を担当する開発者&非開発者が一人づつ*3
  • リリースのない金曜日はプロセスのふりかえりをする
  • リリースは開発者ではなく、非開発者が主導

経緯と歴史

複数アプリケーションにまたがるEnd to endテストをやりきれないのと、テスト対象以外の障害やイケてないところを検知できるっていう手作業のメリットを享受したいな、といったあたりが理由です。 もちろん全部自動化したいんですが*4、このタイミングでは手動のリリースプロセスを導入するのがコスト的にもサービスの品質向上という面も良さそうでした。

ちなみにこのプロセスは以前別のプロジェクトでやっていたものをちょっと変えただけ。そのプロジェクトでうまく行った実績があったので、ある程度自信を持って進められた。

2014年12月の前半くらいに他の仕事をしつつプランニングと制度についてふんわりと考え始めました。先述のプロジェクトでやっていたことをざっと文書化してそれを元に相談しつつ、12月半ばくらいから周知を開始。フィードバックがあった部分や不足していた部分を詰め、自動化とChatOpsの仕組みなどを調査・整備、年明けにやわらかい状態でスタート。そこから一週間で一気に制度としくみを詰めた感じです。 まだ詰め切れてない部分はあるものの、走りながら治せる程度にまとまりました。

やってみて思いますが、サービスの事をよく知ることができる、改善点が見つかる、など、手動のテストにも特有のメリットがありますね。今更ではありますが。実は全体のEnd to endテストもあるので*5、今後はそれをこのプロセスに組み込んで機械と手作業それぞれの良さを活かせる仕組みにしたいなーと思ってます。

*1:言うまでもないですがCIをパスしたもののみ

*2:masterにしかないコミットが発生する。これはJenkinsで毎日masterからdevelopにプルリクエストを出すことで解消している

*3:というか僕です。このプロセスの整備などもこの二人で行った

*4:ちなみに各アプリケーションはそれなりのカバレッジがある

*5:今は不安定すぎてつらい

2014年

後20時間ちょいしかない。表面的に振り返ってみようと思います。

仕事

今年は、大規模なアライアンスプロジェクトの開発リーダーを中心に、人事、採用、開発、体制の整備などに加えてBiz Dev的な活動にも参加するようになった。気がつけば自分でコード書いてない、って日もだんだん出てきた。大人力がコア・コンピタンスになりつつあるのはプログラマーとしては悩ましい事態だけど、今の会社では必要なことをなんでもやるつもりでいるので、まあ良し。

オープンソース

ライブラリ

fujimura/hi · GitHub

Haskellのプロジェクトを生成するやつ。cabal initだと、ちょっと足りないので作った。今日時点で119star。海外のブログで言及されることも何度かあった。ちょっと飽きてきた。そろそろ1.0.0が出せそう。

hspec/hspec-wai · GitHub

WAI(HaskellのRack)のアプリケーションをHspecでテストできるようにした。元々サンプルアプリだったのをライブラリ化した。というかHspecの作者Simonさんがライブラリ化してくれた、が正しいかも。残念ながら僕は個人でも仕事でも使ってないけど、Zaloraでは使われてるらしい。

fujimura/git-gsub · GitHub

git-grepsedを組み合わせリポジトリ内の文字列置換するのをGem化した。今やこれなしでは生きられぬ。

fujimura/git-freq · GitHub

Gitでどのファイルが頻繁に変更されてるか出すCLI。使うより作るほうが楽しかった。

主なPull request

マージされたのはここらへん。Cabalにコントリビュートできたのは結構うれしい。全体に雑で手間をかけちゃってるので反省している。gulp-purescriptとか完全に自分でも忘れていた。

ここらへんは放置中。JSONとBSONの規格を調べたりして楽しかった。

今年の一曲

Leo Anibaldi - Elements - Italian House - ACV 1991 - YouTube

このミックスの1曲目。マニラの空港で飛行機を待っている時に初めて聞いた。ディープハウスと旅は合う。合いすぎる。このミックスはその後も何度も聞いた。

Bodytonic Podcast - Murat Tepeli by Bodytonicmusic - Hear the world’s sounds


来年は「いい一年だったね!」って言って年を越せるといいな。

Haskellでコマンドラインアプリケーションを作る時の基本的な情報とTips

Haskellコマンドラインアプリケーション(以下CLI)を作る時の基本的な情報とTipsをまとめてみました。 Haskellは雰囲気で読める、しかしCLIはあまり作ったことが無い、って人が想定読者です。

この記事はHaskell Advent Calendar 2014の16日目のエントリです。

とりあえず何のサンプルコードも無く話を進めるのも雰囲気が伝わらないかなと思って、Gitリポジトリにあるファイルの中身を標準出力に出力するプログラムをls-moreという名前で作ってみました。

module Main where

import           Control.Monad
import           Data.Monoid
import qualified Data.Version
import           Options.Applicative
import           Paths_ls_more       (version)
import           System.IO           (Handle, hGetLine, hIsEOF)
import           System.Process      (runInteractiveProcess)

data CommandLineOption = CommandLineOption { showVersion :: Bool -- バージョンを出力
                                           , show3Lines  :: Bool -- 3行だけ出力
                                           }

commandLineOption :: Parser CommandLineOption
commandLineOption = CommandLineOption
    <$> switch ( long "verion"       <> short 'v' <> help "Show version" )
    <*> switch ( long "show-3-lines" <> short '3' <> help "Show 3 lines only" )

main :: IO ()
main = do
    -- コマンドラインオプションパーサーを実行してオプションを取得
    opts <- execParser (info commandLineOption mempty)
    -- バージョンを出すか、実行するかで分岐
    if showVersion opts
      -- バージョンを出す
      then putStrLn $ Data.Version.showVersion version
      else do
        -- `runInteractiveProcess`で実行した外部プロセスの標準出力を受け取る
        (_,out,_,_) <- runInteractiveProcess "git" ["ls-files"] Nothing Nothing
        -- 本処理へ
        go opts out
  where
    go :: CommandLineOption -> Handle -> IO ()
    go opts handle = do
      -- ファイル末尾か判定
      eof <- hIsEOF handle
      if eof then return ()
             else do
               -- 一行読む
               path <- hGetLine handle
               --- ファイルの中身を読む
               content <- readFile path
               -- ファイルパスを出力
               putStrLn path

               if show3Lines opts
                 then
                   -- 3行だけ出力
                   forM_ (take 3 (lines content)) putStrLn
                 else
                   -- すべて出力
                   putStrLn content
               -- 次へ
               go opts handle

いかがでしょうか。冒頭にこのサンプルコードを置く意味がどの程度あったのかという問いを放置しつつ、箇条書きでCLIを作る際に必要な情報をまとめていこうと思います。

ファイルの読み書き

PreludereadFilewriteFileなど基本的な関数があります。ByteStringText向けにも同じインターフェイスの関数が用意されています。

ディレクトリ操作

System.Directoryを使います。

ファイルパス

System.FilePath を使います。

ドキュメントはSystem.FilePath.PosixSystem.FilePath.Windowsに分かれていますがインターフェイスは同じです。

外部プロセスの呼び出し

System.Process を使います。readProcessreadProcessWithExitCodeを使うことが多いような気がします。

結構前の話ですがsystemが1.2.0.0で非推奨になってしまいました。よく使う関数だったので衝撃です。今後はcallCommandを使えば良いみたいです。

文字列操作

真面目にHaskellのプログラムを書いていると、ユニコードの文字を出力する必要がある、遅い、などの事情で素のStringではなくByteStringTextを使うことになると思います。「ファイルの読み書き」にも書きましたが、この2つのライブラリははPreludeと同じインターフェイスの関数を多く装備していて、それを使うとByteString/Textの文字列もリスト操作感覚でいじることができます。

終わり方

exitSucess / exitFailureSystem.Exit にあります。

標準入出力

getChargetLinegetContentsなど基本的なものはPreludeにあります。さっきのサンプルプログラムにあるようにHandleを指定するなどの場合はSystem.IOにあるhで始まるものを使います。 これもByteString/Textに同様の関数があります。

今回は省略を省きますが、conduitpipesio-streams等のストリーム処理ライブラリを使うのも良いと思います。

コマンドラインオプションは?

沢山ライブラリがあります。optparse-applicativeがおすすめです。APIの変更が若干激しい、ドキュメントが読みづらい等欠点はありますが使いやすいライブラリです。

同梱したファイルを使いたい

.cabalファイルのdata-filesプロパティで同梱するファイルを指定できます。 このようなパッケージ固有の情報はPaths_pkgname というモジュールから読めます。同梱ファイルのパスはgetDataFileNameで取得できます。

バージョンを出したい

サンプルコードにある通り、

import Paths_pkgname
import Data.Verison (showVersion)

して、 showVersion Paths_pkgname.versionで取得できます。

設計

個人的には下記のような構造に落ち着きました。各工程をテストできるのが良いです。 実際はもうちょっとグチャグチャになります。

-- コマンドラインオプションを生成
parseArgs :: [String] -> CommandLineOption

-- コマンドラインオプションからオプションを生成。
-- 環境変数などはここで読んで、オプションを完成させる
buildOption :: CommandLineOption -> IO Option

-- オプションから処理を実行。
run :: Option -> IO ()

-- 各部品をつなげる。
main = (parseArgs <$> getArgs) >>= buildOption >>= run

おわりに

HaskellCLI作るの楽しいです。相性良い気がします。是非お試しを!

追記

バージョン情報が無かった。各ライブラリは2014/12/16時点で最新のものを使っています。

$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.8.3
$ cabal --version
cabal-install version 1.20.0.3
using version 1.20.0.2 of the Cabal library 

Tools for trade Late 2014

OS and Application

CLI

  • Homebrew
  • rbenv
  • Zsh
  • tmux
  • Dotfiles are managed in this repo

Zsh

f:id:fujimuradaisuke:20141128180208p:plain

  • Colorful prompt
  • Path and Git branch on the right
  • Cabal sandbox status
  • Lots of one character aliases

Vim

f:id:fujimuradaisuke:20141128180100p:plain

  • vimrc is about 250 kloc
  • ctrlp, syntastic, gitgutter, vim-align
  • Just omni complete
  • Wrap parens
  • Emacs keybind in insert mode
  • Warnings for whitespace etc.
  • Search with /

Git

Custom defined Git commands

  • $ git tb to create topic branch named by last commit
  • $ git gsub for substitution. I can't write code without this now

Repository management

peco + ghq = r.

  • $ r (repo url) to clone a repository
  • $ r (repo name) to move to the cloned repository
  • $ r \TAB to auto complete repositories
  • $ r \ENTER to intaractive selection of repository

機内持ち込みオンリーで海外旅行する人の荷物Tips

出張で一週間フィリピンに行きました。ここ数年、毎年一週間ほど海外に行ってるんですが、常に機内持ち込みのバックパックのみです。そこら辺のノウハウが溜まってきたので共有します。

そもそもなぜ機内持ち込みのみで頑張ってるのか?

  • どのサイズのスーツケースを買うか悩みすぎている
  • スーツケース無しでなんとかなってるし、今回も買わないでいいか、という結論に達してしまう
  • 荷物待ち無しは気分が良い
  • 荷物が少ないのも気分が良い

荷物

バッグ

これです。35L。

f:id:fujimuradaisuke:20140819164555j:plain

特に不満は無い。PCも入るし。普段から使ってる。35Lが機内持ち込みの限界サイズだと思う。縦に長いと持ち込めないので気をつけて。

衣類

仕分けケースに入れる。それを圧縮袋で圧縮する。ZiplocでもOK。汚れた衣類はZiplocに入れて、圧縮する。そのために空のZiplocを数枚持っていく。仕分けケースは無印にいい感じの色のがある。Ziplocフリーザーパックのほうが強い気がする。

下着は速乾のもの。ホテルのバスルームで一日で乾きます。 綿100%の洋服は着ない。なぜなら、乾かないから。デニムとか履きたくなるけど諦める。Tシャツも綿ポリのを選ぶ。シャツは必要がなければ持っていかない。

靴はお気に入りを履いて行くとテンション上がって良いです。サンダルはゴミ袋に入れて持参する。ゴミ袋は多めに持ってると何かと便利。

フィジカルな本が必要な場合はフライト中の時間を潰せそうな量だけ持っていく。もし暇になったら…とか考えちゃダメ。そんな事は起こらない。旅先で気合いを入れて読書する予定があるなら別だけど(今回はあったのでこれを持っていった)。軽めの純文学がページあたりの消費時間量も多いのでオススメ。Kindleに読みたい本があるならそれがベスト。

今回はこれでした。面白かった。Los Pepesの話とか出てこなかったな…。

ホテル・フライトの予約はプリントアウトしておく。直前に家にプリンター無くて困るってパターンが多いので、早めにやっておくべし。パスポートのコピーもしておく。

パスポート

空港ではチケットと旅程のプリントアウトを挟んでポケットに直接入れる。それ以外はコピーを持ち歩く。

お金

ちょっとだけ両替しておいて、あとは現地のATMでキャッシングする。

個人用の名刺

常に持ち歩く。あらゆるところで。予期せぬ出会いがあるので。

サングラス

日本より日差しが強い国はけっこう多いのでマスト。

財布とかを入れる小さいバッグ

これは今回の反省。水着にポケットがなくて財布・携帯・鍵が入れられませんでした…。 こういうので良いんじゃないかなと。

化粧水

空港の無印良品で小さい化粧水を買って持って行ってます。全身に使う。ホテルの石鹸が強い時に役に立つ。日焼けした時も使える。

もう一つの財布

国内用と別のを持っていくと詰め替えが楽。激安のを買う。

耳栓

安眠の友。フライトもだし、ホテルがうるさい場合もあるので。カナル型イヤフォンがあっても、音楽を聞きたくない時もあるので、別途持っていたほうがよい。空港で買えます。

アイマス

フライトが長い場合はあると良い。耳栓とアイマスクして入力を減らすとかなりリラックスできます。空港で買える。

RSpec実行にまつわる小ネタとDSLについてのボヤキ

変更されたファイルのみ実行

$ bundle exec rspec `git diff --name-only`

インタラクティブに対象を選んで実行

peco便利。

$ bundle exec rspec `git ls-files | peco`

そういえば、最近GuardやListenで自動実行しなくなってしまった。理由は特にない。

RSpecの変化が速すぎてついていけない。常にRubyを書いているわけではないので(JavaScriptが多くて常にRubyを書いているわけではないので、rspec-mocksも含めると気がつけばAPIが変わっていて、毎回ググっている。APIが安定しないライブラリは辛い。

そもそも、凝ったDSLを覚える事自体が辛い。特定のDSLの理解は再利用性が低いのが良くない。覚えても、そのライブラリ・フレームワークを使えるようになるだけという応用の効かなさが悲しい。逆に言語仕様への理解は再利用性が高い。当たり前だけど。書かれたコードをより深く理解できるし、自分で書くにあたっても、その表現力を活かせる。

ということで、凝ったDSLの学習は最小限にしたいなー、と思っております。