クリスマスイブに聞く本格ブラックメタル

METALバンド Advent Calendar 2015の24日目の記事です。担当がクリスマスイブになったのは偶然です。

詳しい説明はしませんが、それぞれその時代と国を代表する正統派ブラックメタルバンドです。恐らく本気でブラックメタルを聞いていた人は誰も文句を言わない、ブラックメタルという音楽の本質を味わえるチョイスだと思います*1

しかし、ここまで人間のダークサイドにフォーカスした音楽が他にあるでしょうか!?改めて聴いて震えました。カーテンを閉じ、部屋の照明を全て消し、大音量で聞いてください!

1995, France

www.youtube.com

1989, Hungary

www.youtube.com

1993, United States

www.youtube.com

1994, Sweden

www.youtube.com

1994, Norway

www.youtube.com

1986, Sweden

www.youtube.com

1991, Swiss

www.youtube.com

2001, France

www.youtube.com

*1:入れたかったけど量的に割愛したバンドが沢山います。BurzumとかKatharsisとかSarcofagoとか。

Hspecベストプラクティス

Hspecベストプラクティス

Haskell Advent Calendar 2015 の14日目のエントリーです。

イントロ

HspecHaskellコミュニティにすっかり受け入れられたテスティングフレームワークと言ってよいかと思います。しかし!まだ確たるベストプラクティスは無いと言えるのではないでしょうか!

Hspecの元となったRSpecRubyコミュニティでデファクト・スタンダードとなっており、ベストプラクティスの蓄積があります。これを、Haskellの事情を鑑みつつ適用してみようという記事です。

ではないので、その辺りは別の記事を読んでください。

あと、オフィシャルのexampleがあるので、これに先に目を通しておくと話が早いかもしれません。

気になる点、賛同できないプラクティス、改善点などありましたら、是非コメントで教えてください。

では始めます!

一般的なディレクトリ構造に従う

  • 一つのソースファイルに一つのスペック
  • ファイル名はSpec.hsで終える
  • ソースコードのディレクトリ構造に対応させる

が慣用的です。 例えば src/Foo.hsのSpecはtest/FooSpec.hssrc/Data/Bar.hstest/Data/BarSpec.hsとなります。

hspec-discoverでテストスイートをまとめる

複数あるテストを一つのテストスイートにまとめるのは結構面倒です。 上記の命名規則(Spec.hsでファイル名が終わる)に従い、各ファイルでspec :: Specをエクスポートしておけば、hspec-discoverが規約に沿ったファイルから自動的にテストスイートを作ってくれます。

下記のようにファイルを作っておけば $ stack testできるはず。

test/Spec.hs:

