Hatena::ブログ(Diary)

naoyaのはてなダイアリー

May 12, 2014

Sqwiggle が良いという話、またはリモートでアジャイル開発をどう進めるか

KAIZEN platform Inc. は、新しい働き方をいろいろ試してみようという会社でそのひとつにリモートワークがある。リモートワークの良さあるいは良くないところについては、以前に Rebuild.fm の ep.32 でも話した。

ちかごろは、オンラインミーティングのための道具、情報共有のための道具もクラウドサービスがたくさんあるので、その辺を使って工夫すれば一昔前に比べてだいぶリモートワークも現実的になってきている。実際、KAIZEN には大阪からリモートワークしている人とか、最近リモートワークを前提に都内から鎌倉に引っ越したメンバーなんかもいる。

リモートワークとアジャイル開発

HipChat、Google Hangout や Qiita Team なんかを使うことで、日常の会話、ミーティングや情報共有についてはもともと特に困ったこともあまりなかった。特に Qiita Team での情報共有はチームビルディングにおいて重要な一幕だった・・・という話も Rebuild でしたっけかな。

ただ、アジャイル開発という文脈でいったときに「どうするべ?」ということが幾つかあった。

その際たるものが「全員同席」。まあ全員同席はアジャイルで必ずやらなければいけないこと (・・・そもそも必ずやらなきゃいけないことなんてないとは思うんだけど)、ではないのだけど、リモートワークだとどうしてもその辺りのコミュニケーションが希薄になりがちで、チームビルディングという観点では課題だなと思っていた。

例えば、ちょっとした仕様の確認とか、あるいは雑談のために Google Hangout を使ってオンラインミーティングしようとすると HipChat で以下の様なやりとりが行われたりする。

naoya 「@ngs ちょっと確認したいことあるんだけど Hangout いい?」
ngs「なんでしょう」
naoya「あのモジュールのあそこの実装なんだけど」
ngs「あー、あそこは @funami がよく知ってます」
naoya「なるほど、じゃあ @funami も Hangout」
naoya「@funami さんーん」
naoya「・・・いないね」
ngs「いないですね」
funami 「あ、ごめん、チャットみてなかった」
naoya 「おうおう、じゃ Hangout はじめましょ」
ngs 「url どこですかー」
naoya 「ちょっと待ってね・・・はいこれ」
funami 「なんか You're not allowed っていわれる」
naoya 「あれれ」

これで 10分 かかる。経験がある人はわかると思うが、これ、実際はなかなかにイライラする。誰が悪いわけでもないのでそのイライラをぶつける先もない。

これがリモートワークでなければ、その場でいるかどうか確認してその場でちゃちゃっと話合って終われるんだけど、リモートだとなかなかそうもいかない。そしてこの 10 分がめんどくさいので、チャット上でやりとりして実際には10分話せば終わることを30分も1時間もかけてやりとりしたりする、なんてことになりがちである。(結果的にテキストで記録が残る、というところはよいのだけど)

Sqwiggle

そんな折り、たまたま 8 Helpful Online Tools To Keep Your Company On Track という記事を読んだ。これは Buffer を作ってる人たちがどうやってリモートワークしてるかという話。Buffer はなかなか面白い働き方をしているらしい。

この中で紹介されていた Sqwiggle というツールが、まさに先の問題解決をしてくれた。あるいは、今後してくれそう。

Sqwiggle を起動すると、カメラが有効になってこんな感じで Sqwiggle を立ち上げてるチームメンバーが一覧になる。

f:id:naoya:20140512114229p:image

Sqwiggle は常にストリームをしてるわけじゃなくて、定期的に画像のスナップショットをサーバーに送ってる。そのスナップショットがときどき更新されて、この一覧がでる。

この一覧にいるメンバーと口頭で何か話したいことがあると思ったらどうするか。相手の写真をタップするだけ。すると、その瞬間からセッションが始まる。セッションをはじめるよという呼びかけみたいなのは一切なくって、タップしたら音がなって、いきなり相手と会話が始められる状態になる。

常時カメラで相手の状況が映し出されてるので、相手がいる/いないの確認がいらないし、Hangout を始める時の招待とか url のやりとりとかそういうのも一切必要ない。会話の途中で、その会話にもう一人追加したいとおもったらその人もタップすれば3人での会話になる。

