2010-09-05 [長年日記]
_ RubyKaigi 2010 のスライド一覧を作ろうとして挫折
RubyKaigi 2010 が先週あったわけですが、参加してなくてもいろいろ漁れるのが最近のイベントのありがたいところ。
というわけで怒濤の更新がされていた RubyKaigi Nikki からたどってみたところ、
うわぁ。全部動画だ。
いや、ありがたいんです。とてもありがたいんです。が、
3日間マルチトラックで行われたイベントの動画を消化する時間を作れるならイベントに参加してます
これは困った。チェックしたいがとてもチェックできない。あぁ。せめて資料なら目を通せるか?
おおぅ。資料へのリンクはない。
さもありなん。資料はスピーカーの手元にあるので実行委員の自由にはならない。うーん。適当に検索すればいいのかなぁ。→ 適当に slideshare で検索してみる。あぁあるある。じゃあこれを…。えーと。
- RubyKaigi Nikki の category movie を直近の Quarter で検索した結果を scrape してセッションの名前と動画プレイヤーへのリンクを獲得
- スライド共有サイトでセッションタイトルを検索して scrape
- 2 を共有サイトの数だけくり返す
- 得られたデータからスライドへのリンクを持つ HTML を生成
すればいいのか?
手作業で検索して scrape 用の元データを作成し、着実にテストして確認、3, 4 のフェーズに入ったところ、
何もスライドが拾えない。
えっ。
ここでかなり長いことハマる。
……。
分かりました。
スライドタイトルと RubyKaigi Nikki 上のセッションタイトルが一致していない。
しかもスライドタイトルを入れる方法が複数ある。
諦めました orz
たぶん名の通った人が呼びかけた方が早いし、いろんなブログで評判の発表から眺めていくしかないかなぁ。今ちょっと feed 消化もままならないので、これは全部あとで送りにするしかないなぁ。うっうっ。
2010-09-12 [長年日記]
_ EmacsのDesktopを初めてまともに使う
以前 Twitter の timeline で M-x desktop-clear という文字を見かけて、何も考えずにそれを実行して痛い目にあったことがあるんだけど、そのうち
なんと打って痛い目にあったのか忘れてしまった。
うーん。忘却力の向上めざましい。
ということでそれっぽいものをログから必死に検索して見つけたのが 9/1 で、何を実行したのかもう一度書くと
M-x desktop-clear
だった。これは Emacs の持っている全 buffer をクリアしてしまうものなんだけど、desktop っていう言葉はなかなか出てこないなぁ。
Desktop ってなに
なんていうか Eclipse なんかだと Workspace とかそういう言葉になるのかな。まぁいろんなファイルをどういう風に開いているかなど、「Emacs のまさに今の状態」を表すものが Desktop らしい。調べると CentOS 5 の Emacs 21 にもあるので、今使われている多くの Emacs で標準的に使えるものと考えてよいみたい。
できること
もちろん
M-x desk<TAB>
とか打つと補完されるので分かるんだけど、Emacs 21 でも使える
- desktop-clear
- 全bufferクリア
- desktop-read
- save した desktop を読み込む
- desktop-remove
- save しておいた desktop ファイルを削除
- desktop-save
- desktop を保存する
程度が分かればとりあえず十分かなと思う。
カスタマイズしないで全部手動でやることにした
Desktop はもちろん
M-x customize-group
して
desktop
でカスタマイズできる。
Emacs 終了時に自動的に desktop-save して起動時に自動的に desktop-read すると、いわゆるプロジェクト管理機能付きのエディタや IDE の Workspace 復元機能として使えるんだけど、個人的には
ViewSourceWith
を使って Firefox の textarea や Thunderbird のメールを書くときにも Emacs を使っているので、こういう機能が自動で走るととても邪魔くさいことが分かった。何も設定せずに本当に必要なときにだけ desktop-save & desktop-read を使う方針にしてみた。
2010-09-19 [長年日記]
_ OOの原則とテストのための原則破り
レガシーコード改善ガイド (Object Oriented SELECTION)(マイケル・C・フェザーズ) を読んでいます。で、まぁいろいろ Twitter の方には流しているわけですが、とりあえず
テスト用のクラスで本番コードと一部挙動を変えてしまう
という、これまでの自分にはなかった発想が書かれていたので試しに PHP で書いてみました。
Singleton を Singleton じゃなくしてテストする
テスティングフレームワークは今は亡き pearified.com の SimpleTest を使っているのでその辺は適宜書き換え、読み替えてください。
ここでは
Singleton なクラスをテストのときだけ様々なパターンでインスタンス生成したい
ケースを想定しています。実際、よくあると思います。そのために
- コンストラクタの可視性を変更し
- instance() メソッドの戻り値を変更
しています。
どちらかだけで「本当は Singleton なんだけどテストのときだけ普通のクラス」という状態を実現できます。
1 の場合はたまたまコンストラクタですが、同じ要領でテストのときだけメソッドを public にしてテストすることができます。まぁ今回のケースのように「中身がなくて可視性を変えるだけ」であれば簡単ですが、普段はあまりやらないかも。それよりも
どうしても直接テストしたいメソッドは public にする
という方法の方がラクチンだし確実ですね。
2 は本当はメソッドの挙動が変わってしまう(何回呼んでも同じ値が返ってくるわけではない)ので、リスコフの置換原則には反しているような気がします。でもこれも有効なテストのための手法の一つだなぁと思います。Singleton じゃない場合でも
依存オブジェクトの生成処理がメソッドの中にあればオーバーライドして Fake オブジェクトを作るのが容易になります。
そうすると簡単に依存性を排除できます。
cf.
PHP 5.2.0 以降ではオブジェクトの同一性をハッシュ値で確認できます。
何が大事なことなのか
今回やったことは、恐らく OO の大きなメリットの一つであるカプセル化に反しています。また恐らくリスコフの置換原則にも反しているんじゃないかと思います。しかし、おかげでテストが書きやすくなり、コードの挙動をコードで記述し、捕捉することが可能になり、コードが理解しやすくなり、結果、ソフトウェアのメンテナンス性は上がります。
カプセル化とテストによる保護は必ずしも対立しませんが、それらが対立する場合、私はテストによる保護を優先します。そのほうが、将来カプセル化を強めるために役立つことが多いからです。
カプセル化はそれ自体が目的ではありません。それは理解するための手段です。
(『レガシーコード改善ガイド』 初版第2刷 p186)
本当に大事なことは盲目的に OO の教義に従うことではなくて、より良い品質のソフトウェアを書き、その価値を届けることなわけで、OO の教義も今回の原則違反もそのための手段なんですよね。
もしかすると TDD の本やリファクタリングなんかにはこの手のことがすでに書かれているのかもしれませんが、目から鱗でした。どんどん活かしていこうと思います。
cf.
2010-09-21 [長年日記]
_ rsync -C で除外されるバージョン管理関連のファイル
rsync の -C オプションは CVS と似たアルゴリズムで同期対象からファイルを除外してくれる。
- $HOME/.cvsignore
- CVSIGNORE 環境変数
- 各 SRC ディレクトリの .cvsignore
を参照してくれるが、それ以外にもデフォルトで除外してくれるパターンもある。
少なくとも rsync 3.0.7 では
-C, --cvs-exclude
This is a useful shorthand for excluding a broad range of files
that you often don't want to transfer between systems. It uses a
similar algorithm to CVS to determine if a file should be
ignored.
The exclude list is initialized to exclude the following items
(these initial items are marked as perishable -- see the FILTER
RULES section):
RCS SCCS CVS CVS.adm RCSLOG cvslog.* tags TAGS
.make.state .nse_depinfo *~ #* .#* ,* _$* *$ *.old *.bak
*.BAK *.orig *.rej .del-* *.a *.olb *.o *.obj *.so *.exe
*.Z *.elc *.ln core .svn/ .git/ .bzr/
が対象になっている。ということで
- RCS
- SCCS
- CVS
- Subversion
- Git
- Bazzar
これらはデフォルトで対応しているが Mercurial は対応していない。ことが分かった。ちぃ、……覚えられない。
2010-09-24 [長年日記]
_ JavaScript の debugger で勘違い& (function(){})() の中に入る
javascript には debugger って予約語があるじゃないですか。あれって
debugger を起動するためのものじゃなくて、break するためのものなんですね
分かってなかった。
- debugger を書き足してブラウザを reload してボーっ。何も起きないなー。
- あ、debugger というか Firebug は自分で開いておかないとダメなのか。おばか。
- ぼー。
- あれ? window.onload で走る処理が動かない <- その前に break してた。
- あれ? じゃあどうやって (function(){})() なコードの中に入るの?
- setTimeout() でタイミングをずらして break
なんとかなった。
2010-09-26 [長年日記]
_ 複数のGeohashでどのようなエリアを作れるか確認できるツールを書いた
一ヶ月前に GeohashのグリッドをGoogle Maps上に再現するツール書いた で
- Google Maps の上に
- 単一の Geohash を描画でき
- 地図の移動と連動させられる
というツールを書いたんだけど、これは単一の Geohash で何がどの程度表現可能なのかを確認するために作ったものだった。実際にはそのときにも書いたけど単一の Geohash で表現可能なエリアが人間の意図したエリアと 1:1 に対応しないケースが必ず出てくるというかすでに出ていて、
- 複数の Geohash で表現可能なエリアを可視化するツール
が欲しいなと思っていた。
で、書いた。
gist: 595515 - Geohash Visualizer 2, multiple geohashes can be drawn on google maps- GitHub