{-# OPTIONS_GHC -F -pgmF hspec-discover #-}

foo.cabal:

test-suite foo-test
    main-is: Spec.hs

それぞれの関数について、振る舞いの説明をする

describeで説明する関数を宣言し、itでその振る舞いを説明します。

例:

describe "Foo.bar" $
  it "should return multiple of given number" $ do
    Foo.bar 4 `shouldBe` 8

contextを活用する

contextに文脈を書くと整理されたテストスイートになります。

describe "Foo.baz" $
  context "when [] was given" $ do
    it "should return Nothing" $ do
      Foo.baz [] `shouldBe` Nothing

  context "when [1] was given" $ do
    it "should return Just 1" $ do
      Foo.baz [1] `shouldBe` Just 1

一つのテストで一つの振る舞いを確認する

複数の振る舞いを確認すると失敗するテストを見つけるのが難しくなります。

テストが遅くなりすぎる場合は複数の振る舞いを検証するのもアリです。

Good:

describe "Logger.log" $
  it "should write log to log file" $ do
    -- 省略
  it "should write log to stdout" $ do
    -- 省略

Bad:

describe "Logger.log" $
  it "should write log to log file and stdout" $ do
    -- 省略

テストをあまり抽象化しない

BDDはソフトウェアの振る舞いを記述するための手法です。多少冗長でも、記述された振る舞いの読みやすさを優先したほうがよいです。

ちょっといい例が思いつかないので、瑣末な例で。

describe "Foo.baz" $ do
  forM_ ["cat", "dog", "snake"] $ \name -> do
    context "with '" ++ name ++ "'" $ do
      it "should return " ++  name ++ "-chan" $ do
        -- 省略

describe "Foo.baz" $ do
  context "with 'cat'" $ do
    it "should return cat-chan" $ do
      -- 省略
  context "with 'dog'" $ do
    it "should return dog-chan" $ do
      -- 省略
  context "with 'snake'" $ do
    it "should return snake-chan" $ do
      -- 省略

としておいた方がよいです。前者の例はコードから振る舞いを読み取れません。BDDのテストコードは抽象化の対象ではなくソフトウェアの振る舞いを記述するものである、ということを心に留めておきましょう。

今年の24 days of HackageでHspecが取り上げられており、コメント欄でYesodやPersistentのメンテナーであるGregさんもテストの抽象化には反対していました。

とはいえ現実世界では、読みやすい抽象化をすればいいのでは?とか、さすがにボイラープレートコードが多すぎる、とか、悩ましい状況は発生します。適度にルールを破る分には良いかと。

マッチャーを知る

shouldBeshouldReturnなどをマッチャーと言います。これはそんなに数多くないので、一度目を通すとよいです。 ドキュメントはこちら にあります*1

GHCIでテストする

module FooSpec (main, spec) where

main :: IO ()
main = hspec spec

spec :: Spec
spec = describe "Foo.bar" $ do
  -- 省略

というようにmainspecをexposeしておくと、

$ stack ghci
λ import qualified FooSpec  
λ FooSpec.main
Foo.bar
  should return something
Foo.baz
  should do something

という具合にGHCiの中でテストを実行できます。$ stack test より GHCiの中でreload! するほうが早いのでオススメ。

便利なライブラリがある

一時ディレクトリ、一時ファイルの利用はMockeryが便利です。またSilentlyを使うと標準入出力をキャプチャできます。

WAIにはhspec-wai、Snapにはhspec-snapがあります。ちなみに僕はhspec-waiの作者の一人です。

まとめというか所感

Hspecいいソフトウェアだと思います。型がリッチな言語とふわっと振る舞いからコードを育てるBDDの相性がめちゃくちゃ良い。doctestと併用して、(Type|Test|Behaviour) Driven Developmentは捗ります。

あと、他にもRSpecのベストプラクティスをパクれるところは沢山あると思うので、RubyわかるHaskeller諸氏は是非参考にしてみてください。ちなみにRSpecを長年メンテしてたDavid ChelimskyさんはClojureの人になってしまいました。悲しいですね!

リンク集

本家

この記事の元ネタ

RSpecについて:

Hspecについて

*1:ちなみに中置記法があるおかげでRSpecのようにshould/expect論争がないです。

Haskellでなぜストリーム処理ライブラリが必要なのか

関数型ストリーム処理勉強会で発表したので、ブログにも書いておきます。

元になった資料はこちら

Haskellでストリームデータを扱う方法としては、Handleを使う方法、Lazy IOがありました。しかし、それぞれに問題があり、再利用性が高く堅牢なコードを書くことは困難でした。

この状況を解決すべく、ConduitPipesio-streamsなどのストリーム処理ライブラリが現れたのですが、そもそもそれらが必要とされた経緯は具体的にはどのようなものだったのでしょうか?

元ネタ: http://okmij.org/ftp/Haskell/Iteratee/talk-FLOPS.pdf

ソースコード: https://github.com/fujimura/functional-stream-processing-meetup-sample

そもそもストリームとは

必要に応じて処理されるデータの連なりのこと。具体的には標準入力、ファイル、ソケットなど。

上記の定義はScheme実装提案書より。 この定義では入力側をストリームと読んでいますが、出力側(標準出力への書き込みなど)もストリームとして扱われてる場合が多い気がします。

ストリームは多くの場合、IOです。

具体例

200MBのテキストファイルに含まれる空白文字の数を調べる、という例で比較します。200MBのファイルを一気にメモリ上に読み込むのは効率的とは言えません。ストリーム処理の出番です。

Lazy IOの場合

run :: FilePath -> IO ()
run fname = do
  file <- Text.Lazy.readFile fname
  print (countWhiteSpace file)

countWhiteSpace :: Text -> Int
countWhiteSpace = fromIntegral . Text.Lazy.length . Text.Lazy.filter isSpace
  • 良いところ
    • 単純でわかりやすい
  • 悪いところ
    • 純粋な関数で例外が起こる
      • readFileで読んだファイルに不正なバイト列が含まれていた場合は例外が起こります。そして、Haskellは遅延評価なので、値は必要になった時に評価され、例外は評価時に発生します。つまり、評価されるまで例外は発生しないのです!この性質により、なんと純粋な関数で例外が起こることがあります。これのデバッグは非常に難しいです。
      • 具体的には上記のコードの場合、Text.Lazy.filterで不正なバイト列が評価される時に発生します。
    • いつ、どれだけファイルが開かれ、開放されるか予測しにくい
      • 上記と同じ理由でファイルが開放されるタイミングも単純には予測できません*1。また大量のファイルが同時に開かれてしまう場合もあります。

Handleの場合

run :: FilePath -> IO ()
run fname = do
  handle <- openFile fname ReadMode
  i <- countWhiteSpace handle
  print i

countWhiteSpace :: Handle -> IO Int
countWhiteSpace h = loop 0
  where
    loop i = do
      eof <- hIsEOF h
      if eof
        then return i
        else do
          c <- hGetChar h
          if isSpace c then loop (i+1) else loop i
  • 良い所
    • 素朴で理解しやすい
  • 悪いところ
    • ローレベル
      • 素朴さの裏返しですが、Olegさん言う所の「Haskellで書かれた、典型的なCのコード」*2で、実にローレベルです。関数プログラミングとは何だったのか!
      • ロジックを書いている部分より、Handleの世話をしている部分が多い
        • 実際、ロジックが複雑になると大変なことになります。コード量が増えると、それだけバグの入る可能性も増えます。

io-streamsの場合

run :: FilePath -> IO ()
run fname = do
  i <- Streams.withFileAsInput fname countWhiteSpace
  print i

countWhiteSpace :: InputStream ByteString -> IO Int
countWhiteSpace is = Streams.decodeUtf8 is >>=
                     Streams.map (Text.length . Text.filter isSpace) >>=
                     Streams.fold (+) 0
  • 良い所
    • ハイレベルでコンポーザブル
      • ストリーム自体の扱いはio-streamsが隠蔽しています。
      • ストリームを受け取る関数を、Unixのパイプのように >>=で処理を繋ぎます。繋がれたそれぞれ処理は抜き差しがしやすいので、部品化も簡単です。io-streamsで入力を処理する場合、 InputStream a -> IO (InputStream a) を繋いでいくことになります。
    • 安全な例外
      • それぞれの部品はIO (InputStream -> a)を返すので、bracketで例外を捕捉できます。
    • 少ないメモリ使用量
      • io-streamsが面倒見てくれます。
  • 悪いところ
    • \(^o^)/ない

まとめ

既存の解決方法には問題がある。

  • Lazy IO: 純粋な関数で例外が起こる、リソース管理が難しい

  • Handle: 関数プログラミングっぽくないローレベルなコードになる

ストリーム処理ライブラリで、それら問題を解決できる。

  • io-streams: サプライズの少ない例外*3、ハイレベルでコンポーザブル
    • ただ、リソース管理は自分でやらないといけない。

ということで、ストリーム処理ライブラリを活用すると、効率がよく、見通しがよく、サプライズが少ないプログラムが書けるようになります。

参考資料&リンク集

*1:seqやBangPatternsを使ってサンクを潰して回る羽目になります

*2:http://okmij.org/ftp/Haskell/Iteratee/talk-FLOPS.pdfの7ページ参照

*3:実はこれHandleでもwithFileを使えば実現できます。

これからエンジニアがやったらよさそうな仕事

技術顧問ブームですね。先日退職してから色々な会社を回ってて、これニーズあるんじゃね?って仕事を何個か思いついたので、列挙してみます。

チーム開発を軸にした技術顧問

やること: 開発プロセスの構築・実行・改善、ミーティングのファシリテートを行い、チーム開発を良い感じにする。

必要そうなスキル: チームを作った経験。ソフトウェア開発プロセスの知識と実務経験。それなりの技術力。

GitHubでコードレビューしてCI/CDを回して、っていうスタートアップでよくあるエンジニアリングの型はある程度できているけど、うまく運用できていないところは少なくないと予想している。わかってる人が手伝ったら軌道に乗るまでが早そう。事業や組織の性質・フェーズに合わせる必要もあるし結構難しい。チームで仕事をするというカルチャーを伝えるのも価値がありそう。人間力が問われますな…。

個別技術を軸にした技術顧問

やること: 技術選定、アーキテクチャやコードのレビュー。

必要そうなスキル: 当該技術への深い知識と経験。

どのテクノロジーも正しく効果的に使うのは簡単ではない。深い知識は価値が高いはず。

採用支援

やること: エンジニアをうまく採用できていない会社の採用活動を支援する。待遇をエンジニアに訴求するものに再構築し、エンジニアに訴求する求人活動を行う。採用基準の策定。面接、スクリーニング。エンジニア組織の構築・改善。

必要そうなスキル: エンジニアの採用経験。マネジメント経験。幅広い技術とそのシーンの把握。人脈。

困っているファウンダーは多いと思います。カンファレンスやコミュニティの運営をしていて、自社で採用していない人とか良いのでは*1。組織がいけてない場合はそこの改善、場合によってはゼロから構築とかも必要かもなあ。

ベンチャーキャピタリスト

やること: 技術面のデューデリジェンスと、開発体制の構築、技術支援、リクルーティングなどのハンズオン。

必要そうなスキル: VC実務能力に加えて、ハンズオンで説得力を持たせられるだけの技術力とマネジメント経験。エンジニア・コミュニティでの人脈。

金融の友達に、会社やめたのでいろんなスタートアップ回ってるって話をしたら、藤村さんVCやったら?って言われた。その発想は全く無かった。そもそものベンチャーキャピタリストとしての素養が必要なのは言うまでもない。技術面のハンズオンは価値あると思われる。エンジニア業界とVC業界はコミュニティが離れてるので、そこを繋げられるのは悪くないかも。アメリカだと普通にいるっぽい。そもそもYコンビネーターのポール・グレアムLISPハッカー

まとめ

ベンチャーキャピタリスト以外は副業でもできそう。こういうハイエンドな仕事を良い感じに流動化したらシニアエンジニア各位の将来も幸せなのではないか。流動化したハイエンドな労働力を良い感じに流通させるしくみが必要なのかも。

こういう仕事もニーズありそうだよ?とか、追加あったら是非教えてください!

*1:人材紹介業は免許がいるので、紹介で直接対価をもらうのは出来ないと思われる。

無職日記 (1)

Quipperを退職しました & 求職中です - fujimuradaisuke's blog から一週間弱経ちました。

ありがたい事に沢山のお声掛けを頂きました*1。大変申し訳ないのですが、全てのご連絡にお返事できていない状況です…すいません!気がつけば今月のランチ・夕食の予定がほぼ埋まってしまいました。

で、7/24-7/28まで福岡に行きます。Rails Girls Fukuokaでコーチ。その後7/30から20日ほどタイ中心にアジアのどこかに行く予定です。シンガポールは確定、あとはスリランカかな。

今は部屋でこれを聞いてます。60分間、ひたすらミニマルに変化し続ける音楽。スーフィーの音楽を思い出しました。ジャケがかっこいい。 www.youtube.com

wishlistからTシャツと本を送って頂きました!ありがとうございます。記念に着て自撮りを行いました。次の仕事の初出勤はこのTシャツで臨もうと思います。

f:id:fujimuradaisuke:20150713160305j:plain

*1:退職エントリ公開初日で60件くらい

Quipperを退職しました & 求職中です

一言でいうと: Quipperを退職しました。Quipperの皆さん、本当にどうもありがとうございました!現在求職中です。ご興味あれば me@fujimuradaisuke.com か https://facebook.com/dfujimura までご連絡ください。RubyJavaScript、チーム開発のリード、などができます。wishlistはこちら


2015年6月末日をもって、Quipperを退職しました。

立ち上げ当初のMercariを体を壊して*1辞めて*2入院して手術受けて退院、さて今後どうしようと悩んでいるところで、ひとまずフリーランスで働こうとQuipperで働き始めました。2013年6月でした。

当初からフリーランスはあくまでモラトリアム期間という位置づけで、いずれは正式に会社に入るつもりでした。働いてみるとQuipperは想像以上によいところで、9月には正社員になっていました。教育という事業領域、グローバルな体制という点もさることながら、何よりメンバーが素晴らしかったのが決め手です。

Quipper在籍中にやったことを、立場で切って大きく分けるとこの二つでしょうか。

  • ベネッセさんとの大規模実証実験で開発チームリーダー
    • プロジェクトの仕組み作りとか、協業体制作りとか、開発チームの運営とか。
  • 東京開発チームのリーダー
    • 採用とかメンバーの配置とか面談とか。あと、オフィスが3つある(London/Manila/Tokyo)ので、その分担の相談とか。どちらかというと裏方。

一番の実績としては、ベネッセさんとのプロジェクトが無事完遂し高い評価を得たことになるのかな。もちろん全く事故ってないとは言えませんし*3、今思い出しても心がムズムズする反省点もあります。そもそも僕個人の実績ではなく、チームの実績だし。とはいえ、開発チームのリーダーとして在籍していたプロジェクトが「成功です!」と関係者に評価されていることは、客観的に見て実績と考えてもよいだろう、と判断することにしています。

あとQuipper Schoolのリリース体制を整備したりしてました。もちろんコードも普通に書いていました。

ちなみに退職の理由はよくあるタイミング的な問題です*4Quipperは先日リクルートに買収されましたが、これは関係ないです。個人的にはリクルートと仕事するのはとても楽しみだったし、素晴らしいチームになれると思っていたので、残念です。

次の仕事は決まっていません。のんびり勉強しつつ*5、Quipper在籍中に蓄積した思考を解きほぐして、じっくり次の仕事を決めるつもりです。やることとしては、今までしてきた仕事を考えると、技術と組織の掛け算で事業に貢献するって感じになるかな思います*6。けど、よい目的と信頼できるメンバーがいれば、関わり方はなんでもいいかなーと*7

ということで、エンジニアもしくはそれに類する職種の人間をお探しの方、ご興味あれば me@fujimuradaisuke.com か https://facebook.com/dfujimura までお気軽にご連絡ください。下に略歴をまとめておきました。お昼も都合がつきますので、ランチのお誘いお待ちしています。

Quipperは素晴らしい会社です。崇高なゴール、興味深い事業領域、安定した高い技術力、先進国・新興国含めたグローバルな体制、なにより最高のメンバー。なかなか離れがたいです。が!僕は僕の道で高みを目指して頑張っていこうと思います。

辞めた人間が宣伝するのも妙ですが、Quipperは各ポジションで絶賛採用中なので、興味を持たれた方は是非連絡してみてください。

最後に、渡辺さん、中野さんをはじめQuipperの皆さん、社外のお世話になった皆さん、本当にどうもありがとうございました!今後のQuipperと皆さんの発展を心より願っております。何か今の立場で協力できることがあれば、遠慮なくご連絡ください*8

ということで、皆様今後ともどうぞよろしくお願いします。


略歴

早稲田大学第一文学部哲学専修を卒業。大手ERPパッケージソフトの導入エンジニア(2次請け)としてソフトウェア開発を始める。Rubyがやりたくなり、とあるITベンチャーに7人目の社員として入社、Ruby on Railsを使うようになる。一年後業績不振のためレイオフされ(およそ半年後会社もなくなった)、groovesに入社。Rubyをメイン言語とする開発チームを中心人物として立ち上げる。その後Aimingに入社、認証サーバー、分析基盤などのチームを経て、Unityで作られたゲームをHTML5へ移植するプロジェクトに開発チームリーダーとして参画、なんとかリリースにこぎつける。その後フリーランス、Mercariなどを経てQuipperに参加。東京開発チームのリーダーとしてベネッセとの共同プロジェクトを成功に導くなどする。

プログラマーとしてはRubyを最も得意とする。JavaScriptを用いたシングルページ・アプリケーションの開発実績も多数ある。チーム開発をリードする経験も複数ある。プライベートでは主にHaskellを書いており、オープンソース・プロダクトへの貢献がいくつかある。


PS: wishlistを作ってみたので、貼っておきます。僭越ながらよろしくおねがいします。どちらかというとご笑覧向けのおもしろリストになっております。 http://www.amazon.co.jp/gp/registry/wishlist/3Q71MJUSPEEX8/

*1:扁桃炎が扁桃周囲膿瘍になり慢性化しました。最終的に2週間周期くらいで再発しててまじ辛かった。排膿のため口に注射針を入れて喉から膿を抜くんですが、それが痛いし怖い。あと一回再発することに5回点滴に通わないといけなくて超めんどくさかった。挙句の果てにMRSAが出たりした。扁桃腺が怪しい方はどうぞ切除をご検討ください!当たり前ですが、治ります。再発もしません。切除手術を受ける基準としては年4回発症だそうです。ちなみに今は完治して健康です。

*2:とんでもないタイミングで抜けたので、本当に申し訳なく思ってます…。

*3:ソフトウェア開発プロジェクトは大体そうだと思いますが。

*4:知りたい方は個人的に聞いてください。

*5:戸次大介『数理論理学』 を読む予定。論理学の知識が中途半端なので脱半可通したい。これ以外にも不足している/ずっと興味がある領域の知識を補おうと思ってます。『離散数学―コンピュータサイエンスの基礎数学』『ふつうのLinuxプログラミング』をちゃんとやり、『プログラミング言語の基礎概念』は勉強会も開催されてるので読もうかなと。

*6:技術に振るかマネジメントに行くか?って話しについては、過去の経験から見るに、どこに行ってもマネジメント的な仕事をは避けようがない雰囲気なので、両立主義者として生きていくことにしました。そもそもマネジメントというか組織のことは興味もあるし、嫌いではないです。

*7:どんな事業がいいの?って問いについては、僕はヴィジョナリータイプではないので、熱量と千里眼のある(法)人と出会いたいです!業界的には、学生時代からインフラストラクチャーを支えたいという気持ちはあります。エネルギーとか交通とか。スタートアップ向けエンジニアという今の自分のスキルセットが直球で活かせる業界ではなさそうなんですが。投球スタイルを変えるのも面白そうではある。

*8:笹塚のEdTechスタートアップでRailsフリーランス案件あるよ?ってのは無しで…w

『12大事件でよむ現代金融入門』 と『コンテナ物語 』を読んだ

出張中&帰りの飛行機で読んだので軽く感想文を。

倉都 康行『12大事件でよむ現代金融入門 』

1970年以降の国際金融システム史。12の事件が時系列に解説される。金融を中心とした国際経済のしくみがわかる。著者はその現場にいた人。それでか、平易な文体の中にも生々しさがある。この手の本でありがちな「新自由主義が悪い」って論調にではなく、あくまで中立的に書かれているように思える。きっと著者が現場で金融というシステミック・リスクと戦っていたからだと思う。そういう語り口もあってか、好きになれる本だった*1。歴史の本としても教科書としても読める。良書でした。ちょっと消化不良なので再読すると思う。

マルク レビンソン『コンテナ物語 』

箱に荷物を詰めて送るようにしたら物流コストがめっちゃ下がった。けど導入は組合が反対したり標準化でもめたりして大変だった。箱の発明もだけど、それをがんばって導入したマルコム・マクリーンは偉い!って本。色々な人が褒めているだけあって、ものすごい面白い。

この本は幾つかのトピックから読める。

一つめは「起業家としてのマルコム・マクリーン」。ちょっと儲かるとすぐ借金したり資金調達したりして新しいことをやる。お金の突っ込み方がダイナミックで面白い。こうやって会社運営ってするんだあ…という。

二つ目「実録・機械に仕事を奪われた」。かつて沖仲士が手動で船から荷物を下ろして仕分けしてトラックに詰めていた。この仕事はコンテナを導入するとかなり無くなってしまう。なので沖仲士の組合はめっちゃ反対する。けど時代の変化には勝てない。という話。

最後「コンテナリゼーションがいかにして海運を効率化したか」。要はバッチサイズを一定にして作業を標準化するとスループットが上がる、という。トヨタ生産方式を思い出した。20世紀後半の生産性改善の定石なんだろうか。ソフトウェア開発プロジェクトにも活かせそう。


あと、ブルックリンのレコード屋で買ったこれが最高だった。ニューヨークのラテン・ソウル。ほんと良い。

Joe Bataan - I Wish You Love, Part 1 & 2 - YouTube

*1:その点、最近の水野和夫は辛い。『人々はなぜグローバル経済の本質を見誤るのか』は名作だったと思うんだけど、それ以降はこの本でデータから導いた結論に本人が乗っ取られちゃってる感じ