使用感としては Hangout でのミーティングは会議室に移動してよいしょで会議を始める感じで、Sqwiggle は隣にいる同僚にちょっとちょっと、と話しかけるような感じに近い。

最初 Sqwiggle を使い始めたときは、常時カメラで写されてるということでプライバシーのこととか、割り込みしやすいというのでリモートワークの利点がとかいろいろ心配していたけどその辺は実際やってみると普段はほとんど気にならない。まあ、自分は Sqwiggle を ON にしてるのを忘れて画面の前で着替えをしたことがあるが、致命傷にはならなかったw そのうち放送事故が起こるかも知れないが、まあそれはそうなったらそのときだ。

どちらかといえば、リモートワークにありがちな、自己管理できなくてついついさぼってしまうみたいな問題をも Sqwiggle は解決してくれるところが非常によい。周りに誰かいる、というような感覚でリモートワークに望めるので適度な緊張感が得られる。怠惰な自分には、それがとてもありがたい。

Daily Standup やスプリント計画、KPT

こんな感じで全員同席で進めていってるときのチーム感は Sqwiggle によって結構解消されつつある。

KAIZEN のワークフローだとリリースデプロイの直前 QA なんかで頻繁にエンジニア同士でも確認事項が発生するのだけど、普段チャットでやってるところ、次回はその辺も Sqwiggle を駆使してコミュニケーションを厚めにやってみようかなんて話をしている。

ちなみにアジャイル開発、というかスクラムでいくと他のプラクティスをどう実践してるかというと、以下の感じである。

  • Daily Standup は、毎朝時間を決めて固定の Hangout URL に集まるようにしている。Sqwiggle は残念ながら大人数でのリモートチャットをサポートしてないのと、議事録用のスクリーンシェアができないため。時間になると Hangout にみんな集まってきてちゃちゃっとその日のやることを共有して、議事メモがすぐに Qiita Team に上がる。
  • スプリント計画は、実は厳密にはあまりやってない。やってるのはタイムボックスを決めて、2週間毎に前後のプロジェクト進行をスプリント単位で確認するくらい。自分の経験上、受託開発とかもうちょっとカチっとした開発では QCD における Delivery ・・・ つまりはスケジュールの優先度が非常に高いので見積もり精度を上げるためにもスプリント計画を厚めにやるんだけど、365日開発し続ける SaaS 系サービスだとこの辺はゆるくやってるくらいが丁度いいと思ってる。がっつりやりすぎて疲れてしまうことより、ゆるくても長く続けて常にタイムボックスを意識して進められるくらいが良いかなと思う。
  • 一方、KPT は日時を決めてしっかりやっている。スクラムマスターがその日までにオンライン上で KPT を集めておいて、その時間帯に Hangout で集まってミーティングをする。アジャイル開発においては、定期的に開発プロジェクトを見直し自分たちのやり方が間違っていないか、おかしなところがあったらそこをどう直していくかということが何よりも大切で、KPT はそのための良い機会になっている。

人の問題と、技術の問題

顧問として携わりはじめた昨年夏ぐらいから時間が経って、改めてみてみるといろんなプロセスが改善されて (KAIZEN だけに。) 安定した開発ができるようになってきたと思う。

当初は、まずはいろいろ教科書通りにやってみようということでスプリント計画そのほかをみっちりやったりもしてたが、やっぱりこれは違うねと感じたところは KPT で Problem にあげて、やらないことはやらない、緩く崩すところは崩すということをしながら今のスタイルに落ち着いている。

ところで昨晩から「ピープルウェア」という本を読んでいる。ソフトウェア開発の名著なんだけど、今ままで読んだことがなくて、たまたま知り合いのブログで感想があがってたのをきっかけに読み始めた。これの第一章から早速なかなか面白いことが書いてある。

実際のところ、ソフトウェア開発上の問題の多くは、技術的というよりは社会学的なものである

さもありなん。

技術の問題というのは、案外正解を導きやすい。コンピュータは、こうしたらこうなるというのにちゃんと答えを出してくれるし、どちらのやり方が良いかというのに結論を出しやすい。

一方、人間の問題は、そのやり方が本当に正しいのかどうかが見極めにくい。ものによっては半年とか一年後くらいになってようやく結果がわかることなんていうのも多い。時間が経過しすぎてどのアクションがその結果に繋がったのかという因果関係がはっきりしないことも多い。

