最近読んだ本 2014/06
柚木麻子『終点のあの子』
青春時代にあるちょっとしたボタンの掛け違えで人生のものすごく大切な何かを失う出来事が描かれる。 で、今自分には30台独身男子の目の前にある限りの人生しか見えなくなっているのに気がつく。あのころ視界に広がる空間は、見えているものが何なのか、よくわかってはいないけど、とにかくあっけらかんと広かったような。 回収が、ベタだけど美しい。
マイケル・オンダーチェ『名もなき人たちのテーブル』
数週間の船旅の中でいくつもの人生が交わる様子が描かれる。思春期を迎える子供ってこういう風に全てが鮮やかに見えるんだよな。静かな文体のわりに一気に読ませるので策士。
エンリコ・モレッティ『年収は「住むところ」で決まる 雇用とイノベーションの都市経済学』
クリエイティブ資本論の焼き直し。
岩本繁『経営分析の知識』
財務諸表をもとに経営を分析するためのツールと実例が展開される。地味だけどタイトで好感の持てる本。サラッとでも財務諸表が読めると、転職時に会社を調べるのにすごい便利。あと、経営に近い所で仕事をしていた人は実感をもって面白く読めると思う。ただ一切会計の知識がない状態だと辛いかも。
ファイル毎の総追加行数・総削除行数を出すGitのサブコマンド、git-freqをリリースしました
プロジェクトが一段落して「どの機能が一番大変だったのかな?バグが多かったのは?」という情報を知りたくなりました。ということで、ファイル毎の総追加行数・総削除行数を出すGitのサブコマンドを作りました。
https://github.com/fujimura/git-freq
http://hackage.haskell.org/package/git-freq
$ cabal install git-freq
でインストールできます。Haskellの環境が必要なので、お持ちでなかったらHaskell Platformをインストールしてください。
結果はcsvでファイル名、追加行数、削除行数の順に出力されます。 Lensの2587bb01だとこんな感じです。
$ git freq | head src/Control/Lens.hs,5365,5263 src/Control/Lens/Fold.hs,5885,3471 src/Control/Lens/Internal.hs,4205,4123 src/Control/Lens/Type.hs,3493,2869 src/Control/Lens/TH.hs,3530,2066 src/Control/Lens/Setter.hs,3097,1846 src/Control/Lens/Internal/Zipper.hs,2432,2436 src/Control/Lens/Traversal.hs,2846,1628 src/Control/Exception/Lens.hs,2646,1697 src/Control/Lens/Plated.hs,2395,1715
本来は機能ごとに変更を計測したくて、GitHubのタグをAPI経由で取得して…と夢は広がったんですが道のりが遠そうなので、とりあえずファイル別に見れればよいかなと思い。
実装はgit log --numstat
を合計してるだけです。
IOを型クラスで抽象化してテスタブルにする、ってのが出来たのが嬉しいです。
たぶんドキュメントとかサードパーティーのライブラリとか、測りたくないファイルが結果に出ちゃうと思うんですが、そういう場合はこんな感じで絞ればOK。Ruby on Railsのa6c8cde、ActiveRecord部分の様子です。
$ git ls-files activerecord |grep -v html |xargs git freq activerecord/CHANGELOG.md,12854,12126 activerecord/lib/active_record/base.rb,10026,9703 activerecord/lib/active_record/associations.rb,9331,7615 activerecord/test/cases/migration_test.rb,5384,4486 activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb,4829,4085
CHANGELOGが一番更新が多い。しっかりしてますね。
問題点としてはファイルを移動すると変更量がリセットされてしまう点です。仕方ないか。あと歴史の長いリポジトリだとgit log --numstat
自体が結構時間かかるので、遅いです。
次は日付毎に変更量を取れるようにしたいなって思ってます。
ファイルごとでも合計が取れると結構面白いですよ。あ〜ここが辛かったんだな、とか。プロジェクトが一段落したらgit freq
して、振り返ってみてはどうでしょうか。
2014年、春のGit事情
なんとなく最近どんな感じでGitを使っているか、適当にリストアップしてみた。
よく使うやつ
git status
git status --branch --short
にしている。変更されたファイルが出る。とりあえず何をしたかざっくり把握する用。s
にエイリアスしている。一日100回くらい実行しているのではないか。git diff
特にオプションは指定していない。何をしたかしっかり把握する用。
d
にエイリアスしている。一日50回くらい実行しているのではないか。git grep
バージョン管理しているファイルから渡した単語を含む行を検索、表示。関数の検索などあらゆる場面で超便利。オプションは
--line-number --show-function --color --heading --break
がオススメ。git ls-files
バージョン管理しているファイルのファイルパスを表示。どんなファイルがあったか一覧するのに便利。 パイプを駆使すると使い道が増える。例えばこのアプリ、ヘルパーは何があったっけ?って時は
$ git ls-files | grep helper.rb
で一覧できる。git show
HEAD
のコミットログとDiffを表示。ついさっき何やったのかを見るのに便利。最近けっこう使う。git log --decorate
git l
にエイリアスしてる。コミットコメントだけ読む時用。git log --decorate --stat --patch
git lp
にエイリアスしてる。git log
よりもこれをよく使う。パッチ形式で変更を全て出す。pager=less
なので、lessで見ることになる。色々試した結果この出力に落ち着いた。
自作のサブコマンド
実行ファイルになってるコマンドは、PATHが通ってる所ににsymlinkして.gitconfig
にこんな感じで書いて使ってる。
-
HEADにステージされた変更をamendする。あ、これ忘れてた、って時(しょっちゅうありますね…)に便利。Originally by @idesaku.
-
git topic-branchの略のつもり。HEADのコミットログをhyphenizeしてブランチを作成、チェックアウトする。1コミットしてやっぱブランチ切りたい!って時に便利。"Add missing translation"だと
add-missing-translation
という名前のブランチができる。正しくコミットログを書いていてればブランチ名も正しくなるので良い。 -
git backupの略のつもり。
git tb
したあと元いたブランチに戻る。とりあえず現状でブランチ切っておきたい、という時に便利。
エイリアス
いくつかのコマンドは、こんな感じで1文字にエイリアスしてる。賛否両論なんだけど、一度試して欲しいです。特にs
とm
。
alias g='git' alias s='git s' alias m='git checkout master' alias d='git d'
所感
なぜかgit show
を使う機会が増えた気がする。
自画自賛になるけどgit gsub
とgit tb
がライフチェンジングすぎてやばい。git rename
も作った(内容はご想像の通り)が使い込んでないので載せなかった。
最近コミットコメントの3行目以降を努めて書くようにしてる。変更への想い・気持ち・感謝・コードからわからないコンテクストを込めている。実質的に変更箇所に書いた長文コメントと同じになる場合もあるんだけど、人はコードよりコミットコメントを先に読むので重複は気にせず書いてる。コードレビューへの予防線を張るのにも役立つ。
Add, Fix, Changeから始まるコミットコメントはコミットコメントスメルだと思って気をつけてる。「追加、直す、変える。そんなの変更管理してるんだから当たり前だろ!」と自分に言い聞かせて、もっとこの変更で何が起きるのか、具体的に表現する言葉を探すようにしてる。あんまりできてないけど。
jQuery.Deferredの使いどころ
便利便利と言われつつも使ってみないと良さがわからないのがDeferred Object。身近なところで言うと、$.ajax
が返す、done
とかfail
とかを呼べるアレもDeferred Objectです。使いこなすと色々な処理をコールバックを渡すよりもうちょっと綺麗に書けるようになります。
ということで最近プロジェクトで使ったパターンを中心に例をあげてみます。
コードはすべてCoffeeScriptの擬似コードです。
まず最初に便利な書き方を覚える
Deferred Objectは$.Deferred()
で作るわけですが、これには「作られたDeferred Object自体を引数にとる関数」を引数として渡せます。これを利用すると
d = $.Deferred() doSomethingWithCallback -> d.resolve() d
を
$.Deferred (d) -> doSomethingWithCallback d.resolve
と書けます。一行で、コールバックを取る関数をDeferred Objectを返す関数にすることができるわけです。これは僕が働いているQuipperでもイディオムになってて、コード量削減に寄与しています。引数についての詳細はこちら を。
複数イベントにまたがる一連の処理を逐次実行っぽく書く
こんな具合にイベント間に依存関係が生まれる事ってありますよね。 フラグで実行順序を制御しているのが切ないです。
list.on 'selected', -> uploadSelection().done -> uploaded = true input.on 'entered', -> if uploaded uploadEnteredContent().done -> entered = true confirmation.on 'confirmed' -> if uploaded and entered uploadConfirmed().done -> confirmed = true goToNextPage.on 'click', -> if uploaded and entered and confirmed route "/next_page"
実際のアプリケーションを書くと、イベントハンドラ内はもっとゴチャゴチャするはずです。
これはjQuery.Deferred
を使えば、
こう書けます。then
により逐次実行っぽい書き方ができるので、フラグによる実行順序の制御は不要です。
select = $.Deferred (d) -> list.on 'selected', -> uploadSelection().then d.resolve enter = $.Deferred (d) -> input.on 'entered', -> uploadEnteredContent().then d.resolve confirm = $.Deferred (d) -> confirmation.on 'confirmed', -> uploadConfirmed().then d.resolve $.Deferred().resolve() .then(select) .then(enter) .then(confirm) .then -> routeTo "next page"
沢山の非同期処理をまとめる
例えば、画像の先読み
preload = (sources) -> promises = _.map sources, (src) -> d = $.Deferred() img = new Image img.src = src img.onload = d.resolve img.onerror = d.reject d.promise() $.when(promises...) preload [ "assets/foo.png" "assets/bar.png" "assets/baz.png" ]
(Thanks @mizchi)
例えば複数のAjax Request
a = $.get("https://somewhere.com/api/a") b = $.get("https://somewhere.com/api/b") c = $.get("https://somewhere.com/api/c") $.when(a,b,c).then (aResponse, bResponse, cResponse) -> new AView model: aResponse.responseJSON new BView model: bResponse.responseJSON new CView model: cResponse.responseJSON
ところでPromise/A+って何?ES6 Promisesとか何なの?jQuery.Deferredで大丈夫なの?
まず、Promiseというのはいわゆるデザインパターンのひとつ。Wikipediaによると、用語自体はSchemeに由来しているようです。Promise/AというのはJavaScriptにおけるPromiseの標準仕様のProposal。それの強化版としてPromise/A+がある。jQuery.DeferredはPromise/Aにざっくり準拠。ES6 PromisesはPromise/A+にだいたい準拠。つまり、どれもだいたい同じAPIと挙動を持っています。僕はプロジェクトでjQuery.DeferredからQへの乗り換えを試みてみましたが、あまり変わらなかったのでjQuery.Deferredに戻りました。
ということで、とりあえずjQuery.Deferredでも大丈夫だと思います。ただ例外の扱い、done
の挙動などが違うので気をつけて。
余談ですがPromiseをモナドにするって提案をJavaScriptの人が「現実を完全に無視した型付き言語のおとぎの国の話しだろ」って無碍に却下するという事件がありました。 個人的にはPromise/Aの 1) 成功/失敗、 2) 非同期処理の制御フロー という2つの要素をごっちゃにしてるのが汚いなあと思ってて、Brian McKennaさんの提案する仕様のほうがクリーンかつ一貫性があって、いいと思うんですけどね。