<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>おそらくはそれさえも平凡な日々</title>
    <link rel="alternate" type="text/html" href="http://www.songmu.jp/riji/" />
    <link rel="self" type="application/atom+xml" href="http://www.songmu.jp/riji/atom.xml" />
    <id>tag:www.songmu.jp,2008-09-15:/riji/2</id>
    <updated>2011-12-31T12:28:13Z</updated>
    <subtitle>日々の落書き</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type Pro 4.21-ja</generator>

<entry>
    <title>最近書いたPerlモジュールとかパッチとか</title>
    <link rel="alternate" type="text/html" href="http://www.songmu.jp/riji/archives/2011/12/perl_4.html" />
    <id>tag:www.songmu.jp,2011:/riji//2.529</id>

    <published>2011-12-31T12:19:52Z</published>
    <updated>2011-12-31T12:28:13Z</updated>

    <summary>12月頭頃は、今年関わった案件を振り返って、共有できそうな部分をコード化したりと...</summary>
    <author>
        <name>Songmu</name>
        <uri>http://songmu.jp/</uri>
    </author>
    
        <category term="コンピュータ" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.songmu.jp/riji/">
        <![CDATA[<p>12月頭頃は、今年関わった案件を振り返って、共有できそうな部分をコード化したりとかしていた。そういう下回りを整備するような作業は割と好き。</p>

<p>その中で一応公開できそうなやつとかを以下に記す。</p>]]>
        <![CDATA[<h4><a href="https://github.com/Songmu/p5-Encode-JP-Mobile-UnicodeEmoji">Encode::JP::Mobile::UnicodeEmoji</a></h4>

<p>iOS5から絵文字がUnicode絵文字になってたりとかAndroid対応とかでUnicode絵文字対応がちょっと必要になって書いた。</p>

<p>昔はUnicode絵文字とか無かったのでEncode::JP::MobileはUnicode私用領域に絵文字をマッピングする仕様になってますが、Unicode絵文字領域の文字をそのEncode::JP::Mobileの私用領域にマッピングしてしまうという後ろ向きモジュール。</p>

<p>絵文字はEncode::JP::Mobileの私用領域のレンジでDBに保存しているとか言うことも多いので、そういうサービスでスマホにも対応させる場合、Unicode絵文字も同様の対応を取らざるを得ないこともあり、その変換をするためのモジュールです。</p>

<p>一応動きますが、実装は超適当です。ちゃんとしたマッピングを書いているわけではなく、Encode::JP::EmojiとEncode::JP::Mobileの合わせ技で無理やり実現しているという...。Fallbackとかもよく分からなかったんで指定していません！(ｷﾘｯ</p>

<p>なので、現状githubのみ。</p>

<h4><a href="p5-HTTP-MobileAgent-Plugin-SmartPhone">HTTP::MobileAgent::Plugin::SmartPhone</a></h4>

<p>HTTP::MobileAgentにis_iosとかis_smartphoneとかそういうメソッドを生やしたかったので書いた。</p>

<p>これも一応動きますが、正規表現直書き判定でメンテナンス性とかを考えてないので駄目な感じ。なので同様にgithubのみ。</p>

<h4>Archer</h4>

<p>これは<a href="https://github.com/tokuhirom/Archer/commit/239829c5d2fd0a15abdbecbe593146c466905c3c">pull req送って</a>取り込んでもらった。</p>

<p>今年初めの方から、このパッチあてて使ってたんだけど、パッチ送ってなかったのは、File::Rsync のバージョンによって出る問題だかと思って深く追ってなかったからなんだけど、File::RsyncのChangelog見てみたら実はそんなこと無かったので、取り込んでもらった次第。<br />
(File::Rsync::(?:err|out)が以前はString返していたのが、Arrayを返すようになったとか想像していたら、もともとArray(?:_ref)?を返していてそんなことはなかった。)</p>

<p>File::Rsync::(?:err|out)はコンテキストに応じてリストかarray_refかを返すようになっている。そうすると、スカラコンテキストだと常に真になってしまうという問題があって(空のarray_refは真)、<code>if () = $rsync->out;</code>とかやって無理やりリストコンテキストで返すようにしている。カッコ悪い。</p>

<p>Archerは超便利に使わせてもらってるんだけど、情報が少ないし、まだ使いきれてない感があるから、もうちょっと知見を貯めていきたい。</p>

<p>割と弊社では活用されていますが、バラバラに使っていて知見が共有できておりません。</p>

<p>Plugin::ConfirmがPerl5.14では上手く動かない問題なんかもあるから、ちょっと手を入れてみようかな。</p>

<p>ちなみに、<a href="https://github.com/tokuhirom/Archer/watchers">Archerのwatcher</a>がAuthor除くと弊社社員だけで吹いた。</p>]]>
    </content>
</entry>

<entry>
    <title>Wiki記法的なものとか文書管理とかに思うこと</title>
    <link rel="alternate" type="text/html" href="http://www.songmu.jp/riji/archives/2011/11/wiki_1.html" />
    <id>tag:www.songmu.jp,2011:/riji//2.528</id>

    <published>2011-11-05T14:57:28Z</published>
    <updated>2011-11-05T15:01:12Z</updated>

    <summary>Wiki記法的なものとか文書管理とかに思うこと 最近社内向けのドキュメント書いて...</summary>
    <author>
        <name>Songmu</name>
        <uri>http://songmu.jp/</uri>
    </author>
    
        <category term="コンピュータ" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.songmu.jp/riji/">
        <![CDATA[<p>Wiki記法的なものとか文書管理とかに思うこと</p>

<p>最近社内向けのドキュメント書いてたりもするので、かねがね思っていたことを書く。かなり与太話。</p>]]>
        <![CDATA[<h4>文書管理とかについて思うこと</h4>

<p>文書くときって使い慣れたローカルのエディタで編集したいじゃないですか。長いBlogを書くときって、結局ローカルで書いたのをテキストエリアに貼り付けて、みたいにやっている人は多いと思うんですよ。僕はそうしてます。</p>

<p>BlogにせよWikiにせよドキュメントにせよ、ローカルでテキストファイルを編集できて、バージョン管理して、リポジトリにコミットしたらサイト反映みたいになってると、楽だと思うんですよね。</p>

<p>複数人で編集するときにすごく効果を発揮するはず。Wikiとか編集が競合したらめんどくさいけど、今時のバージョン管理ツールなら上手いことマージしてくれたり、コンフリクトを検出できるし。</p>

<p>文書フォーマットをどうするかというと、LaTeXで書いてPDF出力してみたいな話もあると思うし、書籍を執筆するときなんかはそれで良いと思う。実際問題としてはHTMLに変換できる簡易マークアップ記法が良いんじゃないかと思っている。</p>

<h4>HTML+CSSの表現力ってのはすごい</h4>

<p>アウトラインを意識すれば文書を書くというレベルで不自由はない。アウトラインを意識せざるをえないってのがHTMLで文書を書く上で逆に良い点だと思う。print.css書けば印刷物としても十分耐えうる。レイアウトもかなり自由が効く。</p>

<p>実際、僕は職務経歴書はHTMLで管理している。「プログラマの職務経歴書なのに綺麗に整ってますね」とか良くわからない褒められ方をされたことがある。HTMLで書いたと言ったら非常に驚いていた。</p>

<p>書籍とかで目次や索引をつけてページ数との対応とかをやるとなると、ワープロソフトに軍配があがると思うけど、実際は逆にハイパーリンクを張れたほうが何かと便利。</p>

<p>ePubの議論も盛んになってきたので、HTMLを紙にした時の見え方やそれに関連するCSSプロパティの対応はだいぶ進んできている。例えば、少し前まで背景画像のサイズ指定ができない問題があったけどbackground-sizeに対応しているブラウザも増えてきた。</p>

<h4>Wiki記法とか</h4>

<p>ただ、HTMLを直で書くのはきついし、HTMLテキストは可読性も低い。HTMLで使う要素は限られているのだから簡易記法で書くのは理にかなっている。</p>

<p>Markdownはテキストファイルのままでも可読性が高いってのが優れている。</p>

<p>ただ、Wiki的記法に総じて言えることだが、簡易記法である分、HTML→記法の逆変換が難しいってのが問題点。あくまで簡易記法だからHTMLのすべてをまかなえるわけではない。</p>

<p>Markdownは直にタグを書けるようになっていて、Markdownでまかなえないことは自分でタグを書いて解決するという割り切った方針になっている。そして、Markdownが提供するシンタックスも最低限になっている。</p>

<p>その割り切りは好きなんだけど、シンタックスがちょっと最低限すぎるってのがある。ちょっと複雑なHTMLを書きたくなると、すぐにタグが入り交じって可読性が落ちる。やれることが最低限な分、独自拡張が乱立してるのも問題。</p>

<p>そして、タグを書けるようにしているってのは実装上かなり大変。Wikiパーサーはただでさえ処理の前後関係を整理するのが難しいのに、タグ直書きを実現するためにパーサーのコードはさらにカオスなことになっている。だから前後関係を崩さないように拡張するのも大変。</p>

<h4>Markdownその他簡易マークアップ言語に不満な点</h4>

<p>定義リストとテーブルは欲しい。</p>

<p>定義リストは議事録的なものをとるときに、質疑応答とか小テーマとそれに対する決定事項みたいなものを並べるときに使いたい。(議事録なんかをとるときに簡易マークアップ言語を使うのは、書式の統一がとれて良いと思う)</p>

<p>あと、ソフトウェアのドキュメンテーションとかやると、codeの他に出力やシェルプロンプトを出したいので、sampが書けるとうれしいよなぁと思う。</p>

<p>あと、そろそろHTML5対応した簡易マークアップ言語が欲しいと思うところ。</p>

<p>特にasideが欲しい。実際普通に文章を書いていて横道にそれた時とか、議事録なんかで本筋から外れた話を書くときに使いたいですね。</p>

<p>HTML5の目玉(？)である、セクショニングの頭でh1を使うみたいなのは、既存の基本でもバリバリやっちゃって良いと思う。</p>

<p>このへんの不満を解消すべく、<a href="http://www.kuaiwiki.com/">KuaiWiki</a>を書き始めた部分があるんだけど、色々コード的にイケてなさすぎるので、げんなりして開発が止まっている。それに結局こういうWiki記法ってのは使ってもらってなんぼですね。そういう意味ではてな記法は成功したと思う。</p>

<h4>Sphinxは便利っぽいけどreSTがイマイチ</h4>

<p>あくまで個人的な感想ですが、reSTはイマイチだと思う。</p>

<p>あと、SphinxはePub変換とかPDF変換とか謳ってるけど、ePubは所詮HTMLに辞書情報のXMLファイル付加してzipで固めただけだし、PDFもWkHtmlToPdfとか使えば、HTMLからPDF生成できるわけだからそんな特別な話では無い気がする。要は印刷を意識したprint.cssが書ければあとは自由自在。</p>

<p>HTMLとPDFとePubが出せれば他のフォーマットは特に必要ないだろうし、HTMLがあれば、PDFもePubも出せるのです。</p>

<h4>リンクとかリソースとか</h4>

<p>Wiki的なものを実現させようとするときに、ページ内リンクをどう実現するかってのは地味にめんどくさかったりする。(ページ名を変えたときのリンク張替えとか、マルチバイトのリソースをどう管理するかとか。ファイルとして保存する場合はファイル名を可搬性のある形でどう保存するかとか。)</p>

<h4>数式とか</h4>

<p>LaTeXで書けるようになってて、MathMLで出力される感じのシンタックスがあれば良いのかなぁ。MathMLどうなのかなぁ。今日のSugamoでも話題になってたけど。</p>

<h4>図とか</h4>

<p><a href="http://blockdiag.com/">blockdiag</a>がすごすぎる。テキストファイルでUMLを記述して画像出力するという素晴らしさ。今後の継続開発に期待。</p>

<p>あとは、<a href="https://cacoo.com/">Cacoo</a>も素晴らしすぎる。前職で社内向に<a href="http://www.songmu.jp/yapafi/tutorial">Yapafiのドキュメント</a>書いたときに使った。UMLの要素も揃っている。とかそういう話を今日のSugamoでも話が出た。</p>]]>
    </content>
</entry>

<entry>
    <title>YAPC::Asia Tokyo 2011</title>
    <link rel="alternate" type="text/html" href="http://www.songmu.jp/riji/archives/2011/10/yapcasia_tokyo.html" />
    <id>tag:www.songmu.jp,2011:/riji//2.527</id>

    <published>2011-10-16T13:47:43Z</published>
    <updated>2011-10-16T13:48:10Z</updated>

    <summary>ありきたりで、毎回そして誰もが言うことですが、楽しかったし、刺激になった。 本当...</summary>
    <author>
        <name>Songmu</name>
        <uri>http://songmu.jp/</uri>
    </author>
    
        <category term="コンピュータ" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.songmu.jp/riji/">
        <![CDATA[<p>ありきたりで、毎回そして誰もが言うことですが、楽しかったし、刺激になった。</p>

<p>本当に運営の人はお疲れ様でした。毎年のことながら素晴らしいカンファレンスをありがとうございました。今年の運営はこれまでの経験が活かされていて、非常に洗練されていたと思います。</p>]]>
        <![CDATA[<p>今年は話をしたかった人とかなり話せてすごくよかった。「交流しよう」というテーマに即して、全体的にすごく交流しやすい雰囲気を作り出していたと思う。深く考えていなかったけど「懇親会無料」ってのも、交流を促進させるための施策として素晴らしいものでしたね。それに、昼食の時間が取ってあったので、芝生で交流ができたのは非常によかった。</p>

<p>個人的にはブログやらTwitterやらISUCONやらで以前より名前や顔を覚えてもらえていることもあって、交流しやすかったというのもあります。勝手に後夜祭から帰途につくときに、「@lapis25 さんと話せなかったな」とか思っていたら、帰りの電車を待っているときに本人から声をかけていただけたのは感激でした。</p>

<p>まあ、そこまで有名になったわけでも無いのですが、実力に比べて若干名前先行の感があるのでもっと精進しないといけないな、と思います。</p>

<p>そして、Kamakura.pmで話した内容の焼き直しでも良いから、話しておけばよかったと少し後悔しています。年々トークのレベルが上がっているので、そろそろ話しておかないと置いていかれる一方だな、という感じがする。来年は話す。</p>

<p>印象に残ったトークとか</p>

<h4>Perl 5.16 and beyond(Jesse Vincent)</h4>

<p>Perlに対する誤解を解くだとかレガシーPerlがどうのみたいなことを言うフェーズは終わって、どんどんPerlを進化させていくというフェーズに入った。Perl自体をよりスリムに、ソースコードもリファクタリングしていく。</p>

<p>といった内容を話していたと思いますが、非常に力強いメッセージで、期待が持てました。</p>

<p>ORMに関する議論なんかで良く言われることですが、すわ関数呼び出しのコストが高いだとか、オブジェクト生成のコストが高いからといって、ハッシュばかり使うっていうのは、有効なのはわかりますが、バッドノウハウ以外の何者でもない。(DBICがオブジェクト作り過ぎなのは確かですが)</p>

<p>確かに、ハッシュはシリアライズもしやすいし、イチイチオブジェクトの流儀を覚えるよりも楽なことも多いのは確かですが、だからといって、ハッシュばかり使うのは他言語からしたらナンセンスに思えるのは確かだと思います。</p>

<p>そのあたりが、今後Perl自体のソースコードのリファクタリング次第で高速になっていくことを期待しますし、共通的なオブジェクトモデルがどうなっていくか気になるところです。</p>

<p><br />
<h4>Mobage オープンプラットフォームの事件簿(Toru Yamaguchi)</h4></p>

<p>モバゲーでサービスを作っていることもあって、Zigorouさんやriywoさんのトークも非常に自分にとって身近で興味が持てるネタでした。</p>

<p>特にZigorouさんのトークに関しては「ここまで話しちゃっていいんだ...」とかびっくりするような内容でした。</p>

<p>話していた障害の話は、自分が作っているサービスにもモロに影響がでたやつなんだけど、話を聞いてみると、規模は違えどこちらでも悩んでいるような話で、逆に親近感が湧くような話でした。</p>

<p>しかし、それらに対する解決策は目からウロコが落ちるような、でも真似したくないような驚くべき内容で、とはいえ発想の転換という点では非常に参考になりました。</p>

<p>初日の懇親会で、Zigorouさんとお話しましたが、「なんか欲しい機能とかありませんか」とか聞いてきてくださって、こちらが出した要望にも真剣に考えてくださって本当に嬉しかったです。</p>

<p>こういうエンジニアの横のつながりってのは、なかなか非エンジニアには理解しがたい部分でしょうね。</p>

<p>他者のエンジニアが弊社に遊びに来ることとかあるんですけど、「スパイかも知れないよ」とか冗談をいう人がいて、勿論冗談なんだけどそういう冗談が出てしまうのは非常に残念だなぁと思ったりすることもあるので。</p>

<p>あとは、riywoさんのトークでも、</p>

<ul>
<li>運用側にイベントの開始を伝えてない</li>
<li>「リアルタイム」という言葉は特に危険</li>
</ul>

<p>みたいなことを話していて「あるある」とか思いました。</p>

<h4>Perlで構築された中規模サイトのDC引っ越し記録(FUJIWARA Shunichiro)</h4>

<p>ベストスピーカー賞おめでとうございます。初日のほうが来場者が少ないし、投票を促されるのも二日目なので、二日目のトークが有利だと思われる中での勝利は見事としか言いようがありません。</p>

<h4>弾座談会</h4>

<p>トークじゃないけど、二日目の夕方にスウィーツエリアで日本と海外のハッカーたちによる座談会が行われていました。</p>

<p>そこではいつもは空気を読まない弾さんのファシリテート力に驚いた。それだけじゃなく、弾さんが途中で口を挟んでも、すかさずそれに口を挟み返す、みたいなことが頻繁に行われていて、「ああ、これが英語圏の会話なんだな」とか思いました。</p>

<p>スピーチとかはあるけど、英語の座談会的なものは初めて聞いたのは初めてだったので非常に面白かった。聞き取れた英語は3割くらい。</p>

<hr />

<p>その他思ったこと。</p>

<h4>ハッカー文化の啓蒙</h4>

<p>こういうYAPCの雰囲気やハッカー文化的なものを、ビジネスサイドの人たちにも理解してもらうことは大事なのかなぁと思った。最後のhidekさんのトークを聞いてもDeNAなんかはそこにすごく成功しているんだと感じた。</p>

<p>自社のエンジニアの書いたコードが他社のサービスで動いているし、その逆もまた然り。そういう基本的なところからして、ビジネスサイドの人間はなかなか信じられなかったりする。</p>

<p>YAPCがビジネスビジネスしたイベントになるのはゴメンだけど、お金を出してもらうだけではなく、ビジネスサイドの人を引っ張ってくる努力もしたほうが良いんじゃないかと感じている。</p>

<p>今回はスポンサー枠みたいなのもあって、うちの管理部門の人もYAPCに来たりしたわけだけど、一人は「YAPCすごく楽しいですね！」と言っていた。そいつはなんでも本気で「楽しい」と言えるナイスな奴なので、逆に参考にはならないけど、そういうふうにYAPCの空気を非エンジニアに感じてもらうってのは重要なんじゃないかと思う。</p>

<h4>キャリアとか家庭とか</h4>

<p>Perl界隈は僕くらいの年代が多いと思うんだけど、家庭をどうするかに関して色々考えていている人が多いように感じました。JPA理事の牧さんも子供欲しいっておっしゃってますし。</p>

<p><a href="http://www.google.co.jp/search?q=%E5%88%BA%E8%BA%AB%E3%81%95%E3%82%93%E5%95%8F%E9%A1%8C">刺身さん問題</a>(僕しか言ってない)について刺身さんと話せたのも良かった。</p>

<p>一般的にWebエンジニアは家庭を大事にしますが、Webサービスは昼夜問わず対応しなければいけないことも多く、仕事との両立は頭の痛い問題です。</p>

<p>しかし、帰りの電車で、@lapis25さんも@kazeburoさんも「子供かわいいですよね」とかおっしゃっていて、非常に幸せな気持ちになりました。</p>

<p>てことで、Webエンジニアは結婚相手として非常におすすめですね。おすすめな理由はここでは語り切れないので、またの機会にあらためることにします。</p>]]>
    </content>
</entry>

<entry>
    <title>人生は調和級数であるがゆえに美しく、業が深い</title>
    <link rel="alternate" type="text/html" href="http://www.songmu.jp/riji/archives/2011/10/post_378.html" />
    <id>tag:www.songmu.jp,2011:/riji//2.526</id>

    <published>2011-10-09T15:29:33Z</published>
    <updated>2011-10-09T16:57:34Z</updated>

    <summary>しかし、ブログは一度放置に入って全く書かなくなるものですね。くだらないことでも良...</summary>
    <author>
        <name>Songmu</name>
        <uri>http://songmu.jp/</uri>
    </author>
    
        <category term="雑記" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.songmu.jp/riji/">
        <![CDATA[<p>しかし、ブログは一度放置に入って全く書かなくなるものですね。くだらないことでも良いから書き続けることが大事なんでしょう。てことでくだらないことでも書こうかなと。</p>

<p>最近はMTで書くのがたるくなってきて、自分で適当なBlogツール的なものを作ろうかとか考えて、markdownをgit管理する簡易CMS的なものを多少作ってもいたのですが、そんなことをしているうちに余計ブログを書かなくなったフシもあります。</p>]]>
        <![CDATA[<p>閑話休題。</p>

<p>最近(でもないけど)以下のようなツイートをよく見かけますね。</p>

<blockquote><p>hogeはfuga日生きた。今日は有意義だったか</p></blockquote>

<p>こんなのは以下のワンライナー一発です。11448日生きたようです。</p>

<pre><code>perl -MDateTime -E 'say DateTime-&gt;today-&gt;delta_days(DateTime-&gt;new(year=&gt;1980,month=&gt;6,day=&gt;5))-&gt;in_units("days")'
</code></pre>

<p>これを見て常々考えていたことを思い出したんだけど、一年の体感時間て何故かどんどん短くなるじゃないですか。それは、一年が自分の中で何度も繰り返された末に、その価値がどんどん陳腐化していくのが大きな理由だと思うんですね。</p>

<p>これの数式化を試みると、0歳から1歳までの1年てのはその人にとっては人生の全てなわけですよ。この1年の価値を1とすると、1歳から2歳までの1年は自分の人生の1/2を占めるわけで、1/2の価値になります。そして31歳から32歳の1年は自分の人生の1/32にしかなりません。つまり以下のようになります。</p>

<p>人生の体感時間 = 1 + 1/2 + 1/3 ...</p>

<p>この体感時間に基づいて、実際に自分がどれくらいの割合の人生を消化しているのかを1歳から100歳まで出力するワンライナーが以下です。人生が100歳と長めに仮定しています。</p>

<pre><code>perl -e '$die=100;$r+=$_ for map{1/$_}1..$die;printf "| %3d | %5.3f |\n",$_,sub{$i+=1/$_;$i/$r}-&gt;()for 1..$die'
</code></pre>

<pre><samp>|   1 | 0.193 |
|   2 | 0.289 |
|   3 | 0.353 |
|   4 | 0.402 |
|   5 | 0.440 |
|   6 | 0.472 |
|   7 | 0.500 |
|   8 | 0.524 |
|   9 | 0.545 |
|  10 | 0.565 |
|  11 | 0.582 |
|  12 | 0.598 |
|  13 | 0.613 |
|  14 | 0.627 |
|  15 | 0.640 |
|  16 | 0.652 |
|  17 | 0.663 |
|  18 | 0.674 |
|  19 | 0.684 |
|  20 | 0.694 |
|  21 | 0.703 |
|  22 | 0.711 |
|  23 | 0.720 |
|  24 | 0.728 |
|  25 | 0.736 |
|  26 | 0.743 |
|  27 | 0.750 |
|  28 | 0.757 |
|  29 | 0.764 |
|  30 | 0.770 |
|  31 | 0.776 |
|  32 | 0.782 |
|  33 | 0.788 |
|  34 | 0.794 |
|  35 | 0.799 |
|  36 | 0.805 |
|  37 | 0.810 |
|  38 | 0.815 |
|  39 | 0.820 |
|  40 | 0.825 |
|  41 | 0.830 |
|  42 | 0.834 |
|  43 | 0.839 |
|  44 | 0.843 |
|  45 | 0.847 |
|  46 | 0.851 |
|  47 | 0.856 |
|  48 | 0.860 |
|  49 | 0.863 |
|  50 | 0.867 |
|  51 | 0.871 |
|  52 | 0.875 |
|  53 | 0.878 |
|  54 | 0.882 |
|  55 | 0.886 |
|  56 | 0.889 |
|  57 | 0.892 |
|  58 | 0.896 |
|  59 | 0.899 |
|  60 | 0.902 |
|  61 | 0.905 |
|  62 | 0.908 |
|  63 | 0.911 |
|  64 | 0.915 |
|  65 | 0.917 |
|  66 | 0.920 |
|  67 | 0.923 |
|  68 | 0.926 |
|  69 | 0.929 |
|  70 | 0.932 |
|  71 | 0.934 |
|  72 | 0.937 |
|  73 | 0.940 |
|  74 | 0.942 |
|  75 | 0.945 |
|  76 | 0.947 |
|  77 | 0.950 |
|  78 | 0.952 |
|  79 | 0.955 |
|  80 | 0.957 |
|  81 | 0.960 |
|  82 | 0.962 |
|  83 | 0.964 |
|  84 | 0.967 |
|  85 | 0.969 |
|  86 | 0.971 |
|  87 | 0.973 |
|  88 | 0.975 |
|  89 | 0.978 |
|  90 | 0.980 |
|  91 | 0.982 |
|  92 | 0.984 |
|  93 | 0.986 |
|  94 | 0.988 |
|  95 | 0.990 |
|  96 | 0.992 |
|  97 | 0.994 |
|  98 | 0.996 |
|  99 | 0.998 |
| 100 | 1.000 |</samp></pre>

<p>100年生きたとしても、7歳にして人生が折り返すことがわかります。</p>

<p>さて、上の式をみてピンと来た方もいらっしゃるかも知れません。1 + 1/2...の無限和を数式化すると以下のようになります。</p>

<p><img alt="\displaystyle\sum^{\infty}_{n=1} {1 \over n}" class="formula" /></p>

<p>はい。これは<a href="http://ja.wikipedia.org/wiki/%E8%AA%BF%E5%92%8C%E7%B4%9A%E6%95%B0">調和級数</a>ですね。</p>

<p>上記リンクから引用。</p>

<blockquote><p>名称の「調和」(harmonics) というのは音楽や和声学における倍音の概念に由来するもので、振動弦の倍音の波長というのが弦の基本波長の 1/2, 1/3, 1/4, ... となっていることによる。調和級数の各項は前後の項の調和平均になっており、また調和平均という用語もやはり音楽に由来するものである。</p></blockquote>

<p>音楽においても非常に重要な数式でもあり、西洋音楽の美しさの要とも言える式だということがわかります。</p>

<p>さらに以下の記述を引用します。</p>

<blockquote><p>調和級数は、その項の極限が 0 になるにもかかわらず発散するという意味で、初学者にとっては直観的ではない級数である。</p></blockquote>

<p>はい。ほんと直観的ではないですね。</p>

<p>この級数が収束するのであれば、人生を無限に生きることに特に意味が無いと断言できるのですが(いくら生きたって頭打ちだから)、この級数が発散するということは、無限に生き続けることにはわずかながらに意味があるということです。</p>

<p>「いくら生きたって、一定の値に収束するんだから、無限に生きたって意味はないんだ」とか言いたかったんですが、見事に失敗に終わりました。ということで人生は美しくも業が深いものですねと改めて思ったのでした。</p>]]>
    </content>
</entry>

<entry>
    <title>#isucon で優勝させてもらってきました</title>
    <link rel="alternate" type="text/html" href="http://www.songmu.jp/riji/archives/2011/08/isucon.html" />
    <id>tag:www.songmu.jp,2011:/riji//2.525</id>

    <published>2011-08-28T07:15:13Z</published>
    <updated>2011-08-28T08:16:44Z</updated>

    <summary>まずは、ライブドアの皆様、素晴らしいイベントの提供本当にありがとうございました。...</summary>
    <author>
        <name>Songmu</name>
        <uri>http://songmu.jp/</uri>
    </author>
    
        <category term="コンピュータ" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.songmu.jp/riji/">
        <![CDATA[<p>まずは、ライブドアの皆様、素晴らしいイベントの提供本当にありがとうございました。めちゃくちゃ楽しかったです。</p>]]>
        <![CDATA[<p>Kayacのエンジニア3人 @fujiwara @sugyan @songmu の3人でチームfujiwara組を結成し、結果優勝することができました。</p>

<p>実際は周りの認識通り、@fujiwaraさんに優勝させてもらったようなもので、@sugyanと僕は手を動かしていただけです。まあ、空気にならずには済んだので、そこは安堵しています。</p>

<p>修正したisuconソースはフォークして<a href="https://github.com/Songmu/isucon">Github</a>に置きました。プログラムの修正部分のみで、my.cnfの修正なんかはここには反映されていません。</p>

<p>さて、@fujiwaraのコンテストでの動きや、帰宅後のBlogアップまであらゆる仕事が速くてビビるんですけど、詳しくは、<a href="http://d.hatena.ne.jp/sfujiwara/20110827/1314460582">#isucon で優勝してきました</a>を見てもらうとして、</p>

<ul>
<li>どういうドタバタがあったのか</li>
<li>アプリの修正点とか</li>
<li>@fujiwara的には当たり前ですっ飛ばしてるけど僕には勉強になったこと</li>
</ul>

<p>みたいなことを書きたいと思います。結果としては圧勝みたいになっていますが、かなり危うい部分や、苦肉の策なんかがあります。</p>

<h4>事前作戦会議とか</h4>

<p>前日のランチで軽く雑談。</p>

<p>とはいえ話したのは、「リバースプロキシはnginxにするでしょう」「memcachedはどこかで活用するんでしょうね」くらいの話。あんま変なモノは使わず、使い慣れている環境を使いましょう。あとは出たとこ勝負という話。</p>

<h4>当日の役割分担</h4>

<p>当日の役割分担は自然と決まって、作戦決定とOS・ミドルウェアの設定周りを@fujiwaraが担当して、それに従って@sugyanと僕が手を動かすという感じになりました。</p>

<h4>初期設定とか 11:30-</h4>

<p>まずはSSH周りの設定。authorized_keysにそれぞれ自分の鍵書き込んだり、hostnameの設定したり。rev(リバースプロキシ)を踏み台にして、他のサーバーに入る方針。</p>

<p>あとは、revにもアプリが入っていたので、そこでgit init。by @sugyan。それをローカルに落としてきて開発ってつもりだったんだけど、最後はサーバー上で開発になってました。</p>

<p>デプロイに関しては、revからappサーバー2台に、rsync -> SSHリモートコマンドでsupervisord再起動 みたいな簡単なシェルを書いた。(簡単なとか言いつつ、結構調べちゃいましたけどね！) by 僕</p>

<p>@fujiwara 組長にhostname等の設定をしてもらっている間に、アプリをざっと眺める。シンプルで綺麗。生DBIでテンプレートもxslate。こりゃPerlモジュールレベルじゃ全然高速化の余地はないなと、自分が空気にならないか心配になる。</p>

<p>PerlはSystem Perl。置き換えても良いかもしれないけど、他にやることはあるでしょう。MySQLが5.5だったのはスゲー意外。4.0とか覚悟してたんだけどw</p>

<p>チャットは社内IRC。チャンネル作ることも考えたけど、普段使っているチャンネルに。そっちのほうが社内の他のエンジニアへの実況になって面白いかな、とも。</p>

<h4>最初の計測 12:30-</h4>

<p>各サーバーでtop回しながらベンチマークスクリプト走らせる。まずは何はともあれこれ。スコアは800/min程度。</p>

<p>MySQLがネックになっていることが判明したので、今度はクエリログ眺めながらベンチマーク。そこでサイドバーを作るために発行している以下のSQLがネックになっていることが判明。</p>

<pre><code>SELECT a.id, a.title FROM comment c INNER JOIN article a ON c.article = a.id GROUP BY a.id ORDER BY MAX(c.created_at) DESC LIMIT 10
</code></pre>

<p>クエリキャッシュを有効にしても焼け石に水で、1200/minくらいに向上したのみ。ただ、クエリキャッシュを適切に有効にしたことは、後々スキーマ変更した後のクエリ効率には貢献したので、もちろん有効な施策ではありました。</p>

<h4>アプリ修正開始 13:00-</h4>

<p>とりあえず、サイドバーが曲者だなってことで、まだ具体的な方針は決定はしていないものの、サイドバーの生成で上記クエリが走らないように、POST時にサイドバーの配列情報をmemcachedに突っ込んでしまうように先行して@sugyanがプログラムを修正することに。</p>

<p>で、よくよく考えたら、articleにlast_commented_atカラム追加すればjoinの必要なくなるしindexも張れるからかなり速くなるんじゃないか、と @fujiwara が指摘し、そのアプリの修正を僕、DBのAlterやデータ修正を@fujiwaraが担当。</p>

<p>僕と@sugyanがアプリの修正をしている間に、どうせ使うよねってことで、revにnginxとmemcachedを@fujiwaraがさくっとインストール。nginxのmemcachedプラグインも導入。</p>

<p>apacheからnginxにリバースプロキシを差し替えて、ベンチをとったらまさかの500/min。これは@kazeburoの罠で、時々keep-aliveを送りつけるベンチマーククライアントがいて、そのTCP接続が残り続けるのが問題だった。これはkeep-aliveをoffにすることで解決。</p>

<p>静的ファイルもアプリが返していたので、それもnginxでサーブするように変更。</p>

<p>僕の修正部分とnginxの合わせ技でベンチを取ったら20,000/min程度まで改善。@sugyanは大掛かりなコード修正で苦戦中。</p>

<p>このへんで一旦お昼ごはん。</p>

<h4>キャッシュ戦略 14:00-</h4>

<p>この時点で、DBのボトルネックは解消。次はアプリがネックになっている。フロントでnginxのmemcachedプラグインを使うってのは既定路線でそれを如何に有効に使うか。</p>

<p>データがPOSTされた1秒後にGETされるので、そこで確実に高速にレスポンスを返すためにまずはPOSTされた時点でGETされるであろうコンテンツを生成してキャッシュに乗せてしまおうという戦略。@fujiwara立案。</p>

<p>「GETされるであろうコンテンツの生成」はちょっとめんどくさいから、素早く実装できる方法として、localhostをFurlで叩いて、そのレスポンスボディをキャシュに載せてしまおうという力業。これまた@fujiwara案。このへんの見切り判断の早さがやばい。</p>

<p>その辺の実装を僕が担当。nginx memcachedプラグイン設定を@fujiwara担当。</p>

<p>リバースプロキシのアドレスをHostヘッダに入れてやる必要があるんだけど、FurlのHostヘッダの扱いに難があって、Hostヘッダを二重につけてしまったりしてしまう。あとで@xaicronに確認したところ、やっぱFurlの罠だった。結局LWP::UserAgentを使うことに。</p>

<p>その辺の変更を適用してベンチをとったら30,000/min程度までスコアが改善。ここまではすこぶる順調(のように見えた)。</p>

<blockquote>
<p>14:40 (fujiwara) 現在1位<p>
<p>15:21 (fujiwara) 少なくとも惨敗はないなw</p>
</blockquote>

<p><br />
<h4>迷走時間 15:30-</h4></p>

<p>キャッシュ戦略が有効に働き、ボトルネックがフロントに徐々に移行。「後はフロントの最適化」に専念。...とおもいきや「サイドバーの罠」にかかりここから苦戦することになる。</p>

<p>この時点でデータのキャッシュは上記の通りPOST時だけ。それを、GET時もキャッシュしてしまおうという戦略を@fujiwaraが立案。それを僕が実装。サーバー起動時に全URLにアクセスに行き、事前にキャッシュを温めてしまうウォームアップスクリプトを@fujiwaraが作成。</p>

<p>実装したところスコアはかなり改善したがエラーが頻発！</p>

<p>このへんで@sugyanのサイドバーの配列情報をmemcachedに入れる修正ができたので、マージして当て込んだところ、少しスコアは向上したが誤差の範囲内か。しかし、memcachedにミスヒットするとフェールオーバーしない男らしい作りだったため動作が安定せず、rejectすることに。フェールオーバー周りを改良して当て込む手もあったんだろうけど、残り時間の関係と、他のエラーも出てたので、問題点を絞りたかったってのが大きな理由。</p>

<p>この時点のエラー原因は後から振り返ってみると以下の4本。これが同時に起こったから、原因究明に苦労した。</p>

<ol>
<li>アプリ自体の単純なバグ</li>
<li>アクセス増に伴うip_conntrack溢れ</li>
<li>アクセス増に伴うnginx->memcachedでのローカルポート枯渇問題</li>
<li>サイドバーの罠</li>
</ol>

<p>3までは割とすぐ解決。@fujiwara がログを見る所が的確すぎて、原因究明が早すぎてビビる。</p>

<p>これで、問題完全解決とおもってベンチを走らせるも、サイドバーエラーが頻発。キャッシュをPOSTのみにするとエラーは起こらない。GETでもキャッシュさせるとエラーでベンチが通らない。</p>

<p>「謎だー」「DBコミットのタイミングかー」「でもオートコミットだよなー」</p>

<p>完全に迷走状態に。</p>

<p><br />
<h4>恐るべきはサイドバーの罠 16:30-</h4></p>

<p>いや、謎ではありません。以下を完全に見落としていたのです。</p>

<p><strong>データがPOSTされると他のページのサイドバーも書き換わる</strong></p>

<p>データPOST後の1秒後のGETだけではなく、他のランダムGETの処理でもサイドバーの整合性チェックをしていたのでベンチがコケていたのです。</p>

<p>考えてみればごく当たり前です。</p>

<p>つまりこれまで大丈夫だと思っていた、POSTの時だけキャッシュする戦略でも、GETの取られ方によってはベンチがこける可能性がある。</p>

<p><strong>そもそものキャッシュ戦略が完全ではなかった</strong></p>

<p>この恐るべき事実を突きつけられ、チーム内に衝撃が走ります。もう時間もない。</p>

<p>しかしここで、@fujiwaraの起死回生の一言がチームを救います。</p>

<p><strong>「cacheに秒数付けて調整するしかないな」</strong></p>

<p>それだー！苦肉の策ではありながら、時間内に出来ることはもうそれしか無い、むしろそれだけだったら十分すぎるほど時間に余裕はあります。当たり前の対策を的確なタイミングで言えるその凄さ。</p>

<p>懇親会で@kazeburoさんが講評前に「トップのチームはもっとフロントで捌くようにしてくると思ったけど、@fujiwara組はアプリに結構アクセスがあったのが意外だった」って言ってたって話を聞いた。</p>

<p>結局、上記のようにキャッシュ戦略に穴があったので、定期的にアプリに回してキャッシュを更新させるようにせざるを得なかったってのが理由です。ここはかなり出題者に負けた感があります。</p>

<p><br />
<h4>秒数調整 17:00-</h4></p>

<p>とりあえず、POSTのインターバルは1秒だからキャッシュの生存を1秒にしておけばほぼ安全。しかし、それだとキャッシュする意味が少なくなってしまう。他のチームのスコアを考えるともう少し冒険をしないとつらいところ。しかし、本番審査のベンチ時間は1分ではなく3分なので、その分は安全策を取らないといけない。</p>

<p>てことで、キャッシュの寿命を5秒に設定。ここでのベンチスコアは86,000/min! しかし、この時点のトップスコアが88,000/min程度だったので、それは上回れず。</p>

<p>とりあえず、100,000/minの初突破チームの特別賞狙いで、スケベ心を出してキャッシュの寿命を10秒に設定、nginxでのgzip圧縮転送等を試みるも、大して効果は出ず、96,000止まり。計測誤差範囲内。(この辺りの時間帯は各チームがベンチマークを回しまくっていたので、ベンチマークサーバーの負荷の関係か、ベンチマークのばらつきが大きかった。)</p>

<p>10秒でも大して効果なかったので、安全のためキャッシュ秒数を5秒に戻し。ここで、修正は凍結。あとは審査準備。</p>

<p>しかし実はここで僕がgit resetで "--hard"してなかったのでローカルのソースは巻き戻ってなかったというポカミスをしていた...。</p>

<p><br />
<h4>願いを込めて再起動 17:30-</h4></p>

<p>OS再起動後の審査スタートだったので、再起動後もちゃんとベンチが通るかどうかの確認。</p>

<p>ここで@fujiwaraの何気ない神の一手が発動。</p>

<p>おもむろに以下のようなテーブルを追加。</p>

<pre><code>CREATE TABLE article_bh (
...
) Engine=blackhole;
CREATE TABLE comment_bh (
...
) Engine=blackhole;
</code></pre>

<p>そして、以下のSQLがOS再起動後に実行されるように設定。</p>

<pre><code>INSERT INTO article_bh FROM (SELECT * FROM artcile);
INSERT INTO comment_bh FROM (SELECT * FROM comment);
</code></pre>

<p>うおお、なんてお手軽ウォームアップ。これでDBの内容をOSのメモリキャシュに載せるわけですね。</p>

<p>「memoryストレージ」みたいなことも話には出てたんだけど、まずは正攻法という哲学。</p>

<p>何度かベンチ回してスコア出るので大丈夫そうかな、と一安心</p>

<blockquote><p>17:53 (songmu) 1位奪還中。後は本番勝負。</p></blockquote>

<p>しかし間際でまさかのベンチFail。</p>

<p><br />
<h4>最後の修正 17:57-</h4></p>

<p>やっぱ5秒でも厳しいか、ってことで3秒に変更しようとする。しかし実は先程の記述のとおり、git上は5秒に戻してたけど、ソース上は10秒のままだったというオチ。なので、5秒に変更。</p>

<p>ソースを一行というか一文字変更するだけなんだけど、めちゃくちゃ焦って緊張した。ここでsyntax errorとか出したら死刑ものなので。</p>

<p><br />
<h4>審査中 18:00-</h4></p>

<p>周りの中間スコアを見ると、完走さえ出来れば上位には入れそうな感じだったので、なんとかベンチを完走して欲しいと願っておりました。1分完走率が8割だと、3分完走率は5分5分になってしまう。もっと成功率は高かったけど100％ではなかったので、やはり心配でした。</p>

<p>あとはプチ反省会。</p>

<ul>
<li>"/"はPOSTされるタイミングで更新されるわけだからキャッシュに乗せておけばよかった</li>
<li>@sugyanのサイドバーのキャッシュはフェールオーバーをやっていれば、使えたかも</li>
<li>そもそも、サイドバーの更新タイミングの違いの罠に気付くのが遅すぎた。それに早く気づいていたら違う手も打てた</li>
</ul>

<p></p>

<h4>審査結果発表 18:30-</h4>

<p>先に発表された準優勝のスコアが70,000万/3minとそこまで高くないスコアだったので、内心「これはうちは審査完走できなかったのかも...」とドキドキでした。</p>

<p>無事に完走を遂げたらしく、270,000 over/min のスコアで優勝できました。</p>

<p><img src="http://images.instagram.com/media/2011/08/27/71e9fdb423cf402caee336311ac3c3b0_6.jpg" alt="優勝トロフィー" /></p>

<h4>振り返って</h4>

<p>ホント素晴らしいイベントでした。@fujiwara組長の仕事ぶりを目の前で見られたのは本当に大きな経験になりました。</p>

<p>懇親会での会話もめちゃくちゃ盛り上がりました。トークイベントとはまた違って、全員が同じ事をやっているので、話が弾む弾む。</p>

<p>話を聞くと、言いだしっぺの @tagomorisさんが、やりたいなーみたいなことを言い出したら、どんどん話が進んで、トロフィーまで準備されるという。エンジニアドリブンであれだけのイベントをあれだけのリソースを使って開催できるのはマジすごいと思いました。見習いたい。</p>

<p>あと、@tagomorisさんと自転車の話ができてよかったです。今度走りに行きましょう。</p>]]>
    </content>
</entry>

<entry>
    <title>悪いけど正しいかもしれないPHPerになるための10個のTips</title>
    <link rel="alternate" type="text/html" href="http://www.songmu.jp/riji/archives/2011/03/phper10tips.html" />
    <id>tag:www.songmu.jp,2011:/riji//2.524</id>

    <published>2011-03-27T14:22:09Z</published>
    <updated>2011-03-27T14:34:18Z</updated>

    <summary>流行っているみたいなので書いてみた。かなり独断と偏見に満ちたエントリになっていま...</summary>
    <author>
        <name>Songmu</name>
        <uri>http://songmu.jp/</uri>
    </author>
    
        <category term="コンピュータ" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.songmu.jp/riji/">
        <![CDATA[<p>流行っているみたいなので書いてみた。かなり独断と偏見に満ちたエントリになっています。決定的な間違いがあったらブクマコメ等で指摘願います。</p>]]>
        <![CDATA[<p>さて、そもそもPHPとはなんのための言語か。HTMLの延長線上で使える学習コストの低いテンプレート言語であり、多少汚くても良いから、Webアプリケーションを手っ取り早く作るための言語です。</p>

<p>色々なユーザーの声をやたらめったら取り込んでしまったせいで、日本の家電みたいに無駄かつ一貫性のない機能が満載で醜悪なことになっていますが、その辺は気にしないことにしましょう。</p>

<p>ただ、変に多方面の声を取り込んでしまったせいで、妙にお行儀よくなりたがっている部分も多く、使いづらくなっている部分も多々あったりして困りものですが。</p>

<p>まあ、つまりPHPにおいて「良い」ってのはありえないんですよ。とか言ってみたりして。</p>

<p>閑話休題。</p>

<h4>エラーレベルは最大にしろ</h4>

<p>色々コードが書きづらくなる部分もありますが、逆にお行儀がよくなり分かりやすくなる部分も出てきます。また、前方互換も考えると、最大限有効にしておくのが賢明でしょう。</p>

<p>PHP.iniに以下のように書くのが理想です。</p>

<pre><code>error_reporting = E_ALL | E_STRICT</code></pre>

<p>PHP.iniを触れない場合、スクリプト内に以下のように書くこともできます。</p>

<pre><code>error_reporting( E_ALL | E_STRICT )</code></pre>

<p>ただ、この場合、コンパイルレベルでのエラーを一部出力してくれなくなるので残念です。</p>

<p>.htaccessに書くこともできますが、その場合は定数を使えず、即値を使わないといけないので、一長一短ですね。</p>

<p>あと、PHP4と互換性のあるモジュール(MDB2とか)なんかを使うときにエラーがたくさん出て困ることになりますね。このあたりどうすれば良いんでしょうね。</p>

<p>エラーレベルを動的に変更できないところがPHPの辛いところ。</p>

<p><br />
<h4>文字コードはUTF-8一択</h4></p>

<p>理由は色々ありますが、大きな理由としてはマルチバイト文字を扱うときにUTF-8じゃないとpreg系の関数が正しく動かないことです。</p>

<p>mb_regex_encodingを適正に設定して、mb_ereg系を使うという手もありますが、mb_ereg系では、各種正規表現修飾子が使えないのが痛い。特にx修飾子が使えないのが致命的。</p>

<p><br />
<h4>正規表現はpreg系を使い、x修飾子を積極的に使いましょう</h4></p>

<p>x修飾子超便利。</p>

<p><br />
<h4>変数名には「意味」を持たせる。型は持たせない</h4></p>

<p>型は意味ではない。変数の型付けに拘るのは静的型付け言語の考え方であり、動的型付け言語は無意味。</p>

<p>例えば、my_ageだったらintegerに決まっている。それをiMyAgeなんて変数にするのはナンセンス。</p>

<p>それに、追加開発時にmy_ageはintegerではなくて、ageクラスのインスタンスに仕様変更されるかもしれない。そういう自由さを動的型付け言語は持っている。そうなったときに、変数名がiMyAgeのままだったら目も当てられない。</p>

<p>ただ、同じ変数の型がプログラムの中でコロコロ変わるなんてのは分かりづらいのでやってはいけません。これは、次の「真理値を返すのは真理値を返すメソッドのみにする」でも触れます。</p>

<p>それと、キャメルケースは案外読みづらい。変数名はアンスコ区切りが良いんじゃないかと思う。</p>

<p><br />
<h4>真理値を返すのは真理値を返すメソッドのみにする</h4></p>

<p>PHPは動的型付けなので、メソッドの途中で失敗したらfalseを返すみたいなこともやってしまいがち。</p>

<p>しかし、正しくはメソッドの戻り値の型は固定にして、メソッドの途中で失敗したら例外を投げるべき。falseを返すような実装にしてはいけない。呼び出し元でイチイチ戻り値をチェックしないといけなくなり、コードの見通しが悪くなります。</p>

<p>メソッドが真理値を返すのは、そもそも、is*とかcan*とかtrueかfalseを判定するメソッドに限るべきです。</p>

<p><br />
<h4>var_dumpとかアドホックな出力に頼るな</h4></p>

<p>たしかに<code>var_dump</code>は便利だ。ただ、デバッグ値を画面に出力するだなんてのはあまりにもダサい。そんなことだから、PHPerがバカにされるのだ。</p>

<p>var_dumpの内容はデバッグログに吐くべきだ。それには多少工夫が必要になる。以下のような感じだ。</p>

<pre><code>function d(){
    ob_start();
    ob_implicit_flush(0);
    $args = func_get_args();
    call_user_func_array('var_dump', $args);
    $str = ob_get_clean();
    return $str;
}</code></pre>

<p>出力ストリームをトラップして、戻り値として返すようになっている。var_dumpは可変長引数をとるのでそれも受け付けるようにしてある。</p>

<p>上記関数を以下のようにロガーに渡して、ログファイルをtail -f で見ろ。そうすれば変数の変化なんかも追うことができる。</p>

<pre><code>$logger->debug(d($obj));</code></pre>

<p><br />
<h4>三項演算子はネストしない</h4></p>

<p>三項演算子は便利だがPHPだと連結順がおかしいのでネストしない。括弧で囲んで頑張ってネストさせる手もあるが、そこまで頑張らなくてもよいでしょう。</p>

<p>switch文が便利なこともありますが、例によって「緩やかな比較」なので注意。</p>

<p>ちなみに、PHP5.3以降は<code>?:</code>演算子も使えるのでちょっと便利。</p>

<p><br />
<h4><code>$_GET</code>と<code>$_POST</code>を使え</h4></p>

<p><code>$_REQUEST</code>を使うのはもちろん論外だが、<code>$_GET</code>と<code>$_POST</code>をイチイチちょっとしたクラスでラップする必要性も感じない。ユーザーの入力値を使いやすい形で提供してくれているのだから使うべきだ。</p>

<p>もし、オブジェクト化したら、キーをなめるような処理が欲しくなった時にkeysみたいなメソッドを生やさなくてはいけなくなるような不自由さが発生するし、そもそもアプリケーションがWebからの入力を前提とした作りになってしまう。</p>

<p>上手くクラスを利用するとしたら、バリデーターオブジェクトをつくってそれに<code>$_POST</code>を喰わせるとか、フォームオブジェクトを準備しておいてリクエストに対して自動で<code>$_POST</code>の中身をバリデーションするとか、そんな時でしょう。その場合も、<code>$_GET</code>, <code>$_POST</code>自体をラップしておく必要はありません。</p>

<p>そして、ちょっとしたアプリケーションであれば、生の<code>$_GET</code>, <code>$_POST</code>で困ることは少ないのです。</p>

<p>ただ、<code>$_GET</code>, <code>$_POST</code>, <code>$_COOKIE</code>あたりを事前に<code>mb_check_encoding</code>を通して、不正な入力値が与えられていないかはフレームワーク側で担保しておいたほうが良いでしょう。</p>

<p><br />
<h4>設定ファイルはアプリケーション設定ファイルと環境設定ファイルの2種類持て</h4></p>

<p>最近は、アプリケーションの設定をする設定ファイルと、環境情報を記載した設定ファイルの2種類を準備したほうが良いんじゃないかと思い始めている。</p>

<p>そして、環境情報ファイルは本番と開発用で分けておくが、アプリケーション設定ファイルは本番と開発用で共通して使えるものにしておく。</p>

<p>アプリケーション設定ファイルが肥大化してきたら、一部の設定値や定数群をモデルクラスにアサインした方がよくなってくるでしょう。もちろんモデルだからといって、ストレージはDBとは限りません。</p>

<p><br />
<h4>short_open_tagを有効にし、テンプレート内では&lt;? ?&gt;を使え</h4></p>

<p>最後に超独断の爆弾。</p>

<p>個人的にはコントローラやモデルは&lt;?php で書き始め ?&gt;で閉じないように書いていますが、テンプレートでは&lt;? ?&gt;を使うのが好きです。</p>

<p>short_open_tagをoffにして、テンプレート言語としてのメリットを捨ててまで、PHPみたいな(censored)な言語を使う理由を全く感じません。</p>

<p>よく言われるのが、XML宣言云々ですが、そこだけechoで書けばよいだけの話です。なんでそこでechoを使わないためだけに、他のところでechoを使わないといけないのか意味がわかりません。</p>

<p>あと「他の環境に持って行っても動くように」なんて話もありますが、それも.htaccessに書けば良いだけなんでないの、とか思ったり。</p>

<p>理想を言えば、最近のトレンドからして、&lt;?= ?&gt;で囲まれた部分はオートエスケープされるようにPHP側で良きに計らってくれるようになってくれれば良いな、と思う。もちろん後方互換を考えてPHP側でなんらかの環境設定フラグを準備してもらう必要はあるでしょう。またPHPにフラグが増えることになりますが。</p>]]>
    </content>
</entry>

<entry>
    <title>面白法人カヤックで働いています</title>
    <link rel="alternate" type="text/html" href="http://www.songmu.jp/riji/archives/2011/03/post_377.html" />
    <id>tag:www.songmu.jp,2011:/riji//2.523</id>

    <published>2011-03-21T15:11:06Z</published>
    <updated>2011-03-21T15:18:47Z</updated>

    <summary>ご存知のとおり1月からカヤックで働いています。なんとなく会社にも慣れてきたので、...</summary>
    <author>
        <name>Songmu</name>
        <uri>http://songmu.jp/</uri>
    </author>
    
        <category term="雑記" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.songmu.jp/riji/">
        <![CDATA[<p>ご存知のとおり1月から<a href="http://www.kayac.com/" target="_blank">カヤック</a>で働いています。なんとなく会社にも慣れてきたので、その辺の報告等を。</p>

<p>業務としては現状、ソーシャルゲームのサーバーサイドの開発をしています。毎日Perlを書けるので非常にハッピーです。でももっとバリバリ新しいことも出来るようになりたいですね。</p>]]>
        <![CDATA[<p>入社した頃は、エンジニアのほとんどがMac Book ProにHHKBとドデカイディスプレイをつなげてザザーっと開発しているのを見て、覚悟はしていたけど、とんでもないところに来てしまったなと思ったものです。</p>

<p>自分がマウスとGUIに頼りっきりのゆとりだったことを改めて思い知りましたが、なんとかシェルとvimでひと通り開発できています。vimとかzshはもっと使いこなしたいですけどね。gitを本格的にコマンドラインで使うのもブランチを切ったりするのも初めて(!)でしたが、今やgitが無いと生きていけませんね。</p>

<p>社員も増えていて、同じ時期に入った人たちが凄い人ばかりで、存在感を示していて、非常に刺激を受けています。</p>

<p>社員は皆真面目です。ネタと思われてしまうことも多いのですが、そこも含めて真剣に働いています。真面目に稼ごうとしているし、会社として生き抜こうとしているし、実際生き残っている。形だけの真面目さが無い分、それ以上の真剣さが求められます。</p>

<p>その辺り誤解されている部分があって、損している部分もあるかなと思うのですが、今のスタンスを貫きながら世の中に認知され理解されていくしかないんだろうなと思います。実際待遇も悪くないし、良い会社だと思います。忙しくしている人が多いのは事実ですが、多くの人は納得して仕事をしています。</p>

<p>あとは、CPAN Authorを増やしたいですね。社内でCPAN Authorを増やしていくのもありますし、CPAN Authorの人たちもWelcomeです。一緒に働きましょう！<br />
</p>]]>
    </content>
</entry>

<entry>
    <title>東北関東大震災</title>
    <link rel="alternate" type="text/html" href="http://www.songmu.jp/riji/archives/2011/03/post_376.html" />
    <id>tag:www.songmu.jp,2011:/riji//2.522</id>

    <published>2011-03-21T14:51:33Z</published>
    <updated>2011-03-21T14:52:34Z</updated>

    <summary>被災地の方々には心よりお見舞い申し上げます。 ウチは幸い家族も実家も無事で、被害...</summary>
    <author>
        <name>Songmu</name>
        <uri>http://songmu.jp/</uri>
    </author>
    
        <category term="雑記" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.songmu.jp/riji/">
        <![CDATA[<p>被災地の方々には心よりお見舞い申し上げます。</p>

<p>ウチは幸い家族も実家も無事で、被害としては、皿が2割程度割れ、コンポが一部破損し、本が多少グシャグシャになったのと、パソコンが一台壊れたくらいです。</p>]]>
        <![CDATA[<p>当日は鎌倉で勤務中でしたが、その場で解散。嫁と連絡が全然つかなかったので、とりあえず帰ることにしました。電車もタクシーも全然動きそうになかったので、こりゃ歩くしか無いなと即断して、鎌倉から自宅まで45km歩いて帰宅しました。日頃から体力を培っている分、その辺迷いなく決められるのはアドバンテージだと思いましたね。</p>

<p>とはいえ、最後のほうで迷って、3kmくらい逆方向に進んでいて心が折れかけましたが、なんとか帰宅しました。嫁とは帰宅途中にmixiでなんとか連絡がついてかなり安心した。あと、iPhoneとGoogleマップが無かったら帰れなかったと思うので、ネットの力すごい(笑)</p>

<p>家は物が散乱していて大変だったみたいですが、先に帰宅した嫁とお隣さん(!)が片付けてくれたようで、帰宅したらだいぶ片付いておりました。近所付き合い大事。</p>

<p>阪神淡路大震災の時と違うのは、もちろんあの時以上の被害が大きく関東にも影響があることもありますが、あの頃の自分とは格段に交友関係が広がっているので、東北出身者が身の回りにたくさんいるということ。だから、どこか個人的には他人ごとだった阪神淡路の時に比べて、他人ごととは思えず、なかなか心の整理が難しい部分がありますね。</p>

<p>とはいえ、自分ができることや気が回せることの範囲はそう簡単に広がるものでもないので、ネガティブな影響を受けすぎず、いつもどおり出来ることをするということは変わりませんね。被災地に大して出来ることは寄付をすることくらいでしょうか。サクっと赤十字にネット送金をしておきました。</p>

<p>そういえば、ウチにはテレビがなかったのですが、ちょうど仕事の都合でガラケーを契約したばかりでワンセグがスゲー役立ちました。</p>

<p>凄惨な被災地の状況に心を痛める部分もありますが、逆に愛する人と過ごす週末の尊さをいつも以上に噛み締めることも出来ました。まあ、前向きに生きて行くしかありません。</p>]]>
    </content>
</entry>

<entry>
    <title>Kamakura.pm Tech Talk #1でSpiritual Talk(?)をしてきました</title>
    <link rel="alternate" type="text/html" href="http://www.songmu.jp/riji/archives/2011/02/kamakurapm_tech.html" />
    <id>tag:www.songmu.jp,2011:/riji//2.521</id>

    <published>2011-02-02T15:53:59Z</published>
    <updated>2011-02-02T16:05:53Z</updated>

    <summary>先週の金曜日にKamakura.pmで話してきました。Tech Talkというよ...</summary>
    <author>
        <name>Songmu</name>
        <uri>http://songmu.jp/</uri>
    </author>
    
        <category term="コンピュータ" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.songmu.jp/riji/">
        <![CDATA[<p>先週の金曜日にKamakura.pmで話してきました。Tech Talkというよりかは思想的な話でした。まあ、Tech Talkは他の方におまかせという感じで。</p>

<p>yusukebeにスピリチュアルとかやたら言われましたが、割と反応をいただけたようでよかったです。モダンPerlの裏側で有名なkoba04さんも丁度いらしていて、僕も割とモダンPerlの裏側に居た人間なので、お話ができて良かったです。</p>]]>
        <![CDATA[<p>スライドは以下。</p>

<p><a href="http://www.songmu.jp/riji/etc/kamakurapm1/slide.html">Perlの地位を上げる方法</a></p>

<p>基本的には、Perlって必須スキルだよね、誤解されてるよね、どうすればユーザーを増やせるんだろうとか、前の会社での経験も踏まえて話した感じです。</p>

<p>そういやスライドにちょろっと書いているように、今年から面白法人カヤックで楽しく働いています。その辺の話はまたそのうち。</p>

<p>PerlがロードレーサーでPHPがクロスバイクって話は個人的にはナイス例えだったんだけど、一部にしか伝わらなくてやや残念。</p>

<p>エクササイズ目的で自転車買う人って、ロードバイクには抵抗があるから、まずクロスバイクからって人が多いんだけど、そこでロードバイクをゴリ押しで薦めてしまうと、自転車自体に乗ってもらえなかったし、しぶしぶロードを買ったとしても、あまりハマってもらえなかったりする。</p>

<p>逆にクロスバイク買ってしまった人がたくさん乗るようになると、物足りなくなってきて、結局ロードを買ってしまう人が多々いますというお話でした。</p>

<p>実際、プログラミングとロードレーサーって似てる部分があると思っていて、割と簡単に「俺スゲー感」を味わえるんだけど(40km/hを自力で簡単に捻り出せる快感！)、よくよく見てみるとその「俺スゲー感」のレベルって大したことなくて、上を見たらキリがない所とか。まだまだイケると思ってしまい終わりがないところとか。</p>

<p>二次会でも指摘されたんだけど、丁度、プログラミング言語の比較ってのがホッテントリ入りしていて、奇しくもタイムリーな話題でありました。まあ、あのエントリーは良エントリーですよね。公平に書いてあると思う。Perlはもう少し評価して欲しかったけど。</p>

<p>僕以外のTalkはTech Talkに相応しい内容で、yusukebeのBlog Hacks 2011は流石の内容で、nekokakuさんのTengの話を聞けたのは非常に良かったし、fujiwaraさんのSys::Vertの話はVM使っているのでかなり参考になりました。</p>

<p>二次会では、yusukebeと</p>

<ul>
<li>tokuhiromのコードは面白いし参考になる</li>
<li>海外のPerlモジュールはマッチョでなんか違うよね</li>
<li>だから日本から発信していかないといけないね</li>
</ul>

<p>みたいな話をした。</p>]]>
    </content>
</entry>

<entry>
    <title>なぜ安定を捨てて転職するに至ったのかとか</title>
    <link rel="alternate" type="text/html" href="http://www.songmu.jp/riji/archives/2010/12/post_375.html" />
    <id>tag:www.songmu.jp,2010:/riji//2.520</id>

    <published>2010-12-31T12:37:11Z</published>
    <updated>2010-12-31T14:15:56Z</updated>

    <summary>社会人を何年かやってきて、大分会社に対しての考え方も変わってきたのその辺の話を書...</summary>
    <author>
        <name>Songmu</name>
        <uri>http://songmu.jp/</uri>
    </author>
    
        <category term="雑記" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.songmu.jp/riji/">
        <![CDATA[<p>社会人を何年かやってきて、大分会社に対しての考え方も変わってきたのその辺の話を書き留めておく。</p>]]>
        <![CDATA[<p>大学生の時は安定志向だと自認していたので、極端な話、年功序列万歳で会社に守ってもらえれば良いやとか甘く考えていました。仕事はそこそこに趣味に生きるつもりで、公務員になることも考えていました。とりあえず、何がやりたいか分からなかったけど、どんな仕事でも楽しめると思ったし、卒なくこなす事はできるだろうと思ったので。</p>

<p>で結局就職活動に失敗して、その後なかなか安定収入が得られず苦労したので、職に困らず、食いっぱぐれないしっかりしたスキルを身に付けたいと思うようになった部分があります。</p>

<p>それで、紆余曲折を経ていざ念願の守ってもらえるような会社に雇用されると、不安で仕方がなかった(笑) 今の会社が潰れたとしても生きていけるかがわからないから。たとえ潰れる心配は無いにしても。</p>

<p>就活の失敗体験があるから食いっぱぐれる恐怖がどこかにあるわけですよ。会社とか関係ない確固たるスキルを身に付けたいってのがやっぱ強い。絶対に食いっぱぐれない武器が欲しいんですよね。</p>

<p>また、会社に過剰に期待していると、些細なことで裏切られたと感じやすくなるし、その結果愚痴っぽくなってしまう。これは人間関係も同じですね。</p>

<p>それに、前の転職のときも思ったんだけど「いつでも他の場所に行ける」くらいの余裕があったほうが、余裕をもってクオリティの高い仕事が出来るように思います。</p>

<p>だから終身雇用とかアテにせず、自分の力で生きていこうと。結局そんなあやふやなものに頼るよりかは自分を頼りにしたほうがよっぽど安心だな、と。すごく当たり前のことに行き着いたわけです。</p>

<p>てことで、会社に頼らない・しがみつかないのは大事ですよ。</p>

<p>絶対起業とかしないとか思ってたけど、まあ、なんだかんだでそのうち起業しちゃったりするかもしれませんね。だって、また転職するだなんて思ってなかったんだから。</p>]]>
    </content>
</entry>

<entry>
    <title>今年のJPerl Advent Calendarとか</title>
    <link rel="alternate" type="text/html" href="http://www.songmu.jp/riji/archives/2010/12/jperl_advent_ca_1.html" />
    <id>tag:www.songmu.jp,2010:/riji//2.519</id>

    <published>2010-12-31T12:32:22Z</published>
    <updated>2010-12-31T12:33:10Z</updated>

    <summary>少し前の話になりますが、去年も一記事書いたのですが、今年は調子に乗って3記事書き...</summary>
    <author>
        <name>Songmu</name>
        <uri>http://songmu.jp/</uri>
    </author>
    
        <category term="コンピュータ" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.songmu.jp/riji/">
        <![CDATA[<p>少し前の話になりますが、去年も<a href="http://perl-users.jp/articles/advent-calendar/2009/casual/15.html" target="_blank">一記事書いた</a>のですが、今年は調子に乗って3記事書きました。</p>]]>
        <![CDATA[<ul>
<li><a href="http://perl-users.jp/articles/advent-calendar/2010/win32/6" target="_blank">CPANモジュールをWindowsのみで作成する方法</a></li>
<li><a href="http://perl-users.jp/articles/advent-calendar/2010/win32/23" target="_blank">Encode::EUCJPMSで楽々日本語処理(ただしWindowsに限る)</a></li>
<li><a href="http://perl-users.jp/articles/advent-calendar/2010/casual/25" target="_blank">String::Randomでランダム文字列を作成してニヤニヤする</a></li>
</ul>

<p>ブログは全然更新してないのにね。</p>

<p>ところでAdventと言えばシュトーレンですが、Twitterで@<a href="http://twitter.com/neotag" target="_blank">neotag</a>と絡んでいたら、今更急にシュトーレン作りたい欲求が高まっています。それだけ。</p>]]>
    </content>
</entry>

<entry>
    <title>退社と転職と</title>
    <link rel="alternate" type="text/html" href="http://www.songmu.jp/riji/archives/2010/12/post_374.html" />
    <id>tag:www.songmu.jp,2010:/riji//2.518</id>

    <published>2010-12-28T14:43:25Z</published>
    <updated>2010-12-28T15:46:53Z</updated>

    <summary>前のエントリーで社内フレームワークとか言っておきながら、今日が仕事納めで今年いっ...</summary>
    <author>
        <name>Songmu</name>
        <uri>http://songmu.jp/</uri>
    </author>
    
        <category term="雑記" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.songmu.jp/riji/">
        <![CDATA[<p>前のエントリーで社内フレームワークとか言っておきながら、今日が仕事納めで今年いっぱいで現在の職場を退職となりました。</p>]]>
        <![CDATA[<p>今年の頭には転職とか殆ど考えていなかったのですが、今の会社だとなかなか技術的にスキルアップが難しく、自分も技術的にもうちょっとチャレンジしたいなぁということで、新たなステージを選んだ次第です。退職を考え出したのが6月くらいで8月から活動開始。10月に内定が出て、年内退社の運びとなりました。</p>

<p>今の会社は安定しているし、恐らく一生勤めることも可能なので、周りの友人や前職の友人からは「勿体無い」とか「何で？」とか言われます。私としてもチャレンジだと言うことは分かっているのですが、年齢も30になってしまったので、今後そうそうチャレンジできる機会も少なくなってくるだろうと言うことで転職に踏み切ることにしました。</p>

<p>正直、ここ2年は技術的に学べる人が誰もおらず、逆に私が一番知識的にあるということになっていて非常にストレスでした。自分のエンジニアとしての価値を計るためにこの業界に入ったにも関わらず、結局その辺りが未だにはっきりしていないという。生産金額として残した数字的にはダントツでしたが、たいしたことはやっていないので、中身が伴わず空虚な感じです。それで技術の分からない上司に妙に評価されるのもストレスでした。</p>

<p>もっともっと自分よりも優秀な人達と一緒に刺激を受けながらレベルアップしていきたい、そういう中で自分の実力を把握したいという思いが強く、また、このまま中身の伴わないマネージメント職に回されていく未来にゾッとした部分もあります。</p>

<p>今の会社の中で自分一人で周りを巻き込みながら成長していったとしても、他の自社サービスをやっているようなエンジニアにどんどん差をつけられていくのがわかってすごく歯がゆいものを感じていました。</p>

<p>そこで、自分の選択肢としては、頑張って会社を変えてくように努力するか、転職するかだった訳ですが、そこに気づくのが遅かったと言うことと、年齢的な部分もあり、後者を選んだということです。</p>

<p>今回、転職活動をしたときはなかなか結果が出ず、泣きたくなるくらい非常に悔しい思いをしました。前回転職活動をしたときもそういう気持ちになったはずなのですが、それを忘れていました。結局ここ2年間まったく成長が出来ていないことに愕然としました。</p>

<p>自分は我儘なことはわかっている。でもハッカーになりたい。2年前の転職のときに思っていたその熱い気持ちを忘れていました。</p>

<p>Webで生きていこうと決めたのが2年前で、そう決めるまでに自分は非常に回り道をしたと思います。でも、回り道をしてきた事を間違っていたとは思いたくないし、回り道をしてきたからこそ僕は肥沃だと信じたい。そういう意地があります。ああ、すごく恥ずかしいこと書いてますね。</p>

<p>だからこそ自分が成長できるステージってことで、大企業病のSIerではなく、自社サービス系の企業でチャレンジしてみようと思い次の職場を決めました。</p>

<p>次の職場は、チャレンジできる機会も多そうで、何より目標と出来るエンジニアもいるので、しっかりやろうと思います。</p>

<p>かなりネガティブサイドの話をすると、今の会社は社員に手厚いので、しがみついている人が残りやすく、若くて出来る人が割りを食らい、そういう人から辞めていくという悪循環がありました。</p>

<p>僕は共産主義者で年功序列万歳なので(嘘)、能力が違えど給与がある程度横並びなのは別に構わないと思うんですよ。そういう会社は別にあっても良いと思うんですね。だって能力の差なんてある程度生まれつきなんだから、それで生きる生きられないくらいの給与の差をつけられちゃたまらないでしょう。最低限を保証して、かつ、上積みで差をつけるんなら構わないと思うけど。</p>

<p>でも、出来る人が死ぬほど残業して、出来ない人はむしろ居るのが邪魔だから定時であがってもらってみたいな状況が常態化しているのはいくらなんでもヒドイなと。しかも出来る人が残業しているのは、出来ない人が下手に動いてしまって、被害を出したときだったりするわけです。上のマネージメントの問題もあるわけですが。</p>

<p>あと、エンジニア業界は、スポーツ選手に近い部分があって、人によって効率が劇的に違うし、プライベートと仕事の差が付けにくい、日々のトレーニングで差がつくわけですよ。だからちょっと普通の給与体系が則さない部分てのはありますよね。色々難しいですね。</p>

<p>ということでまとまってませんが、待遇とかに関しても色々思う部分も有りました。</p>

<p>ただ、今の職場には給与面では全く不満は無く、転職したらむしろ下がることも覚悟していたのですが、結果的にはそこそこ上がることになり、身の引き締まる思いです。</p>

<p>だから実際ソーシャル系は今バブルなんだと思いますよ。だからこそ弾けたときに生き残れるかどうかってところは覚悟してないといけないと思うし、そういったところで戦って行こうという決心はしました。</p>

<p>今の会社を辞めるに当たっては、残せるものは残していきたいなぁということもあり、スキルトランスファーとか非公式社内勉強会とかをちょこちょこやりました。社内フレームワークを作ったのもその一環だったりします。非公式社内勉強会はもっとやっておけば良かったなぁとか思いました。</p>

<p>Yapafiの<a href="http://www.songmu.jp/yapafi/column.html">技術コラム</a>が妙に充実してるのもそのせいです。</p>

<p>ところで、今年から本社グループの再編成があり、その関係で本社の人とも仕事をする機会が増えたのですが、本社出身の人はやはり優秀な人が多く、その辺は刺激を受けたんですが、退職を翻意させるまでには至りませんでした。</p>

<p>てことで、来年から心を新たに頑張ります。勝負できるステージで勝負してやろうと思います。</p>]]>
    </content>
</entry>

<entry>
    <title>YapafiっていうPHPフレームワーク書いた</title>
    <link rel="alternate" type="text/html" href="http://www.songmu.jp/riji/archives/2010/12/yapafiphp.html" />
    <id>tag:www.songmu.jp,2010:/riji//2.517</id>

    <published>2010-12-27T14:41:21Z</published>
    <updated>2010-12-27T16:42:17Z</updated>

    <summary>ここのところPHPのフレームワークを書いていて、ひと段落ついたので公開します。名...</summary>
    <author>
        <name>Songmu</name>
        <uri>http://songmu.jp/</uri>
    </author>
    
        <category term="コンピュータ" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.songmu.jp/riji/">
        <![CDATA[<p>ここのところPHPのフレームワークを書いていて、ひと段落ついたので公開します。名前は完全にYacafiインスパイアです、ごめんなさい。</p>

<ul>
<li><a href="http://www.songmu.jp/yapafi/">http://www.songmu.jp/yapafi/</a></li>
<li><a href="http://www.github.com/Songmu/yapafi">http://www.github.com/Songmu/yapafi</a></li>
</ul>]]>
        <![CDATA[<p>社内フレームワークとして使われることを期待して作ったものです。</p>

<p>「社内フレームワークとかダサッ」</p>

<p>とか言う声が聞こえてきそうなのですが、まあ、WAF作りはWebプログラマーのはしかの一つといわれるくらいですから。</p>

<p>実際のところ、社内でそこそこ実績のある社内フレームワークがいくつか有り、ただ、それらがいい加減古い設計になっていたり、今からするといけていない点があったりしつつ、なかなか移行が進まないと言う問題があったので、その辺りの刷新を狙って作りました。</p>

<p>まあ何で作ったかとかは、公開ページに書いてあります。</p>

<p>基本的にはワンファイルで動き、WAF自体が提供するのはディスパッチ機能くらいな感じの薄いフレームワークとなっています。コードジェネレータとか難しいこともやらない感じです。</p>

<p>あと、単独でFormValidator.phpってのを作ったのですが、これが結構いけてるんじゃないかと思っています。ただ、まだドキュメンテーションできていません...。</p>

<p>チュートリアルとサンプルを見れば大体どんな感じかは分かると思います。</p>

<ul>
<li><a href="http://www.songmu.jp/yapafi/tutorial">http://www.songmu.jp/yapafi/tutorial</a></li>
<li><a href="http://www.songmu.jp/yapafi/sample">http://www.songmu.jp/yapafi/sample</a></li>
</ul>

<p>モジュールなんかの作りはかなりCPANモジュールからパクらせてもらっています。以下のモジュールはそんな感じですね。</p>

<ul>
<li>Mail_Address_MobileJp</li>
<li>Devel_BackTraceAsHTML</li>
<li>DataValidator</li>
<li>FormValidator</li>
</ul>

<p>PHPはPEARがイマイチ使いづらいので、集合知の部分はPerlに劣るなぁとか思いました。PEAR2に期待。</p>]]>
    </content>
</entry>

<entry>
    <title>モダンなPerlを「読む」上で覚えておくとよい構文 第2回「リストを理解すれば配列とハッシュをより活用できる」</title>
    <link rel="alternate" type="text/html" href="http://www.songmu.jp/riji/archives/2010/09/perl_2_1.html" />
    <id>tag:www.songmu.jp,2010:/riji//2.516</id>

    <published>2010-09-26T18:54:08Z</published>
    <updated>2010-09-26T19:07:16Z</updated>

    <summary>第1回から大分時間が空きましたが、なんと続きます。「次回は無名関数について書く」...</summary>
    <author>
        <name>Songmu</name>
        <uri>http://songmu.jp/</uri>
    </author>
    
        <category term="コンピュータ" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.songmu.jp/riji/">
        <![CDATA[<p>第1回から大分時間が空きましたが、なんと続きます。「次回は無名関数について書く」とか書いていましたが、先にリストについて言及することにします。</p>]]>
        <![CDATA[<p>混同されがちですがこのエントリーでは「リスト」と「配列」を厳密に違うものとして扱います。結論を先に簡単に言ってしまうと、<strong>リストを配列に代入すれば配列になるし、リストをハッシュに代入すればハッシュになる</strong>ということです。</p>

<h4>Perlの式は値を返す</h4>

<p>サブルーチンに限らずPerlのあらゆる式は評価された値を返します。返された値は代入先があれば代入され、代入先がなければ捨てられます。</p>

<div class="aside">
<h4>値を返さないケース</h4>
<p>ブロックは値を返しません(doを使えばブロックに値を返させることが出来ます)。例外的にuse文やpackage文は値を返しません。この二つはコンパイル時にコードを実行する前に最初に評価されるので値の返しようがありません。</p></div>

<p>さて、本題です。Perlの式の値の返し方には2種類あります。スカラーとリストです。スカラーを返すかリストを返すかはコンテキストに応じて変化することもあります。</p>

<p>リストコンテキストで返されるものがリスト(当たり前！)です。また、以下のようにすればリストを直に記述できます。</p>

<pre><code>(1, 2, 3, 'hoge');
qw/1 2 3 hoge/;</code></pre>

<p>「なんだ、配列じゃないか。」</p>

<p>いいえ、違います。そう思う人は以下のコードを実行してみて下さい。驚きの結果が得られることでしょう。</p>

<pre><code>use Data::Dumper;
my $hoge = \(1, 2, 3, 'hoge'); #配列をリファレンス化している...？
print Dumper $hoge;</code></pre>

<p>リストを配列リファレンスに代入したい場合は、リストをブラケットで囲めば配列リファレンスを返します。</p>

<pre><code>my $hoge = [1, 2, 3, 'hoge'];</code></pre>

<div class="aside">
<h4>リストはハッシュキーにもなれる(けど使う機会はまずない)</h4>
<p>以下のようなことも可能です。</p>
<pre><code>my %hash;
$hash{qw/1 2 3/} = 'hoge';
print $hash{qw/1 2 3/}; # hoge</code></pre>
<p>これはどういう事かというと、以下のコードを実行すれば分かります。</p>
<pre><code>my %hash;
$hash{qw/1 2 3/} = 'hoge';
my ($key) = keys %hash; #キーを取り出す。
$key =~ s/(.)/'\x'.unpack('H2', $1)/eg; #バイトごとに16進にエンコーディング
print $key; # \x31\x1c\x32\x1c\x33</code></pre>
<p>値が'\x1c'という文字で区切られていることが分かります。これは印字されない制御文字(FS)です。つまり印字されない文字を区切り文字に使った文字列(バイト列)がキーになっているという単純な仕掛けです。</p>
<p>なのでバイナリデータをハッシュキーにしたりすると上手くいかない可能性があります。</p>
<p>また、この区切り文字には特殊変数<code>$;</code>を使ってアクセスすることができます。</p>
<p>ややマニアックだけどかなりどうでも良いネタでした。</p>
</div>

<p>冒頭に書いたとおり、リストを配列に渡せば配列になり、ハッシュに渡せばハッシュになります。</p>

<div class="aside">前の記事でも書きましたが、ハッシュへの代入で使われる、"=>"(ファットコンマ)ってのは単なるカンマの代用であり、コードの可読性を上げるために使われています。ハッシュに渡されるのは単なるリストです。</div>

<pre><code>my @arr = (1, 2, 3, 'hoge');
print $arr[1]; # 2
my %hash = (1, 2, 3, 'hoge'); # (1 => 2, 3 => 'hoge') と同じ
print $hash{3}; # hoge</code></pre>

<p>配列はリストコンテキストで評価された場合リストを返します。ハッシュも同様にリストを返します。なので以下のようなことも可能です。</p>

<pre><code>my @arr = (1, 2, 3, 'hoge');
my %hash = @arr;
print $hash{3}; # hoge
@arr = %hash; # こんなことも可能。ハッシュの順番が保証されないので、普通はやらない</code></pre>

<p>これを利用して、名前付き引数的な関数を実現可能です。</p>

<pre><code>#カッコの中はリスト。ファットコンマは単に可読性のため。
func(
    hoge => 'fuga',
    piyo => 11,
);
sub func {
    #配列をハッシュに代入していて一見意味不明だが、配列がリストを
    #返し、それがハッシュにわたっていると考える。
    %hash = @_;
    if ($hash{hoge} ){ ... }
}</code></pre>

<p>また、以下のようにmapを組み合わせて、配列の各要素をキーとして、ハッシュを作成することが可能です。</p>

<pre><code>my @arr =  qw/hoge fuga piyo/;
%hash = map { $_ => 1 } @arr; #各要素を1で初期化
if($hash{hoge}){# @arr内に'hoge'が存在するかをチェックできる
...
}</code></pre>

<p>mapやgrepは難解に思えますが、リスト操作には欠かせません。トリッキーに思えることも多いかと思いますが、そのうち慣れてくるでしょう。ただ、やりすぎはいけません。</p>

<h4>リファレンス</h4>

<p>[]や{}を使って、配列/ハッシュリファレンスを作成することが出来ますが、内部に単なるリストではなく、<strong>リストを返す式を書くこと</strong>もできます。以下のような感じです。</p>

<pre><code>$arr_ref = [1,2,3]; # 普通の書き方
$arr_ref = [qw/hoge fuga piyo/]; # こんな書き方も
$arr_ref = [@arr]; # \@arr と実質同じだけど、こう書かれることも多い
$arr_ref = [split //, $str]; #文字列を一文字づつ切り出した結果を配列リファレンスに</code></pre>

<p>最後の式は少しびっくりするかもしれません。人によって多寡はありますが、これくらいだったら良く使われているように思います。mapやgrepがこの中で使われることもあります。例に因って自分で書くときはやりすぎは厳禁です。</p>

<p>また、オブジェクトのコンストラクタに引数を渡すときに、名前付き引数的な渡し方とハッシュリファレンスを渡すやりかたが両方可能になっている場合も結構あったりします。以下のような感じです。</p>

<pre><code>my $obj1 = Hoge->new( #名前付き引数的な渡し方
    hoge => 'fuga',
);
my $obj2 = Hoge->new({ #ハッシュリファレンスを渡す渡し方
    hoge => 'piyo',
});
package Hoge;
sub new{
    my $cls = shift;
    #渡されたのが、リスト(名前付き引数)か、ハッシュリファレンスか判別
    my $self =
        ref $_[0] eq 'HASH' ? shift : {@_};
    bless $self, cls;
}</pre></code>

<p><code>{@_}</code>という書き方が最初慣れないかも知れませんが「配列がリストとして展開されて、それがハッシュリファレンスになる」と考えれば理解可能でしょう。</p>

<h4>まとめ</h4>

<p>「何でここでは配列なのに、こっちではハッシュなんだ？」とか思ってしまうこともあるかもしれません。</p>

<p><strong>全てリストを介してつながっている</strong></p>

<p>と考えれば話は簡単です。この辺りのリストの扱いを理解してくると「PerlがLISPの影響を受けている」と言われる所以も分かってくるでしょう。</p>]]>
    </content>
</entry>

<entry>
    <title>Perlでフィボナッチ数列の高速化とか無名関数の再帰とか</title>
    <link rel="alternate" type="text/html" href="http://www.songmu.jp/riji/archives/2010/09/perl_3.html" />
    <id>tag:www.songmu.jp,2010:/riji//2.515</id>

    <published>2010-09-20T14:07:03Z</published>
    <updated>2010-09-20T14:14:39Z</updated>

    <summary>簡単にfibを高速化する方法を読み、おおっと思って、Perlでやってみた。...</summary>
    <author>
        <name>Songmu</name>
        <uri>http://songmu.jp/</uri>
    </author>
    
        <category term="コンピュータ" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.songmu.jp/riji/">
        <![CDATA[<p><a href="http://d.hatena.ne.jp/mrkn/20100906/easy_faster_fib">簡単にfibを高速化する方法</a>を読み、おおっと思って、Perlでやってみた。</p>]]>
        <![CDATA[<pre><code>#!/usr/bin/perl
use strict;
use warnings;
use feature qw/state/;
use Benchmark qw/timethese cmpthese/;
 
sub _fib_ret2 {
   my $n = shift;
   if ( $n == 1 ){
       (1,1);
   }
   else {
       my ( $aa, $bb ) = _fib_ret2($n-1);
       ($aa+$bb, $aa);
   }
}
sub fib_ret2 {
   (_fib_ret2(shift))[0];
}
 
sub fib_memo {
   state @cache;
   my $n = shift;
   $cache[$n] ||= $n &lt;= 1 ? 1 : fib_memo($n-2) + fib_memo($n-1);
}
 
sub fib_normal {
   my $n = shift;
   return 1 if $n &lt;= 1;
   return fib_normal($n-2) + fib_normal($n-1);
}
 
sub fib_no_recv { #まあ、これが一番速いのは分かってるんですよ。
   my $n = shift;
   return 1 if $n &lt;= 1;
   my ( $fib, $prev ) = (1,1);
   ( $fib, $prev ) = ( $fib+$prev, $fib ) for 2..$n;
   $fib;
}
 
my $fib_arg = 30;
cmpthese timethese 0, {
   fib_ret2    =&gt; sub { fib_ret2($fib_arg) },
   fib_memo    =&gt; sub { fib_memo($fib_arg) },
   fib_normal  =&gt; sub { fib_normal($fib_arg) },
   fib_no_recv =&gt; sub { fib_no_recv($fib_arg) },
};</code></pre>

<pre><samp>fib_memo:  3 wallclock secs ( 3.19 usr +  0.00 sys =  3.19 CPU) @ 1742548.96/s (n=5551761)
fib_no_recv:  3 wallclock secs ( 3.17 usr +  0.00 sys =  3.17 CPU) @ 66800.76/s (n=211892)
fib_normal:  3 wallclock secs ( 3.61 usr +  0.00 sys =  3.61 CPU) @  0.55/s (n=2)
fib_ret2:  3 wallclock secs ( 3.20 usr +  0.00 sys =  3.20 CPU) @ 28944.44/s (n=92738)
                 Rate  fib_normal    fib_ret2 fib_no_recv    fib_memo
fib_normal    0.554/s          --       -100%       -100%       -100%
fib_ret2      28944/s    5224372%          --        -57%        -98%
fib_no_recv   66801/s   12057437%        131%          --        -96%
fib_memo    1742549/s  314529988%       5920%       2509%          --</samp></pre>

<p>確かに速い。しかし、メモ化するよりかは遅い？いや、再帰なしのパターンよりか速いのはおかしくね？</p>

<p>違ぁう！そりゃそうだ。メモ化したやつは2回目の試行以降は、単なる配列のインデックスアクセスになっているので速いに決まっているのだ。つまり、実装としては正しいが、ベンチマークとしてはフェアじゃない。</p>

<p>てことで、ベンチマークの試行毎にメモの内容が初期化されて欲しい。しかし、stateが初期化された無名関数を返すにしても、無名関数を再帰する方法はPerlにはデフォルトで無いので、ダサいけど外部にメモを持たせるしかないかなぁと。</p>

<pre><code>#!/usr/bin/perl
use strict;
use warnings;
use Benchmark qw/timethese cmpthese/;
 
sub _fib_ret2 {
   my $n = shift;
   if ( $n == 1 ){
       (1,1);
   }
   else {
       my ( $aa, $bb ) = _fib_ret2($n-1);
       ($aa+$bb, $aa);
   }
}
sub fib_ret2 {
   (_fib_ret2(shift))[0];
}
 
my @memo;
sub fib_memo2 {
   my $n = shift;
   $memo[$n] ||= $n &lt;= 1 ? 1 : fib_memo2($n-2) + fib_memo2($n-1);
}
 
sub fib_no_recv {
   my $n = shift;
   return 1 if $n &lt;= 1;
   my ( $fib, $prev ) = (1,1);
   ( $fib, $prev ) = ( $fib+$prev, $fib ) for 2..$n;
   $fib;
}
 
my $arg = 50;
cmpthese timethese 0, {
   fib_ret2    =&gt; sub { fib_ret2($arg) },
   fib_memo    =&gt; sub { @memo=();fib_memo2($arg) },
   fib_no_recv =&gt; sub { fib_no_recv($arg) },
};</code></pre>

<pre><samp>fib_memo:  3 wallclock secs ( 3.22 usr +  0.02 sys =  3.23 CPU) @ 12827.77/s (n=41485)
fib_no_recv:  3 wallclock secs ( 3.14 usr +  0.02 sys =  3.16 CPU) @ 34344.42/s (n=108391)
fib_ret2:  4 wallclock secs ( 3.30 usr +  0.00 sys =  3.30 CPU) @ 17243.33/s (n=56834)
               Rate    fib_memo    fib_ret2 fib_no_recv
fib_memo    12828/s          --        -26%        -63%
fib_ret2    17243/s         34%          --        -50%
fib_no_recv 34344/s        168%         99%          --</samp></pre>

<p>確かに一回だけの計算だったら、二つ返すほうがメモ化よりも速いことが分かる。</p>

<p>理由を考えてみると、値を二つ返すパターンだと、単に実行コンテキストをスタックに詰んでいって戻ってくるのが一本道だと言うことが分かる。</p>

<p>メモ化のパターンだと関数内で関数が2回呼ばれるので、その分関数の呼び出し回数が指数的に増えていってしまうので、そこがネックになるのでしょう。</p>

<p>なるほど。考えた人すごい。</p>

<h4>おまけ</h4>

<p>無名関数の再帰が出来なくてスマートに記述できなかったのが悔しかったので、Sub::Recursiveを使って書き直してみた。Sub::Recursiveを使ったのは、<a href="http://blog.livedoor.jp/xaicron/archives/50759985.html" target="_blank">「Perlで無名関数再帰のベンチ」</a>で一番速いって書いてあったし、そこにあったベンチマークスクリプトを走らせても圧倒的にSub::Recursiveが速かったので。</p>

<pre><code>#!/usr/bin/perl
use strict;
use warnings;
use feature qw/state/;
use Benchmark qw/timethese cmpthese/;
use Sub::Recursive qw/$REC recursive/;
 
sub _fib_ret2 {
   my $n = shift;
   if ( $n == 1 ){
       (1,1);
   }
   else {
       my ( $aa, $bb ) = _fib_ret2($n-1);
       ($aa+$bb, $aa);
   }
}
sub fib_ret2 {
   (_fib_ret2(shift))[0];
}
 
sub fib_ret2_lambda{
   ((recursive {
       my $n = shift;
       if ( $n == 1 ){
           (1,1);
       }
       else {
           my ( $aa, $bb ) = $REC-&gt;($n-1);
           ($aa+$bb, $aa);
       }
   })-&gt;(shift))[0];
}
 
my @memo;
sub fib_memo2 {
   my $n = shift;
   $memo[$n] ||= $n &lt;= 1 ? 1 : fib_memo2($n-2) + fib_memo2($n-1);
}
 
sub fib_memo_lambda {
   recursive {
       state @cache;
       my $n = shift;
       $cache[$n] ||= $n &lt;= 1 ? 1 : $REC-&gt;($n-2) + $REC-&gt;($n-1);
   };
}
 
my $fib_arg = 50;
cmpthese timethese 0, {
   fib_ret2        =&gt; sub { fib_ret2($fib_arg) },
   fib_ret2_lambda =&gt; sub { fib_ret2_lambda($fib_arg) },
   fib_memo        =&gt; sub { @memo=();fib_memo2($fib_arg) },
   fib_memo_lambda =&gt; sub { fib_memo_lambda()-&gt;($fib_arg) },
};</code></pre>

<pre><samp>fib_memo:  4 wallclock secs ( 3.17 usr +  0.00 sys =  3.17 CPU) @ 13341.11/s (n=42318)
fib_memo_lambda:  3 wallclock secs ( 3.20 usr +  0.00 sys =  3.20 CPU) @ 6907.90/s (n=22126)
fib_ret2:  3 wallclock secs ( 3.22 usr +  0.00 sys =  3.22 CPU) @ 16680.96/s (n=53696)
fib_ret2_lambda:  3 wallclock secs ( 3.25 usr +  0.00 sys =  3.25 CPU) @ 15201.23/s (n=49404)
                   Rate fib_memo_lambda     fib_memo fib_ret2_lambda    fib_ret2
fib_memo_lambda  6908/s              --         -48%            -55%        -59%
fib_memo        13341/s             93%           --            -12%        -20%
fib_ret2_lambda 15201/s            120%          14%              --         -9%
fib_ret2        16681/s            141%          25%             10%          --</samp></pre>

<p>まあ、やっぱ余計なことしないほうが速いに決まってますよね。</p>]]>
    </content>
</entry>

</feed>