だから、ソフトウェア開発の人間はついつい (解決の道筋が見えやすい) 技術的な問題にばかりフォーカスしてしがち、というようなことがピープルウェアには書いてあって、そうだよねえと思いながら読んでいる。

Daily Standup をリモートでどうやるかとか、リモートでも気軽に雑談できるような環境を整えることにリソースを割き続けるとか、そういうことは社会学的な問題だと思っている。一方、先日書いたような GitHub を使ったデプロイフローなんかは社会学的側面もありつつ基本は技術的な問題である。

人の問題が解決されてチームが良い状態になると、今度は技術の問題がボトルネックになる。せっかく迅速に開発してるのにリリース作業や QA に時間がかかりすぎる、とか。実際 KAIZEN では一時期リリースの品質に問題があったのでコミュニケーションを取って QA をしっかりやるようになったのだが、そうしたところ今度は人手での作業が多すぎてつらい感じになったので、E2E テストを書いて全部自動化することによってそのボトルネックを解消した、なんて典型例があった。

逆に技術的な問題ばかりを解決しても、コミュニケーションがボトルネックになって、だれそれの了解が得られないからリリースできないとかそういうことが起こる。

人と技術の問題を両面からバランスよく解きほぐしていくのが、昨今のソフトウェア開発におけるチームビルディングのコツなんではないか、と思っている。

追記

ちなみにリモートワークと書くと時折誤解を招くので、捕捉しておく。

リモートとはいっても、100% リモートワークしましょうということではなくて写真にも映ってる通りオフィスはある。オフィスに行くか行かないかは自分で決めるようになっている。対面でしたほうがよいミーティングがある日はオフィスにいくしそうでないなら自宅、あるいはカフェかどこかでやる。いい大人なんで、その辺は自分たちで判断しましょうね、お互い信頼してれば大丈夫だよね、ってな感じの仕組みになっている。

もちろん対面でやった方が早いと思うことはたくさんあるけど、本当にそれは対面じゃないとできないのかというところをまずは疑ってみないことには、新しい働き方を追求するということはできない。結果的にそれで会議を減らす、非同期に作業することができれば全体の効率が上がるわけで、そこで思考停止しない・・・ということが大切だと思う。

May 02, 2014

GitHub 時代のデプロイ戦略

少し前までアプリケーションのデプロイと言えば capistrano などをコマンドラインから叩いてデプロイ、みたいなことをやっていたが、最近は少し様子が違うのでそのやり方、KAIZEN platform Inc. での事例を紹介する。

GitHub のイベントを契機に CI as a Service にデプロイを担当させる

GitHub で Pull Request を送って開発するのが前提になっているのは以前にも紹介した。

最近は Travis CI や CircleCI などに代表される CI (Continuous Integration) as a Service があって、CI も自分たちで環境を構築しなくてもクラウドに任せることができる。KAIZEN では CircleCI を積極的に使っている。

f:id:naoya:20140502194857p:image

これらの CI as a Service は基本的に GitHub と連携することが前提になってて、Github に差分を push するとそれを契機にインテグレーションテストを実行してくれたりする。

で、CI という文脈でいくとこの自動テストの実行が主なユースケースとして想像されやすいのだけど、CI as a Service にはそのテストの実行が終わったあとのデリバリーの機能もある。

Travis CI: Deployment なんかを見るとよくわるのだけど、master に push したらそれをきっかけに Heroku にデプロイを行うとか、そういうことができる。

CircleCI のデプロイオプション

この CI as a Serivice のデプロイオプションは結構色々細かく設定できて、例えば「deployment/production という名前のブランチに変更が push されたらこれを実行する」なんて設定ができる。

設定はレポジトリに置いた circle.yml ファイルに記述する。例えば以下のような感じ。

deployment:
  production:
    branch: deployment/production
    commands:
      - ./script/assets_precompile.sh:
      - bundle exec cap production deploy:migrations:
          
  edge:
    branch: deployment/edge
    commands:
      - ./script/assets_precompile.sh:
      - bundle exec cap edge deploy:migrations:

これでリモートの deployment/production ブランチにコードを push するとそれを契機に production へデプロイが行われるし、deployment/edge なら edge へ、てな感じになる。

実際のデプロイは、(まだ Mutable Infrastructure なので) capistrano を実行している。

CircleCI にデプロイを実施させると、テストを実行してその結果が緑だったらデプロイさせるというようなこととか、デプロイのログが共有しやすくなるとか、キャンセルが簡単とかいろんなメリットを享受できる。