基本的なアイディアは以前書いたものと同じで、コードも大半はそのまま流用。単に複数の Geohash を textarea に書けるってだけ。複数書けるので map の移動との連動は不可能になり、Geohash に該当する Polygon の再描画のタイミングは map そのものを再描画したときと明示的に Geohash を与え直したときだけになったので、バージョン1より軽く動くかも。
UI がダサイのは仕様です。ほんとは 1 と 2 を使いやすく統合できるとかっこいいんだろうけど、もう力尽きた。
すぐ動くバージョンも置いたのでなんのこっちゃと思う人はとりあえず LatLng に表示されている Geohash を textarea にコピペして適当に頭から 5, 6 文字のものに縮めて [ geohash ! ] ってボタンをクリックしてみるとなんとなく分かると思う。
本当は LocalStorage とか使って使いやすいアプリに仕立てられるとそこそこ使えるツールになりそうな気がするんだけど、今はとりあえず確認できるだけー。
※ 細かい話だけど、hash ってもしかして複数形ないんじゃ? だとするとなんかすごく恥ずかしいコードになってしまったけど、もう直す気力ないんでいいんです。
2010-09-28 [長年日記]
_ マッチしなかった要素を探す
ちょっと表現が微妙なんだけど
- 正規表現マッチを使い
- マッチしない要素(行など)
を探す方法が急に気になったのでまとめてみた。
grep -v
GNU grep, BSD grep の場合は -v オプションが使える。--invert-match で、まさに「マッチしなかった行を探す」目的に使う。
awk '!/RE/'
awk の場合は基本的な動作を
パターン { アクション }
で記述する。このパターンを ! で否定すればマッチしない場合の動作を簡単に記述できる。
フィールドなどを明示する場合は
$1 ~ /RE/
がマッチするパターンで
$1 !~ /RE/
がマッチしないパターンになる。この ~, !~ の書き方は他の多くの LL にも採用されている。少なくとも Perl, Ruby では ~ を =~ で置き換えるだけでパターンの部分は記述できる。
Perl の grep()
Perl には list の中から特定のパターンにマッチする要素だけを抜き出す grep() 関数がある。これは
grep( /RE/, LIST )
という形で使う*1。このとき !/RE/ とすればマッチしないものだけを抜き出せる。
Ruby の Enumerable#grep()
Ruby には Perl の grep によく似た機能があって、それが Enumerable#grep(). 構文こそ違うけど、働きはよく似ている。ただし、
Enumerable#grep( !/RE/ )
とは書けない。どうするのかなぁと思ったけど、こう書くしかないのかな?
Enumerable#select { |e| e !~ /RE/ }
Enumerable#find_all { |e| e !~ /RE/ }
Enumerable#reject { |e| e =~ /RE/ }
最近は find_all が有名っぽいので find_all で否定のマッチを書く場合が多いのかも。reject は意味は分かるけどまどろっこしい感じがする。
PHP の preg_grep()
PHP には PCRE を使って正規表現周りの機能を実現している preg_XXX() 関数群があって、この中に Perl の grep() のような preg_grep() がある。ただし、PHP には正規表現リテラルはないので
preg_grep( !/RE/, array() )
のようには書けない。どうするかというと、
preg_grep( '/RE/', array(), PREG_GREP_INVERT )
のように第3引数に PREG_GREP_INVERT という定数を与えてやる。
sed -ne '/RE/!p'
[2010-10-123 追記]
Twitter / eban: @finalfusion えー? sed -ne ' ...
さらにツッコミがあったので。場外場外。
sed 使ってないので未確認で垂れ流しますよ。
[2010-10-11 追記]
sed の説明はしません(笑)
改めて思うと !/RE/ の書き方は awk じゃなくて sed 由来かな? あるいはもしかして ed ? じゃないよな、たぶん。
*1 だけじゃないけど
_ ムムリク [ご利用ください。 http://mumrik.air-nifty.com/blog/2010/09/07_rk20..]
_ wtnabe [すげぇ。あざっす!]