Pull Request でデプロイする

「ほうほう、なるほど。じゃあデプロイしたいときは master から deployment/production へ merge して、git push するのか」というところだけど、ここでもう一個工夫する。

デプロイしたくなったら、master から deployment/production へ Pull Request を作るんである。

f:id:naoya:20140502192450p:image

この Pull Request を merge すると、CircleCI がそれを検知して結果的に CircleCI 上でデプロイが走る。キャンセルしたいときは merge しないで close する。

なんで直接 push せずにわざわざ Pull Request にするかは、上の画面を見ればだいたいおわかりのとおり

  • デプロイの見える化
  • 何がデプロイされるかのコミットログの可視化

など本当にいろんな利点がある。

production デプロイの際には、この Pull Request のスレッドを使って QA の最終確認をしたりする。コミュニケーションが Pull Request 上に集約されることになるし、デプロイ直前の hotfix が行われたコミットなんかも全て見えるようになる。

今思うと、手元でエイヤで cap deploy の時は、このあたりのワークフローが全部暗黙知化していた。アプリケーションへの変更を Pull Request ベースにして色んなものが見えるようになるのと同じで、デプロイもまた Pull Request で改善できるところがたくさんある。

hubot へデプロイをお願いする

仕上げは、この Pull Request を作る方法である。つい先日までは Pull Request を GitHub 上でマニュアルで作っていたが、ここまできたら GitHub API を使って Pull Request 作成は自動化してしまえばい。

そして、日頃 HipChat を使ってるのだから、チャット上で hubot にデプロイをお願いしたら Pull Request を作ってくれる、とすれば「デプロイ始めまーす」みたいな宣言いらずで一石二鳥である。

というわけで作った。

f:id:naoya:20140502193558p:image

hubot にお願いするとデプロイ用 Pull Requet が作られて、CircleCI がデプロイしてくれる、そんなワークフローができあがった。万歳。

GitHub や * as a Service を前提にしたワークフローの時代

GitHub や CircleCI のようなサービスがあるという前提でワークフローを構築していくとこんな感じで工夫次第でいろいろ面白くできる。Web サービスと Web サービスを繋げて、さらにそこに自分たちの開発フローを組み込んで一つのフローとして完成すると、なかなかに爽快である。

この辺の開発は、もうこういったWebサービスのような、一見するとプログラム部品としては見えないようなものものも、開発のための一つのプログラマブルな部品であると認識できるかどうか、ライブラリやフレームワークと同じ類のものであるとフラットに見れるかどうかそういう感覚が要求されるように思う。

それは Web 2.0 で Web API だなんだと言われてきたころからあったことなのだけれども、その感覚が、フロントエンドだけではなくて、こうして開発プロセスのワークフローの組み上げににも適用できるようになったというのが、自分としては昨今この領域が面白く感じる理由のひとつでもある。

逆に言えば、こういう領域に開発リソースをうまく継続的に投資できるかどうかということが今後の開発組織のあり方として重要な要素だと思っていて、KAIZEN では会社が立ち上がった当初から CTO と話して "Developer Productivity" という、この手の仕事をミッションにしたチームを構成するようにしてきて、その形が固まってきたところ。それがこういう形で面白い成果に繋がっている、と思っている。

April 24, 2014

Cask

昨年 ELPA で elisp を管理 - naoyaのはてなダイアリー に書いたとおり、昨今は Emacs にもパッケージ管理システムが搭載されいて、どこからか elisp をコピペしてきてその後管理できなくなる・・・みたいなことはなくなった。

ただ、じゃあ ELPA で全て解決したかというとそんなことはなくて、ELPA はパッケージのインストール自体は簡単にしてくれるけれども、それだけだった。

elisp の管理も Bundler のように入れたいパッケージ一覧を書いて bundle install すれば全部まとめて入るみたいな、そういうのが欲しい・・・と常々思っていた。

と思っていたら、Cask というのを見つけた。これがずばりそのものだった。

(source gnu)
(source melpa)
(source marmalade)

(depends-on "ag")
(depends-on "anything")
(depends-on "auto-complete")
(depends-on "browse-kill-ring")
(depends-on "color-theme")
(depends-on "elscreen" :git "git@github.com:knu/elscreen.git")
(depends-on "flycheck")
(depends-on "git-gutter")
(depends-on "pbcopy")
(depends-on "popup")
(depends-on "popwin")
(depends-on "powerline")
(depends-on "quickrun")
(depends-on "recentf-ext")
(depends-on "zlc")

;; prog modes
(depends-on "coffee-mode")
(depends-on "go-mode")
(depends-on "js2-mode")
(depends-on "json-mode")
(depends-on "less-css-mode")
(depends-on "motion-mode")
(depends-on "puppet-mode")
(depends-on "rhtml-mode")
(depends-on "ruby-mode")
(depends-on "sass-mode")
(depends-on "slim-mode")

(depends-on "rubocop")
(depends-on "ruby-block")
(depends-on "ruby-electric")
(depends-on "ruby-end")

(depends-on "go-autocomplete")

こんな感じで Cask というファイルを用意しておいて

$ cask

これで、.cask ディレクトリ以下に所望のパッケージがインストールされる。

$ cask update

でまとめてパッケージをアップデートすることもできる。

途中

(depends-on "elscreen" :git "git@github.com:knu/elscreen.git")

とあるように、パッケージソースを GNU や melpa ではなく Github レポジトリにできる。これがかなり嬉しい。

Cask で入れた elisp にロードパスを通すには二つやり方があって

  • cask exec emacs で起動する
  • init.elcask-initialize を呼んでやる

の二つ。

元々 Cask は Bundler に同じく elisp の依存関係を特定のディレクトリ内に封じ込めてやって、ライブラリの開発などで無用のトラブルを避けるために開発されたもの。前者はそのユースケースのための方法。

一方、Cask は普段使いの Emacs の elisp 管理にも使えて、後者がその方法だと思われる。

Cask をワンライナー ($ curl -fsSkL https://raw.github.com/cask/cask/master/go | python) で入れた場合

$ cask init

すると ~/.cask ディレクトリが作成されてそこに cask.el が入ってるので、これを使って

;; cask
(require 'cask "~/.cask/cask.el")
(cask-initialize)

と、init.el の中で呼んでやる。すると普段使いの emacs は ~/.emacs.d/.cask ディレクトリ以下を読むようになる。このディレクトリ用の Cask ファイルは ~/.emacs.d/Cask になる。

あとはこの Cask ファイルと init.el を git で管理すれば十分、ということになる。実際には Cask で入れられないパッケージ化されてない elisp は相変わらずロードパスに置かれたままだけど、その辺はおいおい整理していこう。

上記手順は記憶を頼りに適当に書いてるので詳しくは http://cask.github.io/usage.html などを参照されたし。

Emacs を使い始めてはや15年、ようやくまともな elisp 管理ができるようになった。

March 18, 2014

HBFav の不具合が直りました

HBFav で新着ブックマークが正しく取得できない不具合が発生しています - naoyaのはてなダイアリー で報告しました HBFav の不具合ですが、はてなブックマーク本体が修正されたことにより HBFav 側もこれまでどおり動作するようになりました。

ご利用の皆様にはご迷惑をおかけしました。また、修正にあたったはてなスタッフの皆様に感謝申し上げます。

引き続き HBFav をよろしくお願いいたします。

March 15, 2014

JAWS DAYS 2014、Immutable Infrastructure について

何もかも投げ棄てて Dark Souls II をやりたい気持ち抑えながら JAWS DAYS 2014 で Immutable Infrastructure について話してきました。以下、資料です。(Embed できないのでリンクです)

https://speakerdeck.com/naoya/immutable-infrastructure-number-jawsdays

Immutable Infrastructure トラックのトップバッターだったので、そもそも Immutable Infrastructure とは何か、どのような背景でこのような概念が提唱されるに至ったのか、そして現在は。またこれから何が変わるのかみたいな、大枠の話にフォーカスして話しました。会場は Immutable Infrastructure トラックは立ち見が出てるくらい盛況で、やはりこの分野に注目が集まってるのだなと実感しました。

続けて 3/25 にも Immutable Infrasturcute Conference #1 があります。こちらの方は聴衆の顔ぶれがまた JAWS DAYS と少し異なりそうなので、開発プロセスと関連づける形で話してみようかなと思います。とはいえ、こちらもオーバービュー的な役割だし結構かぶるかもしれない。

ちなみに、講演中 Immutable Infrastructure / Infrastructure as Code と発音するのに10回以上噛みました。