<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Eorzea Lounge</title>
    <link rel="alternate" type="text/html" href="http://blog.eorzea.asia/" />
    <link rel="self" type="application/atom+xml" href="http://blog.eorzea.asia/atom.xml" />
    <id>tag:blog.eorzea.asia,2009-06-28://1</id>
    <updated>2010-02-23T03:49:39Z</updated>
    <subtitle>Eorzea System Works開発日誌 - FF14.nameとFF14.asiaの開発日誌です。</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type Pro 4.261</generator>

<entry>
    <title>人肌のPerl</title>
    <link rel="alternate" type="text/html" href="http://blog.eorzea.asia/2010/02/post_92.html" />
    <id>tag:blog.eorzea.asia,2010://1.92</id>

    <published>2010-02-21T00:38:52Z</published>
    <updated>2010-02-23T03:49:39Z</updated>

    <summary>「文法最速マスター」というタイムリーなネタに半ば悪のりしてしまいましたが、はてブ...</summary>
    <author>
        <name>Gardejo</name>
        
    </author>
    
        <category term="雑記" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="moosemouse" label="Moose/Mouse" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="Perl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://blog.eorzea.asia/">
        <![CDATA[<p>「文法最速マスター」というタイムリーなネタに半ば悪のりしてしまいましたが、<a href="http://b.hatena.ne.jp/entry/perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html">はてブ</a>や<a href="http://clip.livedoor.com/page/http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html">Livedoorクリップ</a>などで拙稿の「<a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html">Moose &amp; Mouse基本文法最速マスター/The Fastest Way to Mastering Moose &amp; Mouse</a>」が先週末にホッテントリ入りしたようです。ご覧いただきましてどうもありがとうございます。</p>

<p>日本ではYAPC::Asia 2008などが契機となったのか、2008年の半ばにMoooooooooooooooooooose!の潮流が大きく促進されました。そして2010年の現在、<a href="http://search.cpan.org/perldoc?Moose"><code>Moose</code></a>はもうPerlハッカーの方々だけのものではなく、私のような一般のPerlユーザーにもとても近い存在になっています。そうした土壌があることも、奏功した一因かと考えています。</p>

<p>思い返せば、私が<code>Moose</code>を触り始めたのは2008年の後半でした。2009年2月に出た<a href="http://mt.endeworks.jp/d-6/">lestrratさん</a>の『<a href="http://www.amazon.co.jp/dp/4798119172">モダンPerl入門</a>』には大いに感銘を受けました。5月には2万行くらいの私的な開発案件に投入して、その威力を再確認しました。7月に<a href="http://github.com/jpa">GitHubのJPAリポジトリ</a>にpushされた<a href="http://d.hatena.ne.jp/charsbar/">charsbarさん</a>による<a href="http://github.com/jpa/Moose-Doc-JA"><code>Moose::Manual</code>と<code>Moose::Cookbook</code>の邦訳版</a>は、<a href="http://perldoc.perlassociation.org/pod/Moose-Doc-JA/">JPAのドキュメント和訳プロジェクトでの公開</a>を待たずして、<a href="http://blog.perlassociation.org/2009/07/perldoc-in-japanese.html">JPAの発表</a>を知ったその日にPODをHTML化して印刷し、当初から印刷していた原語版共々愛読しています。これにはかなり助けられました。そして10月。<a href="http://conferences.yapcasia.org/ya2009/talk/2192">YAPC::Asia特別研修「Moose入門」</a>が開催され、中の人である<a href="http://sartak.org/">sartakさん</a>直々の仕込みに<a href="http://blog.eorzea.asia/2009/09/post_65.html">ひたすら感激しました</a>。「最速マスター」を書けるようになったのも、ひとえにこうした方々の成果があったためです。私は日々皆さんに感謝しながらコードを書いています。</p>

<p>そうした感動を何とか還元したくて、<a href="http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=gitmo/moose-presentations.git;a=tree;f=moose-class">スライド</a>を<a href="http://blog.eorzea.asia/2009/10/post_70.html">和訳してみたり</a>、<a href="http://blog.eorzea.asia/2010/02/post_91.html">クイックリファレンスシート（チートシート）を書いたり</a>しました。今回の「最速マスター」もその一環として位置付けたつもりです。</p>

<p>二ヶ月弱もこのブログを放っておいたので、「最速マスター」をここで公開しようかとも考えましたが、<a href="http://blog.eorzea.asia/2010/02/post_90.html">先日書いた</a>通り、<a href="http://perl-mongers.org">perl-mongers.org</a>にお世話になることにしました。理由をもう少し捕捉しておくと、公益性が多少ありそうな入門記事を折角書いたのだから、ここのような「どこの馬の骨とも知れない場末ドメインのインチキブログ」で公開するよりは、「多くの方にご覧頂けそうで、かつ、公益性があって信頼の出来る場所」に公開したいと考えたからです。</p>

<p>公益性を感じられるドメイン名が既にあり、登録すれば誰でも寄稿出来る仕組みが既にあり、実際に多くの記事が既に投稿されている。この環境はとても素晴らしいものだと思います。perl-mongers.orgを立ち上げた<a href="http://vkgtaro.jp/">vkgtaroさん</a>、サイトを現在ホストしている<a href="http://blog.woremacx.com/">woremacxさん</a>に、とても感謝しているところです。</p>

<p>言語や処理系へ大会社のサポートがあるといっても、それらは実際には大して頼りにならず、そのうえ日々「バグだ」「いや仕様漏れだ」「何だと、瑕疵担保条項を発動するぞ」「そもそも要件定義からして腐っていたんだ」などと前から後ろから弾丸が飛び交う場所で設計・開発・試験して、祈りながら実行して飯を食べている私は、コミュニティーに感謝しながら楽しく設計・開発・試験して、実行結果を安心して見守れるPerlを心のオアシスとして生きているのかも知れません。</p>

<p>これは完全な私感になりますけれども、<a href="http://ja.wikipedia.org/wiki/Ruby#Ruby.E5.93.B2.E5.AD.A6">Rubyでプログラミングを楽しめる</a>一方で、PerlにはCPANやコミュニティーを含めた楽しさや居心地の良さを他の言語よりも強く感じます。</p>

<p>Perlコミュニティーにはperl-users.jpや各地の*.pmもあります。<a href="http://d.hatena.ne.jp/perlcodesample/20091226/1264257759">基本文法</a>や<a href="http://d.hatena.ne.jp/chaichanPaPa/20100206/1265436393">オブジェクト指向</a>や<a href="http://d.hatena.ne.jp/gfx/20100202/1265091606">XS</a>などの「最速マスター」シリーズも盛んです。勿論、こんな美味しい方法論が放っておかれるわけもなくて、他の言語の暖かいコミュニティーでもhogehoge-usersが出来たり、「hogehoge文法最速マスター」が公開されたりしています。でも、それらの嚆矢がPerlであったということは、Perlユーザーは誇ってもいいと思うのです。</p>

<p>私はそんなPerlが大好きです。</p>

<p>今般<code>Moose</code>/<code>Mouse</code>を使い始めようとする方に奉仕するのは、私の義務であり喜びでもあります。どうか、<code>Moose</code>/<code>Mouse</code>による楽しいプログラミングを、Perlコミュニティーの体温を感じながら味わってください。</p>

<p>ところで、体温といえば、私は投稿した日に風邪を引いたらしくて摂氏37度になりました。ぎゃふん。</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Moose &amp; Mouseの私家版クイックリファレンスシート(チートシート)を作りました</title>
    <link rel="alternate" type="text/html" href="http://blog.eorzea.asia/2010/02/post_91.html" />
    <id>tag:blog.eorzea.asia,2010://1.91</id>

    <published>2010-02-19T14:44:24Z</published>
    <updated>2010-02-21T00:33:02Z</updated>

    <summary><![CDATA[Moose &amp; Mouseの私家版クイックリファレンスシート（チートシー...]]></summary>
    <author>
        <name>Gardejo</name>
        
    </author>
    
        <category term="雑記" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="moosemouse" label="Moose/Mouse" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="Perl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://blog.eorzea.asia/">
        <![CDATA[<p><a href="http://search.cpan.org/perldoc?Moose"><code>Moose</code></a> &amp; <a href="http://search.cpan.org/perldoc?Mouse"><code>Mouse</code></a>の私家版クイックリファレンスシート（チートシート）を作ってみました。</p>

<p>PDF版とODT版の両方を置いておきます。</p>

<ul>
<li><a href="http://perl.ermitejo.com/moose_quick_ref.pdf">Moose &amp; Mouse QUICK REFERENCE (PDF)</a></li>
<li><a href="http://perl.ermitejo.com/moose_quick_ref.odt">Moose &amp; Mouse QUICK REFERENCE (ODT: OpenDocument Text for OpenOffice.org Writer)</a></li>
</ul>

<p><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="moose_quick_ref.png" src="http://blog.eorzea.asia/2010/02/20/moose_quick_ref.png" width="640" height="450" class="mt-image-none" style="" /></span></p>

<p><a href="http://ja.openoffice.org/">OpenOffice.orgは無料で入手出来ます</a>ので、オレオレチートシートの元ネタとしてもお使いいただけるかも知れません。</p>

<p>そもそもMooseには<a href="http://sites.google.com/site/gorwits/">Oliver Gorwitsさん</a>による<a href="http://tinyurl.com/moosequickref">Moose Quick-Ref Card</a>というチートシートが昔からあります。これは奥深い<code>Moose</code>の世界が端的にまとめられた素晴らしいものです。ただ、幾つかオレオレ仕様にしたい点がありました。</p>

<p>そんな日々を送っていると、『<a href="http://ascii.asciimw.jp/books/books/detail/978-4-04-868411-8.shtml">Web制作の現場で使うjQueryデザイン入門</a>』の付録にフルカラーのjQueryチートシートが付いていることを知りました。これに触発されて作り始めたという経緯があります。</p>

<p>当初はこの2倍くらいの量があったのですが、だったら流行りの「基本文法最速マスター」に悪のりしてしまおうとしたのが「<a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html">Moose &amp; Mouse基本文法最速マスター/The Fastest Way to Mastering Moose &amp; Mouse</a>」という副産物です。</p>

<p>ところで、上述のjQuery本はプログラマー向けというよりは意匠デザイナー向けの本であるので、カラフルなチートシートで間口を広く取るのは大正解だと思います。一方、今回作った<code>Moose</code> &amp; <code>Mouse</code>チートシートは白黒灰の3色かつ無味乾燥な作りになっているので、初学者向けのチートシートにはなっていません。カラフルでA4両面くらに日本語の説明文をふんだんに盛り込んだ初学者向けのシートも併せて作りたかったのですが、意匠センスが決定的に不足しているので断念しました。</p>

<p><code>Moose</code>/<code>Mouse</code>の素敵なプログラミングを体験する人が増えることを期待していますので、ナウなヤングにバカウケなイけてるシートを公開してくださる偉い人の登場を心待ちにしています。</p>

<p>とはいえ今回のシートも多少は物を考えて書いたつもりです。苦心した点を以下に簡単にまとめておきます。</p>
]]>
        <![CDATA[<h2>カカオ増量、砂糖減量</h2>

<p>クイックリファレンスというのは、「読む」ものではなく「見る」ものだと考えています。従って、自然言語、つまり英語（や日本語）の説明文を極力省くことで、必要なコードスニペットだけが目に飛び込んでくるようになります。</p>

<p>私はクイックリファレンスをそれ自体で単独で完結させようとはせず、<code>Moose</code>の基本的な構文を「最速マスター」の水準で理解できていることを前提として記述しました。</p>

<p>いくつかの例を元にもう少し詳しく説明します。</p>

<h3>自明な箇所の解説は除いた</h3>

<p>端的な例は<code>extends @superclasses</code>です。</p>

<p>見ての通りsuperclassesをextendするので、class inherits superclassesなどという説明文は不要ですね。自明な処理はコメントしないという鉄則を守らないと、コードを逐行で日本語訳して立派な「クラス仕様書」をこしらえるどこかの会社の轍を踏んでしまいます。</p>

<p>Moose Quick-Ref Cardでもあまりにも自明な解説文は省いていますが、しかしどちらかというと親切な記述になっているようにお見受けしました。多少間口を狭くした方がかえって利便性が増す可能性があるのではないだろうか、と思います。</p>

<h3>コードで書けるものは極力コードで書く</h3>

<p>他にも、Moose Quick-Ref Cardではメソッドモディファイヤーのコードリファレンスに渡ってくる引数について</p>

<blockquote>
  <p><code>around</code> is passed <code>($next_method, $self, @args)</code>.</p>
</blockquote>

<p>と書かれていますが、これは以下のようにコードだけで書くこともできます。</p>

<pre><code>around @methods =&gt; sub {
    my ($next, $self, @args) = @_; ...
};
</code></pre>

<p>ついでに<code>my @return_values = $self-&gt;$next(@args); ...</code>という記述も追加して、<code>override</code>/<code>super()</code>との違いが分かるようにもしました。</p>

<h3>元々甘い<code>Moose</code></h3>

<p>いかにもそれっぽい理由付けを書きましたが、こうでもしないと内容をA4へ収めきれないという切実な問題が一番の理由だったりします。</p>

<p>ただし、<code>Moose</code>のシュガー関数はそれ自体が「甘い」ので、さらなる砂糖を振り掛けなくても美味しくいただけるということが分かります。宣言的プログラミングが病み付きになる所以ですね。</p>

<h2>痒いところに孫の手を</h2>

<h3><code>Any::Moose</code>対応</h3>

<p>クラスやロールのスケルトンなどで<code>Any::Moose</code>を使った書き方にしています。</p>

<p><code>Any::Moose</code>の仕様が分かっていれば、シートに相当して<code>Moose</code>, <code>Moose::Role</code>, <code>MooseX::Types</code>を生で<code>use</code>する記述も書けると思います。というか、流石に<code>use Moose;</code>することを知らないと<code>Moose</code>クラスは書けないと思います。</p>

<h3><code>MooseX::Types</code>前提</h3>

<p><code>Moose::Util::TypeConstraints</code>ではなく<code>MooseX::Types</code>を使うことを前提にしています。</p>

<p><code>My::App::Types</code>以下の名前空間に勝手に入ってくれたりするので、あれやこれや気を遣ったり、注意を促す文言を書くよりは、すっぱり<code>MooseX::Types</code>を使った方が楽だと思ったからです。</p>

<p>勿論<code>Any::Moose</code>に対応した書き方をしています。</p>

<h3>ネイティブトレートのヘルパーメソッドを網羅</h3>

<p>私家版チートシート作成の動機は、ひとえに名前空間が深い<code>Moose::Meta::Attribute::Native::Trait::Array</code>などを<code>perldoc</code>すると疲れることでした。</p>

<p>ということで、4段組のうちまるまる1段を使ってヘルパーメソッドの一覧を羅列しました。</p>

<ul>
<li><code>abs</code>がアトリビュートの値を汚すこと（汚さないなら単に<code>abs $obj-&gt;attr</code>）</li>
<li><code>sort</code>がアトリビュートの値を汚さないこと（汚すなら<code>sort_in_place</code>）</li>
</ul>

<p>などという点で引っ掛かりそうだったので、相当する素のPerl構文も併記しています。</p>

<h3><code>MooseX::*</code>拡張モジュールに言及</h3>

<p>モジュールの名前を羅列するだけでなく、空間が余ったので使い方をごく簡単に書きました。</p>

<p><code>use MooseX::Clone;</code>なのか<code>with qw(MooseX::Clone);</code>なのかと、拡張モジュールの呼び方をすぐ忘れてしまうからです。</p>

<p>そのモジュールで書けるようになる構文も、ほんの触りだけ記述しています。</p>

<h3><code>has</code>オプションをカテゴライズしつつオレオレソート</h3>

<p>これは「最速マスター」の意図としてもご紹介しましたが、<code>has</code>のオプションをベタに羅列するのではなく、或る程度関連性のある内容を小分けにしています。</p>

<p><a href="http://d.hatena.ne.jp/hakobe932/">hakobe932さん</a>によるKansai.pm #9での<code>Moose</code>入門の発表「<a href="http://www.slideshare.net/hakobe/moose">初めてのMoose</a>」などでもネタにされるように、<code>has</code>のオプションはかなり多いです。情報を鉄砲水のように浴びせられると心が折れてしまいかねないので、多少は考慮しました。</p>

<p>また、これは完全にオレオレルールなのですが、<a href="http://blog.eorzea.asia/2009/10/post_73.html">Mooseアトリビュートのオプション指定順についての私案</a>の順番の通りに並べています。自分であんな記事を書いておきながら、まだ順番を手で覚えるまでには至っていないため、自分のためのアンチョコとして記述しています。</p>

<h2>判型と組版</h2>

<p>Moose Quick-Ref CardはA4縦で、上下方向に2つ折りにしてA5横両面で使うことを想定した組版となっています。私家版では以下のような点を考慮して変更しています。</p>

<h3>A4横1片面1枚に収めた</h3>

<p>キーボードの手前に空いているスペースはA4横の縦辺だったという理由ですが、「jQuery Cheat Sheet」など、色々なチートシートを見てもA4横が多かったので、この寸法を採用しました。</p>

<h3>4段組にした</h3>

<p>私は「机の天板に透明シートを敷いて、その下に資料を挟み込む」ということをしていません。トナーが裏移りするだとか、梅雨時にべたつきかねないだとかの理由によります。</p>

<p>従って、クリアファイルやアクリルケースに入れて使うことを想定していますが、場合によっては2つ折りや4つ折りで使うことも考えられます。さっと手にとって目を通せるという意味では、卒業式の答辞で手に持つような縦長の張扇型の方が好ましかったりするからです。</p>

<p>具体的にはオライリー刊『<a href="http://www.oreilly.co.jp/books/4873111544/">UMLデスクトップリファレンス</a>』(A5変判)などのデスクトップリファレンスシリーズなどを想定しています。</p>

<p>日本IBM刊『エンタープライズ・システム体系/370便覧』(N:GX20-0406-00)という旧世紀の遺物を例示しようとしましたが、同僚以外に分かってもらえそうにありません。<a href="http://ja.wikipedia.org/wiki/EBCDIC">EBCDIC</a>のページだけコピーしてチートシートにしたことはいい思い出です......。</p>

<p>ということで、折っても見られるような均等4段組で割り付けることにしました。電車の中での読み易さなどを考慮してか、最近では毎日に続いて読売や朝日も偶数段で組版していますね。</p>

<p>などと書いてから実際に4つ折りにしてみると、左右のマージンの考慮が漏れていて、折り目を跨いでしまっていることが判明しました。機会があれば直しておきます......。</p>

<h3>関係性を目で追えるようにした</h3>

<p>ネタは以下のように割り付けています。</p>

<ol>
<li>基本的な内容
<ul>
<li>(題名)</li>
<li>CLASSES</li>
<li>ROLES</li>
<li>METHOD MODIFIERS</li>
<li>CONSTRUCTION AND DESTRUCTION</li>
</ul></li>
<li><code>has</code>のオプション
<ul>
<li>ATTRIBUTE CONSTRUCTION OPTIONS</li>
</ul></li>
<li>型と、場所が余ったので<code>MooseX::*</code>
<ul>
<li>TYPE CONSTRAINTS &amp; COERCIONS</li>
<li>MooseX::* EXPANSION MODULES</li>
</ul></li>
<li>ネイティブトレートのヘルパーメソッド
<ul>
<li>HELPER METHODS FROM NATIVE TRAITS</li>
</ul></li>
</ol>

<p>この構成は以下のようなシナリオを想定して意図しています。</p>

<ul>
<li>1段目にあるクラスやロールのスケルトンで<code>has</code>があり、<code>has</code>のオプションが見たくなる。cf. ATTRIBUTE CONSTRUCTION OPTIONSとして飛び先を指示されるが、それはすぐ右の第2段にあるので、目で自然に追える。</li>
<li>2段目の<code>isa</code>でcf. TYPE CONSTRAINTS AND COERCIONSとして飛び先を指示されるが、それはすぐ右の第3段にあるので、目で自然に追える。</li>
</ul>

<p>ただ、流石にネイティブトレートは無理でした。それだけで第4段を占拠してしまっているので、<code>handles</code>に関連する内容として飛ばそうと思っても、第3段の型とは相乗り出来ないためです。</p>
]]>
    </content>
</entry>

<entry>
    <title>Moose &amp; Mouse基本文法最速マスターをperl-mongers.orgへ寄稿しました</title>
    <link rel="alternate" type="text/html" href="http://blog.eorzea.asia/2010/02/post_90.html" />
    <id>tag:blog.eorzea.asia,2010://1.90</id>

    <published>2010-02-17T17:15:12Z</published>
    <updated>2010-02-19T03:22:25Z</updated>

    <summary>二ヶ月弱のご無沙汰でしたが、あ、ありのまま起こったことを（略）。 MooseのM...</summary>
    <author>
        <name>Gardejo</name>
        
    </author>
    
        <category term="雑記" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="moosemouse" label="Moose/Mouse" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="Perl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://blog.eorzea.asia/">
        <![CDATA[<p>二ヶ月弱のご無沙汰でしたが、あ、ありのまま起こったことを（略）。</p>

<p><code>Moose</code>の<a href="http://tinyurl.com/moosequickref">Moose Quick-Ref Card</a>というクイックリファレンスカード（チートシート）へ<a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#helper_methods_from_native_traits">ネイティブトレートによるヘルパーメソッド</a>だけ追加して今風にするつもりで私家版チートシートを書いていたら、いつの間にか「<a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html"><code>Moose</code> &amp; <code>Mouse</code>基本文法最速マスター/The Fastest Way to Mastering <code>Moose</code> &amp; <code>Mouse</code></a>」になってしまいました。</p>

<p>下書きをしていたら流行りの「基本文法最速マスター」のような内容になったので、折角なので各種の情報を参考にしつつ、説明文などを追加して公開してみました。「基本」文法でないものも少なからず混じっていますが、副産物なのでご容赦ください。また、Moose用語は可能な限り元の英語を併記していますが、Moose用語以外の英語への訳出はいい加減です。ごめんなさい。</p>

<p>誤っている点, ご不明な点, 冗長すぎてかえって初学者を混乱させかねないため削除すべき点などがありましたら、上記記事へのコメントやトラックバックなどでお寄せいただければ幸いです。適宜改訂します。また、<a href="http://creativecommons.org/licenses/by/2.1/jp/">CC-BYライセンス</a>なので、「とても見ていられないので俺が全面的に書き直してしまえ」という企ても歓迎です。</p>
]]>
        <![CDATA[<h3>公開場所の選定基準</h3>

<p>出来上がったものをどこに晒そうか迷ったのですが、Perl界隈にはせっかく<a href="http://perl-users.jp">perl-users.jp</a>や<a href="http://perl-mongers.org">perl-mongers.org</a>という素敵なサイトがあるので、この場末ドメインのブログではない公の場に寄稿すことにしました。</p>

<p>昨年末にYappoさんにCodeReposのコミット権をいただいたのでperl-users.jpの方に書こうかとも考えましたが、</p>

<ul>
<li>ブログだとコメントやトラックバックなどを受け付けられ、perl-mongers.orgではすぐにでもブログ記事を書ける</li>
<li>今回のネタはperl-users.jpの単独コンテンツほど精錬されていないように思えた</li>
</ul>

<p>などの事情に鑑みて、今回はperl-mongers.orgにお世話になることにしました。</p>

<h3>苦心したこと・書くまで気付かなかったこと</h3>

<ul>
<li>何と言うこともないものですが、アトリビュート構築オプションを分類して記述してみました。羅列すると圧迫感を感じるのは人間として無理からぬことだと思うので、或る程度の関連性のあるものを小分けにしてまとめています。</li>
<li>ネイティブトレートの引数と挙動を書きました。<code>abs</code>を使ったことがなかったため、アトリビュートの値を汚すことは知りませんでした。</li>
<li>「設定」と「指定」の使い分け。アトリビュートの値をセットすることを（<code>default</code>などでセットされること）を「設定」・コードに各種のメタ操作を定義すること、記述することを「指定」と書いていますが、結構曖昧ですね......。「格納」と「記述」とかでも良かったかも知れません。</li>
<li>「オブジェクト」と「インスタンス」の使い分け。これも微妙ですが、an objectとan instance of a classの関係を気にしました。</li>
<li><code>handles</code>指定時に<code>isa</code>指定が必須であることなどは知りませんでした。私は「Moose入門研修」で「型は動的チェックなので、多用すると遅くなる」というお話を伺ったにもかかわらず偏執狂的に<code>isa</code>をほぼ必須指定しているので、なかなか気付きにくい仕様でした。</li>
</ul>

<h3>余談</h3>

<p>CodeRepos.orgやLivedoor.comのOpenIDだとサインイン出来なかったので（原因は追えていません）他の方を参考にMyOpenID.comにアカウントを作ったり、Markdownフォーマットだと<code>Wide character in subroutine entry</code>エラーが出たので素のフォーマットで書いたりと、色々ありました。</p>

<p>そしてさらに、細かな修正を行おうとしても<code>mt.cgi</code>がしばらく503になって再ログイン出来ない状態を引き起こしてしまいました（当日の昼には復帰していました）。何か私が悪いことをしてしまったか心配です。ごめんなさい。</p>

<p>ということで、取り急ぎtwitterで<a href="http://vkgtaro.jp/">vkgtaroさん</a>へお詫びというかご報告というかを差し上げました。</p>

<h3>目次（完全版）</h3>

<p>目次が膨大すぎるとかえって読む気が失せそうなので、先方には簡略版の目次だけ掲げています。当初書こうとしていた目次は、もう少し階層を深く掘った以下のようなものです。単語だけ眺めると、<code>Moose</code>のイロハは網羅できているのかな、と思っています。</p>

<p><code>role_type</code>, <code>duck_type</code>, 無名型, <code>handles</code>にロールを渡した場合の挙動, <code>DEMOLISHALL</code>, <a href="http://search.cpan.org/perldoc?Moose::Exporter"><code>Moose::Exporter</code></a>等々の記述を省いたくせにカリー化辺りが入っているのは私の独断と偏見によります。</p>

<p>Parameterized Typesが<code>Moose 0.26+</code>であるとか、かなり昔から存在する機能についてはバージョンを明記しないようにしています。ただ、その閾値の見極めは難しいです。</p>

<ul>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#classes">クラス/Classes</a>
<ul>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#turning_on_pragmas_and_importing_sugar_functions">プラグマの有効化とシュガー関数のインポート/Turning on Pragmas and Importing Sugar Functions</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#class_has_attributes">アトリビュート/Attributes</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#class_implements_methods">メソッド/Methods</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#class_extends_superclasses">スーパークラス/Superclasses</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#class_consumes_roles">ロール/Roles</a></li>
</ul></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#roles">ロール/Roles</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#sugar_functions">シュガー関数/Sugar Functions</a>
<ul>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#attribute_installation">アトリビュートの設定/Attribute Installation</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#class_inheritance">クラスの継承/Class Inheritance</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#consuming_roles">ロールの消費/Consuming Roles</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#interfaces">インターフェース/Interfaces</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#method_modifiers">メソッドモディファイヤー/Method Modifiers</a></li>
</ul></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#attribute_constructor_options">アトリビュート構築オプション/Attribute Constructor Options</a>
<ul>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#attribute_extension">アトリビュートの拡張/Attribute Extension</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#accessor_methods_generation">アクセッサーメソッドの生成/Accessor Methods Generation</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#type_constraints_and_coercions">型制約と型変換/Type Constraints and Coercions</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#constructor_arguments">コンストラクター引数/Constructor Arguments</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#lazy_building_predication_and_cleaning">値の遅延設定と設定状況/Lazy Building, Predication and Cleaning</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#default_values">デフォルト値</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#triggers">トリガー/Triggers</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#delegation_setting">委譲設定/Delegation Setting</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#documentation">文書化/Documentation</a></li>
</ul></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#types">型/Types</a>
<ul>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#type_constraints">型制約/Type Constraints</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#build_in_type_constraints">組み込みの型制約/Build-in Type Constraints</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#parameterized_types">パラメーター化された型/Parameterized Types</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#automatically_created_types">自動生成された型/Automatically Created Types</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#type_unions">型結合/Type Unions</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#to_define_your_own_types">独自の型の定義/To Define Your Own Types</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#type_coercions">型変換/Types Coercions</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#moosex_types"><code>MooseX::Types</code></a></li>
</ul></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#delegation">委譲/Delegation</a>
<ul>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#delegation_to_an_object">オブジェクトへの委譲/Delegation to an Object</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#method_currying">メソッドのカリー化/Method Currying</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#delegation_to_common_perl_data_structures">Perlの通常データ構造体への委譲/Delegation to Common Perl Data Structures</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#helper_methods_from_native_traits">ネイティブトレートによるヘルパーメソッド/Helper Methods from Native Traits</a></li>
</ul></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#construction_and_destruction_of_instances">インスタンスの生成と破棄/Construction and Destruction of Instances</a>
<ul>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#hooks_into_constructor">コンストラクターのフック/Hooks into Constructor</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#hooks_into_destructor">デストラクターのフック/Hooks into Destructor</a></li>
</ul></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#other_tidbits">その他の内容の触り/Other Tidbits</a>
<ul>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#measures_against_namespace_pollution">名前空間の汚染への対策/Measures against Namespace Pollution</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#meta_object_protocol_and_class_mop">メタオブジェクトプロトコルとClass::MOP/Meta Object Protocol and Class::MOP</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#speed_up_by_immutabilizing_metaclasses">メタクラスの不変化による高速化/Speed Up by Immutabilizing Metaclasses</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#mouse"><code>Mouse</code></a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#moosex_expansion_modules"><code>MooseX</code>拡張モジュール/<code>MooseX</code> Expansion Modules</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#oose"><code>oose</code></a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#timing_to_consuming_interfaces">インターフェースの消費タイミング/Timing to Consuming Interfaces</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#measures_against_method_conflict">メソッド衝突対策/Measures against Method Conflict</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#measures_against_testing">テスト対策/Measures against Testing</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#to_moose_or_not_to_moose">Mooseを使うか否か/To Moose or not to Moose</a></li>
</ul></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#see_also">情報源など/See Also</a>
<ul>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#manuals_for_moose">Mooseマニュアル/Manuals for Moose</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#sources_about_moose">Moose関連のその他の情報源/Sources about Moose</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#the_fastest_ways_for_mastering_basic_perl_grammer">Perl関連の基礎文法最速マスター/The Fastest Ways for Mastering Basic Perl Grammar</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#collection_of_the_fastest_ways_for_mastering_a_programming_language">基礎文法最速マスターのまとめ/Collection of the Fastest Ways for Mastering a Programming Language</a></li>
<li><a href="http://perl-mongers.org/2010/02/the-fastest-way-to-mastering-moose-and-mouse.html#errata">正誤一覧/Errata</a></li>
</ul></li>
</ul>
]]>
    </content>
</entry>

<entry>
    <title>2009年の回顧と展望</title>
    <link rel="alternate" type="text/html" href="http://blog.eorzea.asia/2009/12/post_89.html" />
    <id>tag:blog.eorzea.asia,2009://1.89</id>

    <published>2009-12-31T12:52:47Z</published>
    <updated>2009-12-31T15:32:09Z</updated>

    <summary>まったく、時の経つのは早いもので、2009年の年の瀬も押し迫ってきました。夏休み...</summary>
    <author>
        <name>Gardejo</name>
        
    </author>
    
        <category term="雑記" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="perl" label="Perl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://blog.eorzea.asia/">
        <![CDATA[<p>まったく、時の経つのは早いもので、2009年の年の瀬も押し迫ってきました。夏休みの宿題を9月に入ってから終えるという悪癖があった私のことですから、今年を総括する記事をこんな時刻に書き始めるのも無理からぬ事です。</p>

<p>しかし、新学期の開始日と時間割を突き合わせ、例えば中学校では</p>

<ul>
<li>理科Iは月・火・金に授業がある</li>
<li>新学期は9月1日水曜日に始まる</li>
<li>故に理科Iの宿題は9月2日木曜日中に片付ければよい</li>
</ul>

<p>という嫌らしい打算で生きて来た私にとっては、むしろこのくらいが普通の生き様とも言えます。</p>

<p>ともあれ、今年2009年を一言で表現するのであれば、ただひたすら「感謝」の一年だった、ということになります。</p>
]]>
        <![CDATA[<h2>Perlの催事へ参加</h2>

<p>今年は</p>

<ul>
<li><a href="http://yokohama.pm.org/2009/04/yokohamapm-4-2.html">Yokohama.pm #4</a></li>
<li><a href="http://conferences.yapcasia.org/ya2009/">YAPC::Asia 2009</a></li>
<li><a href="http://shibuya.pm.org/blosxom/techtalks/200911.html">Shibuya.pm Tech Talks #12</a></li>
</ul>

<p>などの催事に参加させていただきました。</p>

<p>参加報告が尻切れだったり、そもそも書けていなかったりします（ごめんなさい！）が、とても多くのことを学び、そしてそれ以上に私の意識を大きく揺さぶられることとなりました。その甲斐もあって、いちPerlファンから、いちPerl戦士にクラスチェンジした感があります。</p>

<p>当たり前のようですがどんなソフトウェアも、それを作り上げた「中の人」がいます。そしてその人の顔が見えると、そのソフトウェアへの愛着が増します。そしてその中の人が語る場は、そのソフトウェアの顔を知らしめるものともなります。</p>

<p>掛け替えのない体験をさせてくださった、催事関係者の皆様に感謝です。</p>

<p>なお、Yokohama.pmでは体調不良もありました。やはり体が資本のこの業界、自分の体を大切にしないといけないなと反省しているところです。</p>

<h2>CPANにコントリビュート</h2>

<p><a href="http://www.cpan.org/">CPAN</a> authorsの<a href="http://search.cpan.org/~moriya/">仲間入りを果たしました</a>。今年は</p>

<ul>
<li><a href="http://search.cpan.org/perldoc?MooseX::Types::Locale::Language"><code>MooseX::Types::Locale::Language</code></a></li>
<li><a href="http://search.cpan.org/perldoc?MooseX::Types::Locale::Country"><code>MooseX::Types::Locale::Country</code></a></li>
<li><a href="http://search.cpan.org/perldoc?DBICx::Modeler::Generator"><code>DBICx::Modeler::Generator</code></a></li>
</ul>

<p>の3本をリリースしたことになります。</p>

<p>YAPC::Asia 2009のLightning Talksで、<a href="http://d.hatena.ne.jp/charsbar/">charsbarさん(石垣さん)</a>のTop Tens of 2008/2009の講演を拝聴して、CPAN authorsの多さや、YAPC::Asia 2008以降に初登場した人の数の多さに驚愕したことが切っ掛けだったのかも知れません。夕暮れの仄暗い会場で、我こそはCPAN authorだとして手を挙げた人の、それはもう多かったこと。今でも思い出せます。</p>

<p>そして、CPANに上げてみようとして始めて、CPANを含めたPerlの思想や文化への理解を（おぼろげながらにでも）深められたような気がします。ソフトウェアICとも称されるCPANモジュールは、モジュールのユーザーからすればそれこそ「水や空気」のように当たり前のようにそこにあるものとして便利に使って来ました。しかし、自分がCPAN authorsの末席を汚すようになって始めて、「<a href="http://slashdot.jp/~taro-nishino/journal/475752">何故、私はPerlを続けるのか</a>」にあるような</p>

<blockquote>
  <p>ライブラリの存在は更に容易にライブラリを書かせる。サイクルがそれ自身に餌を与える。すなわち、我々は多くのライブラリを持っている、それが別のライブラリを簡単に書かせ、更に多くなって、別のライブラリを書くことが更に簡単になる</p>
</blockquote>

<p>という基盤があってこそ、CPANモジュールユーザーやCPAN authorsが恩恵を享受出来るのだということを肌で理解出来たような気がします。</p>

<p>CPANという仕組みそれ自体や、多くの前提モジュールの作者の方々に感謝です。</p>

<p>本当は<a href="http://www.cpan.org/">Text::UTX::Simple</a>がCPANデビュー作となるはずでしたが、これは<a href="http://github.com/gardejo/p5-text-utx">Text::UTX</a>として2010年1月中にリリースする予定です。私にしては珍しく期限を切っているのは、<a href="http://www.aamt.info/english/journal.htm">AAMT Journal</a>への寄稿の締め切りがある所為です。相変わらず綱渡りの人生ですね......。</p>

<h2>Blogの引っ越し</h2>

<p>これまでは、サイドバーの「やや真面目なサイト」に掲げている「<a href="http://ttt.ermitejo.com/">エスペラント語日本語翻訳Ermitejo</a>」の開発日誌としてブログを書いていました。一方、（一応）このブログのドメイン名が語っているように、来年サービスイン予定のMMORPGであるFF14用のウェブアプリケーションの開発日誌として<a href="http://blog.eorzea.asia/2009/06/post_2.html">2009年6月末に開始した</a>はずのこのEorzea Loungeですが、気付いたらその他の事についての記述が多くなっていました。</p>

<p>「その他」といっても主にはPerl勉強日誌的なものですが、上述の<a href="http://blog.eorzea.asia/2009/09/post_61.html">YAPC::Asia 2009の報告</a>や、<a href="http://blog.eorzea.asia/2009/08/post_57.html">LLTVの報告</a>などは多くの方にご覧いただいたようで、会場の熱気や催事の素晴らしさを少しでもお伝え出来たのならば嬉しいです。</p>

<p>WordPressよりもMovable Typeの方が性に合っていただとか、Permalinkをいちいち考えるのが面倒臭かった（このブログはエントリーIDがPermalinkになっています）だとか、諸々の理由がありますが、ともかく何となくこちらのブログを更新することになったようです。</p>

<p>各ウェブアプリケーションに紐付く話題とは別に、その他のこと全般を書くブログをこしらえた方が良いかとも思いましたが、取り敢えずもう後の祭りなのでしばらくこのままで運用していこうと思います。</p>

<p>分不相応にも多くの方にブックマークしていただけた記事もあったようで、記事の題材である催事関係者の方々や、読んでくださった方々に感謝です。</p>

<h2>Mooseを使い始めました</h2>

<p><a href="http://search.cpan.org/perldoc?Moose"><code>Moose</code></a>/<a href="http://search.cpan.org/perldoc?Mouse"><code>Mouse</code></a>を使い始めて、Moose信者になりました。事情があって公開は出来ないのですが、証券関係のWindows向けの2万行強のアプリケーションを会社勤めの傍ら1ヶ月程で<code>Mouse</code>で書ききったことが、一つの転機となりました。</p>

<p>基本的に私は頭の回転が遅いので、何事も使ってみて始めて分かるという面倒臭い性格をしていますが、OOの利点が使ってみなければ分かりにくいことと同様で、まず使ってみて正解だったと思います。今ではもう、ごく限られた場合を除いては、Perl OOでMoose/Mouseを利用しないことは考えられません。</p>

<p>Perlのモジュール等を使い始めて、それについてググったりすると、自分が1年や2年ほど周回遅れをしていることがよく分かります。しかし、いわゆるアーリーアダプターなPerl Hackerの方々がブログで書かれた内容がちんぷんかんぷんだった時代と比べれば、時間を経たとしても「あぁ、これはこういうことを言っているのか」と分かるようになったというのは、とても嬉しい物があります。</p>

<p><a href="http://blog.eorzea.asia/2009/09/post_65.html">Moose入門研修の素晴らしさ</a>にほだされて<a href="http://blog.eorzea.asia/2009/10/post_70.html">スライドの日本語訳</a>を書き始めましたので、未訳部分の補完などを含め、定期的に保守していきたいです。</p>

<p><code>Moose</code>/<code>Mouse</code>のメンテナーやコントリビューターの皆様や、研修関係者の皆様に感謝です。</p>

<h2>gitの利用とGitHubの利用</h2>

<p>上記のWindows向けアプリケーションまではSubversionを使っていたのですが、色々と思うところがあって、VCSをgitに移行しました。その一番の理由は、GitHubでなんだか楽しそうなことをしているなぁ、というものでした。ということで、<a href="http://github.com/gardejo">GitHubのアカウント</a>を取っていくつかのモジュールを公開し始めました。</p>

<p>gitやGitHubをまだ十全に活用出来てはいませんが、<a href="http://search.cpan.org/perldoc?DBICx::Modeler"><code>DBICx::Modeler</code></a>というCPANモジュールへテストを含めて<a href="http://github.com/gardejo/dbicx-modeler/commit/5dadb20b3bf1ac36cd05c605bf860d3086d4408f">数行のパッチ</a>をお送りすることが出来たりと、その可能性に気付かされました。</p>

<p>GitHub運営者の方々や、GitHubで惜しげもなくご自分のソフトウェアの開発過程を公開してくださる方々に感謝です。</p>

<h2>JPerl Advent Calendar 2009に寄稿</h2>

<p>上記の<code>Moose</code>と<code>DBICx::Modeler</code>に関連して、FF14向けウェブアプリケーションの開発に際して「<a href="http://blog.eorzea.asia/2009/10/post_76.html">ORMスキーマとドメインモデルを統合する方法・分離する方法</a>]という記事を書きました。また、これに関連して、<a href="http://search.cpan.org/perldoc?DBICx::Modeler::Generator"><code>DBICx::Modeler::Generator</code></a>というモジュールをCPANに上げました。</p>

<p>元々オレオレモジュールとして細々と書いていたものでしたが、Shibuya.pm Tech Talks #12でtokuhiromさん(松野さん)が<a href="http://perl-users.jp/articles/advent-calendar/2009/">JPerl Advent Calendar 2009</a>の<a href="http://perl-users.jp/articles/advent-calendar/2009/hacker/">hacker track</a>の執筆者が不足していると仰るのを伺って一念発起し、勢いでCPANizeしつつ、空気を読まず<a href="http://perl-users.jp/articles/advent-calendar/2009/hacker/22.html">DBICx::Modeler::Generatorでスキーマクラス群とモデルクラス群を一発生成しよう</a>という記事を書かせていただきました。hacker trackも無事完走して、とてもほっとしています。</p>

<p>発起人の<a href="http://d.hatena.ne.jp/tokuhirom/">tokuhiromさん(松野さん)</a>をはじめ、関係者の皆様に感謝です。</p>

<p><a href="http://blog.yappo.jp/">yappoさん(大沢さん)</a>にお願いして<a href="http://coderepos.org/">CodeRepos</a>のcommit権をいただいたので、GitHubだけでなくCodeReposでも何か公開していきたいと思います。</p>

<h2>2010年の抱負</h2>

<p>2010年は</p>

<ul>
<li>CPANモジュールText::UTXの公開</li>
<li>FF14向けウェブアプリケーション「<a href="http://eorzea.asia/amikeco/">Amikeco</a>」のサービスイン</li>
<li><a href="http://ttt.ermitejo.com/">エスペラント日本語翻訳システム</a>の開発進展、およびGitHubかCodeReposでの公開</li>
<li>聞く側としての参加だけでなく話す側としての催事への参画</li>
</ul>

<p>などを目標にしたいと思います。来年もまた感謝のし通しの一年となりそうです。</p>

<p>それでは、良いお年を(Feliĉan jaron)!</p>
]]>
    </content>
</entry>

<entry>
    <title>地球時間と仮想世界の時間を相互変換する日付時刻クラス</title>
    <link rel="alternate" type="text/html" href="http://blog.eorzea.asia/2009/12/post_88.html" />
    <id>tag:blog.eorzea.asia,2009://1.88</id>

    <published>2009-12-24T15:39:03Z</published>
    <updated>2009-12-25T16:53:52Z</updated>

    <summary>アセトアルデヒドの勢いで変な物を書いたような気がします。書きかけですけれども。 ...</summary>
    <author>
        <name>Gardejo</name>
        
    </author>
    
        <category term="開発日誌" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="finalfantasyxiv" label="Final Fantasy XIV" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="moosemouse" label="Moose/Mouse" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://blog.eorzea.asia/">
        <![CDATA[<p>アセトアルデヒドの勢いで変な物を書いたような気がします。書きかけですけれども。</p>

<p><a href="http://github.com/gardejo/p5-games-datetime"><code>Games::DateTime</code> - A simple date and time object on any games</a></p>

<p><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="screenshot_of_p5-games-datetime.png" src="http://blog.eorzea.asia/2009/12/26/screenshot_of_p5-games-datetime.png" width="580" height="388" class="mt-image-none" style="" /></span></p>

<p>たまには脇道に逸れて、ff14.nameおよびff14.asia向けの部品的なモジュールを書くというのも、気分転換に良いかも知れません。何に対しての気分転換かというと、独り身の帰宅路で涙にむせぶ件といったところでしょうか。</p>

<p>上掲のスクリーンショットのような「時計」であればFlashやJavaScriptでもよく見掛けるのですが、「ローカルタイムな地球現在時→仮想世界の現在時」以外に</p>

<ul>
<li>仮想世界の日時→地球の日時方向への変換</li>
<li>ローカルタイム以外のタイムゾーンへの対応</li>
<li>地球日時もしくは仮想世界の日時の指定</li>
<li>時間計算（地球および仮想世界の両方）</li>
</ul>

<p>などが出来る「日付時刻クラス」というのは寡聞にして知らないので、書きました。取り敢えずググって要件を見つけられたのはFF11だけでしたが、起点日時の対称が見付かれば、プレースホルダー的に置くだけ置いたEverQuestなどの実装にも対応出来るかも知れません。</p>

<p>ちなみにスクリーンショットの時計はライブラリー本体ではなく<code>examples</code>ディレクトリー以下のおまけである<a href="http://github.com/gardejo/p5-games-datetime/blob/master/examples/lib/Games/DateTime/Clock.pm"><code>Games::DateTime::Clock</code></a>です。ff14.nameやff14.asiaでは、最終的にはこれと<code>Games::DateTime</code>をJavaScriptに移植することになります。</p>

<p>なお、<code>Acme::*</code>以下の名前空間にするかどうかは考え中です。また、テストは酔いが覚めてから書く予定です。などと書いていると肝臓が明日も泣きそうな気がします。</p>

<p>備忘録ですが、<a href="http://search.cpan.org/perldoc?MooseX::AbstractFactory"><code>MooseX::AbstractFactory</code></a>で、ファクトリーメソッドに指定する具象クラス名（の一部）を指定する際にエイリアスを使えるようにしています。ただし<code>HashRef</code>を渡さずにエイリアスクラス名（の一部）を渡す際には、宝箱を開ける為の鍵が当該宝箱の中にあるような状態で、いまいちです。</p>

<p><code>Moose</code>の型制約を遅延設定する<a href="http://github.com/gardejo/p5-games-datetime/blob/master/lib/MooseX/Types/Games/DateTime.pm"><code>MooseX::Types::Games::DateTime</code></a>辺りの小細工（実装クラスに依存して<code>where</code>ブロック内の振る舞いを規定する、など）については、稿を改めようと思います。</p>

<ul>
<li>1日24時間という世界の具象クラスでは<code>hour</code>が<code>0 &lt;= $_ &amp;&amp; $_ &lt; 24</code>の範囲になり、</li>
<li>1日30時間という世界の具象クラスでは<code>hour</code>が<code>0 &lt;= $_ &amp;&amp; $_ &lt; 30</code>の範囲になる</li>
</ul>

<p>という要件があったときに、事前に（静的に）それぞれ別の型制約を作らずに、最大値を具象クラスから引っこ抜いて型制約で使うということです。これもまたいまいちな実装ですけれども。</p>

<p><ins><em>追記</em></ins>: テストを薄く書いてバグを除いたほか、見本の時計はロケールにも対応させました。また、cp932でなくUnicodeなコンソールでの字詰めの問題等々を解消しています。上記スクリーンショットも差し替えています。全角半角の「文字幅」の取り扱い方については、（時間があれば）稿を改めて備忘録を起こす予定です。</p>
]]>
        

    </content>
</entry>

<entry>
    <title>JPerl Advent Calendar 2009 hacker track: 22nd day</title>
    <link rel="alternate" type="text/html" href="http://blog.eorzea.asia/2009/12/post_87.html" />
    <id>tag:blog.eorzea.asia,2009://1.87</id>

    <published>2009-12-22T03:01:31Z</published>
    <updated>2009-12-23T13:34:01Z</updated>

    <summary>JPerl advent calendar 2009 hacker trackの...</summary>
    <author>
        <name>Gardejo</name>
        
    </author>
    
        <category term="雑記" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="dbic" label="DBIC" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="orマッパー" label="O/Rマッパー" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="orochi" label="Orochi" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="Perl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://blog.eorzea.asia/">
        <![CDATA[<p><a href="http://perl-users.jp/articles/advent-calendar/2009/hacker/">JPerl advent calendar 2009 hacker track</a>の<a href="http://perl-users.jp/articles/advent-calendar/2009/hacker/22.html">22日目を執筆</a>させていただきました。</p>

<p>補足情報を簡単に記します。</p>
]]>
        <![CDATA[<h2><code>DBICx::Modeler::Generator</code>のご紹介</h2>

<p>採り上げたCPANモジュールは、拙作<a href="http://search.cpan.org/perldoc?DBICx::Modeler::Generator"><code>DBICx::Modeler::Generator</code></a>です。</p>

<ul>
<li><a href="http://search.cpan.org/perldoc?DBIx::Class::Schema::Loader"><code>DBIx::Class::Schema::Loader</code></a>による<a href="http://search.cpan.org/perldoc?DBIx::Class"><code>DBIx::Class</code></a>スキーマクラス群の生成</li>
<li><code>DBIx::Class</code>スキーマと<a href="http://search.cpan.org/perldoc?Moose"><code>Moose</code></a>とを仲立ちする<a href="http://search.cpan.org/perldoc?DBICx::Modeler"><code>DBICx::Modeler</code></a>モデルクラス群の生成</li>
</ul>

<p>をラップする（だけ）のヘルパーモジュールです。元々先月末くらいから自分用に作っていたのですが、本稿の執筆を想定して先日CPANizeしたものです。若干、手段の自己目的化のきらいがありますが......。</p>

<p>ただ、このモジュールの紹介というよりは、むしろPoEAAでいうところのDomain Modelパターン讃歌のような趣になりました。以前の記事「<a href="http://blog.eorzea.asia/2009/10/post_76.html">ORMスキーマとドメインモデルを統合する方法・分離する方法</a>」と<code>DBICx::Modeler::Generator</code>のPODを鍋に入れた感じです。</p>

<p>MySQL Workbench以外のツールは、「<a href="http://blog.eorzea.asia/2009/08/post_54.html">ER図の描画ツールを求めて三千里</a>」などでもご紹介しています。</p>

<h2><code>Orochi</code> + <code>MooseX::Getopt</code> + <code>MooseX::SimpleConfig</code> = 便利</h2>

<p>日曜プログラマーとして補足しておきたい点として、</p>

<ul>
<li>DIフレームワークである<a href="http://search.cpan.org/perldoc?Orochi"><code>Orochi</code></a>および<code>Moose</code>クラスをアノテートする<a href="http://search.cpan.org/perldoc?MooseX::Orochi"><code>MooseX::Orochi</code></a></li>
<li><code>Moose</code>アトリビュートの初期化を<a href="http://search.cpan.org/perldoc?Getopt::Long"><code>Getopt::Long</code></a>式に行う<a href="http://search.cpan.org/perldoc?MooseX::Getopt"><code>MooseX::Getopt</code></a></li>
<li><code>Moose</code>アトリビュートの初期化を設定ファイルから引き込む<a href="http://search.cpan.org/perldoc?MooseX::SimpleConfig"><code>MooseX::SimpleConfig</code></a></li>
</ul>

<p>を合わせて利用すると、</p>

<ul>
<li>中身は<code>Moose</code>クラスやロールを多用して整然と書いておき</li>
<li>ユーザーインターフェースではそれらクラス・ロールに分散する設定値をまとめて指定する</li>
</ul>

<p>ことが出来て便利だ、ということが挙げられます。</p>

<h2>泣き言: casual trackが埋まってしまった......</h2>

<p>本来<a href="http://perl-users.jp/articles/advent-calendar/2009/casual/">casual track</a>向けとして想定していた内容ですが、そちらの投稿者枠はあっという間に埋まってしまいました。その一方、<a href="http://shibuya.pm.org/blosxom/techtalks/200911.html">Shibuya.pm Tech Talks #14</a>に於いてtokuhiromさんがhacker trackの投稿者が足りていないとおっしゃったので、ハッカーでない一般人としてですが、末席を汚した次第です。</p>

<p>野球としては右方向への流し打ちで、プランシー=パウエル神父の箴言としては「次の世代のための道をつくるだけでよい」といったところでしょうか。舗装された道ではなく、砂利道でもなく、せいぜい獣道くらいの出来映えで恐縮ですが。</p>

<h2>執筆者をまだまだ募集中です！</h2>

<p>さて、25日目までにはあと3日間ありますが、<a href="http://atnd.org/events/2275">ATND</a>で宣言のあった限りでは、キュー内の執筆者が空の状態です。自作のCPANモジュールだけでなく、Perl Hacksっぽいことでも書けるそうです。</p>

<p>我こそは、と思う方は、どうかこの道を最後まで繋げてください！</p>
]]>
    </content>
</entry>

<entry>
    <title>FF14ベータテスターへ応募</title>
    <link rel="alternate" type="text/html" href="http://blog.eorzea.asia/2009/12/post_86.html" />
    <id>tag:blog.eorzea.asia,2009://1.86</id>

    <published>2009-12-17T13:35:10Z</published>
    <updated>2009-12-17T14:31:38Z</updated>

    <summary>本サイトはFF14のプレイヤー向けウェブシステムの開発日誌という位置付けですので...</summary>
    <author>
        <name>Gardejo</name>
        
    </author>
    
        <category term="雑記" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="betatest" label="beta test" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="finalfantasyxiv" label="Final Fantasy XIV" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://blog.eorzea.asia/">
        <![CDATA[<p>本サイトはFF14のプレイヤー向けウェブシステムの開発日誌という位置付けですので、FF14の話題にも触れておきます。</p>

<p>遂に<a href="http://jp.finalfantasyxiv.com/newsletter/091217/index.html">FF14のベータテスターの募集が始まりました</a>。2010年の正式サービス開始予定を前に、開発も佳境に入っていることとお見受けします。大変期待の持てる作品であり、末永く愛されることを願ってやみません。</p>

<p>さて、応募に際しては必要事項を色々記入することになりますが、いくつか気掛かりな内容がありました。といっても、馬鹿正直に書いた内容が裏目に出たらどうしよう、という心配事でしかないのですが。</p>
]]>
        <![CDATA[<h2>環境</h2>

<p>物理的資源と人的資源のいずれも、正直に回答しましたが心配の種を播いてもいます。</p>

<h3>CPU</h3>

<p>まず、CPUです。これはまずい。私が主に使っている環境は少々特殊で、何せラジオボタンの選択項目には使用しているCPUが存在しないという有様です。</p>

<p>サーバーおよびワークステーション用CPUの選択肢がないことは理解出来るのですが、これで「うげっ、こいつはもしかしてPentium IIとかで動かしているのか？」などと思われて落とされないか、戦々恐々です（一部誇張あり）。</p>

<h3>OS</h3>

<p>主に使っている環境は未だにWindows XP Professional SP3です。モバイルPCではWindows Vistaの荘重な......と言葉を飾っても仕方がないので正直に書きますと「緩慢な」動作に感銘を受けて、Ubuntuを入れたりしています。</p>

<p>一方で、運営側にとって一番ありがたいのは、やはりWindows 7でのテストでしょう。売り止められてサポート期限も切られているWindows XPなどより、サービス開始を起点として一番長い寿命を見込めるWindows 7の方が、テストの</p>

<p>4年前に構築した自作ワークステーションは、Super πなどではまだまだ会社で使っている最新のPCをも蹴散らす成績を残していますけれども、流石にそろそろマザーボードごと交換しようとも考えていますので、その時にはWindows 7を載せようと思います。</p>

<p>ただし、それはあくまで未来の話。現時点では正直にXPと書くしかないので、「何だかんだ言ってもまだまだサービス開始時点ではXPユーザーが一番多いのではないか」という希望的観測を展開することにしました。</p>

<h3>貢献時間</h3>

<p>テスターとして貢献出来る時間も、少々心配です。平日は21～25時に帰宅するとして、頑張って2時間くらいと計算します。休日は寝溜めをするような非生産的な時間が多いのですが、この生活を見直して4～5時間。しめて「週12時間以上～24時間未満」の枠に収まります。</p>

<p>かつてEverQuestなどで頑張っていた時代（といっても殆どが大学生時代ですが）とはかなり見劣りがするかも知れません。いわゆる廃人などと称されるハードコアプレイヤーの方々と、いわゆるカジュアルプレイヤーの間に位置する、私のようなミドルレンジのプレイヤーが一番多いのではないだろうかと勝手に想像しています。ただ、あくまでテストなので、システム実装的な問題点の確認および報告を行うためには、貢献時間の長さが物を言うことは言うまでもありません。</p>

<p>ということで不安は不安なのですが、設計面やバランス調整など、ミドルレンジのプレイヤーならではの視点で貢献出来る余地があるのではないかとも思いますので、</p>

<h2>意向調査</h2>

<p>「環境調査」に比べて「意向調査」の色合いが強い項目は、心配の種にならない分、熟慮して回答しました。</p>

<h3>訴求点</h3>

<ul>
<li>他のプレイヤーとの交流</li>
<li>強い敵との戦闘</li>
<li>世界観</li>
</ul>

<p>「上位3つまで」という質問でしたが、順番をさらに付けるとしたら上記の通りになります。伝統的EQプレイヤーの回答ですね。他のプレイヤーとの濃厚な交流を旨とし、それをよすがとしてレイドエンカウンターとの交戦を行うという（PvPではなく）PvE重視で、それらを緻密に織りなされた世界観に抱かれて満喫するという案配です。</p>

<h3>FFシリーズに対する情熱</h3>

<p>これは大変答え難い質問ですが、私は100点満点中99点としました。</p>

<p>オフライン作品には初代からお世話になって来ました。大学生・社会人になってからは流石に全作品に手を伸ばせている訳ではありませんが、安心して財布の口を開けられるシリーズだと思っています。</p>

<p>オンライン作品については、世間一般では色々な意見が（オフライン作品以上に）あることと思いますが、その運営品質は比較第一級に位置すると考えます。不正行為への厳正な対処は、「当たり前のことを当たり前にする」ことの難しさも相まって、高く評価したい点です。</p>

<p>しかし、いずれも完全というものはありません。そうした「伸びしろ」が満点への差分ということになります。ということで伸びしろは1点分ということになりましたが、今にして思えばもう少し差分を大きく取った方が良かったかも知れません。「テスターに必要なのは太鼓持ちではなくて、真摯な評価者だ！」と突っぱねられる可能性があるからです。</p>

<p>しかし、上記のような採点根拠を<code>string</code>型で書けない以上、<code>integer</code>型の値でのみ表現する必要があるので、あまり低すぎると「嫌いな人にテストしてもらいたくないね！」と突っぱねられる危険性もあります。</p>

<h2>今後の展望</h2>

<p>大学生時代と違って、業務に於けるテストの重要性は骨の髄まで染みこみました。テスターに選出いただけた暁には、誠心誠意テストに励む所存です。また、FF14プレイヤー向けウェブシステム「<a href="http://eorzea.asia/amikeco/">Amikeco</a>」も、ベータテストに後れを取らないよう、開発にさらに発破を掛ける所存です。</p>

<p>といっても、テスターに選出されたことの表明自体がNDAに抵触する可能性もありますので、未来は何とも言えませんが......。</p>
]]>
    </content>
</entry>

<entry>
    <title>備忘録: Orochiで依存の逆順にinject_classしないこと</title>
    <link rel="alternate" type="text/html" href="http://blog.eorzea.asia/2009/12/post_85.html" />
    <id>tag:blog.eorzea.asia,2009://1.85</id>

    <published>2009-12-07T16:23:08Z</published>
    <updated>2009-12-07T16:33:15Z</updated>

    <summary>PerlのDIコンテナーであるOrochiは、作者である牧さん(lestrrat...</summary>
    <author>
        <name>Gardejo</name>
        
    </author>
    
        <category term="雑記" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="dbic" label="DBIC" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="di" label="DI" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="moosemouse" label="Moose/Mouse" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="orochi" label="Orochi" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="Perl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://blog.eorzea.asia/">
        <![CDATA[<p>PerlのDIコンテナーである<a href="http://search.cpan.org/perldoc?Orochi"><code>Orochi</code></a>は、作者である牧さん(lestrratさん)ご本人が<a href="http://fukuoka.pm.org/">Fukuoka.pm</a>の<a href="http://fukuoka.pm.org/2009/10/fukuoak-perl-workshop-14.html">Fukuoka Perl Workshop #14</a>の<a href="http://users.endeworks.jp/~daisuke/presentations/fukuoka-pm/fukuoka_perl_workshop14.pdf">スライド</a>のp.46で「循環依存の解決は実装できてない」と書いていらっしゃいます（参考：平田さんの「<a href="http://p-lab.freeflux.net/blog/archive/2009/11/15/post-119.html">Fukuoka Perl Workshop #14に行ってきた</a>」の記事）。</p>

<p>ただし、これは私にとっては特段の制約事項とは感じません。循環依存するようなクラスは、場合にもよりますが、私の場合には大抵クラス設計を誤って陥る泥沼状態であるからです。</p>

<p>とはいえ、クラスが複雑に絡み合う事態は起こり得るので、依存関係には気を付ける必要があります。ただ単に依存がぐるぐる回ってバターにならないようにすることは勿論ですが、依存関係を実際に注入する処理でも気を付ける必要があります。この処理は、dannさんの記事の通り、Java界隈ではwiring（ワイヤリング）という用語が充てられます。</p>

<p>で、そのwiringで気を付けるというのは、具体的には、<code>inject_class</code>の実行順が依存の逆順であってはならない、という点です。当たり前といえば当たり前なのですが、うっかりしていました。</p>

<p>以下はその備忘録と解説です。</p>
]]>
        <![CDATA[<h2>Windowsで通ったテストがUbuntuで通らない</h2>

<h3>インスタンスが入って来ない</h3>

<p>事の発端は、拙作<a href="http://github.com/gardejo/p5-dbicx-modeler-generator"><code>DBICx::Modeler::Generator</code></a>のテストです。なお、このモジュールについては、CPANに上げる価値があるのか、CPANモジュール足り得る品質を満たしているのかをもう少し見極める必要があると考えています。</p>

<p>さて、自宅での専らの開発環境がUnix系（2割）ではなくWindows（8割）であるという、geekのgの字も見えない一般人な私は、Windows環境でテストを終えたつもりになりました。いざUnix系環境でのテストと、石垣さん(charsbarさん)が紹介している、<a href="http://d.hatena.ne.jp/charsbar/20080928/1222570663"><code>chmod</code>がちゃんと動く<code>make dist</code></a>を行おうと勇躍してUbuntuを立ち上げた私は、以下のようなエラーでテストに躓いてしまいました。</p>

<pre><code>Attribute (tree) does not pass the type constraint because:
Validation failed for 'DBICx::Modeler::Generator::TreeLike' failed
with value Orochi::Injection::BindValue=HASH(0x5921b8)
</code></pre>

<p>要は<code>tree</code>アトリビュートでは<code>TreeLike</code>インターフェース(<code>Moose::Role</code>)を満たす値を想定していたのに、蓋を開けてみたらそんなインスタンスじゃなくて<code>Orochi::Injection::BindValue=HASH(0x5921b8)</code>という値が入っていたよ、ということです。</p>

<h3>依存が未解決であるという印</h3>

<p>実はこの問題には以前にもはまったことがあって、依存が未解決の値を使おうとするとこうなります。インスタンスだけでなくて、例えば<code>Str</code>などの型を想定していても同様です。</p>

<p>実際のDIの定義（<code>MooseX::Orochi</code>でエクスポートして使う<code>bind_constructor</code>）と注入処理（ワイヤリング）部では、その<code>tree</code>アトリビュートを規定する<code>/DBICx/Modeler/Generator/Tree</code>レジストリーだけを着目すると確かに問題なさそうに見えます。</p>

<p>例えばこの場合は<a href="http://github.com/gardejo/p5-dbicx-modeler-generator/tree/v0.00"><code>v0.00</code>タグ</a>で、</p>

<dl>
<dt>依存関係をクラスの<code>meta</code>アトリビュートへ設定する箇所</dt>
<dd><a href="http://github.com/gardejo/p5-dbicx-modeler-generator/blob/v0.00/lib/DBICx/Modeler/Generator/Driver/SQLite.pm#L51"><code>DBICx::Modeler::Generator::Driver::SQLite</code>の54行目</a></dd>
<dt>依存を注入する(ワイヤリングする)箇所</dt>
<dd><a href="http://github.com/gardejo/p5-dbicx-modeler-generator/blob/v0.00/lib/DBICx/Modeler/Generator/CLI.pm#L252"><code>DBICx::Modeler::Generator::CLI</code>の252行目</a>や、実際のクラス名群をこしらえている<a href="http://github.com/gardejo/p5-dbicx-modeler-generator/blob/v0.00/lib/DBICx/Modeler/Generator/CLI.pm#L182">182行目付近</a></dd>


</dl>

<p>がこれにあたります。</p>

<p>しかし、注入時の順番にも注意が必要なのです。<a href="http://github.com/gardejo/p5-dbicx-modeler-generator/tree/v0.0001"><code>v0.0001</code>タグ</a>の<a href="http://github.com/gardejo/p5-dbicx-modeler-generator/blob/v0.0001/lib/DBICx/Modeler/Generator/CLI.pm#L310">同310行目</a>に書きました通り、このアプリケーションは7段の依存関係があります。</p>

<ol>
<li><code>DBICx::Modeler::Generator</code></li>
<li><code>DBICx::Modeler::Generator::Schema</code></li>
<li><code>DBICx::Modeler::Generator::Driver</code></li>
<li><code>DBICx::Modeler::Generator::Model</code></li>
<li><code>DBICx::Modeler::Generator::Path</code></li>
<li><code>DBICx::Modeler::Generator::Tree</code></li>
<li><code>DBICx::Modeler::Generator::Class</code></li>
</ol>

<p>無駄にクラスを量産しすぎたきらいがありますが、ともあれ、この順番を覆して（以下のような順番で注入して）しまうと、場合によっては値が未解決のままインスタンスを生成しようとしてしまいます。</p>

<pre><code class="perl">return [
    qw(
        DBICx::Modeler::Generator
        DBICx::Modeler::Generator::Class
        DBICx::Modeler::Generator::Model
        DBICx::Modeler::Generator::Path
        DBICx::Modeler::Generator::Schema
        DBICx::Modeler::Generator::Tree
    ),
    'DBICx::Modeler::Generator::Driver::' . $self->driver,
];</code></pre>

<h3>ちゃんと末端から根本の順に注入する</h3>

<p>ということで、葉から枝へ、幹へ、値へというように末端から順にインスタンスを生成していかなければなりません。</p>

<p><a href="http://github.com/gardejo/p5-dbicx-modeler-generator/blob/v0.0001/lib/DBICx/Modeler/Generator/CLI.pm#L182"><code>v0.0001</code>での同182行目</a>付近では、以下のように真っ当な順番にしました。</p>

<pre><code class="perl">return [
    qw(
        DBICx::Modeler::Generator::Class
        DBICx::Modeler::Generator::Tree
        DBICx::Modeler::Generator::Path
        DBICx::Modeler::Generator::Model
    ),
    'DBICx::Modeler::Generator::Driver::' . $self->driver,
    qw(
        DBICx::Modeler::Generator::Schema
        DBICx::Modeler::Generator
    ),
];</code></pre>

<p>これで、クラス間での依存関係は循環していないのに、依存の逆順でインスタンスを生成しようとしてテストに失敗することがなくなりました。めでたし、めでたし。</p>

<h2>何故Windows環境ではテストに成功したのか</h2>

<h3>クラス生成で生じる差異</h3>

<p>しかし、そもそも全く同じコードなのに、何故Widnows環境とUbuntu環境でテスト結果が異なるのでしょうか。これが<code>DBD::mysql</code>や<code>DBD::SQLite</code>などに密接に関わったテストであればともかく、クラスの生成で差異が出るのは気持ち悪いところです。</p>

<h3>ハッシュ関数の挙動ではなかろうか</h3>

<p>テストが通った後によく考えてみた結果、これは完全に憶測なのですが、(ユーザーによる大文字PなPerlプログラムという意味ではなく、処理系としての小文字pな)<code>perl</code>のハッシュ関数の挙動が異なる所為ではないかと踏んでいます。</p>

<p>というのも、当の<a href="http://github.com/gardejo/p5-dbicx-modeler-generator/blob/v0.0001/lib/DBICx/Modeler/Generator/Driver/SQLite.pm#L44">実装クラス側で<code>bind_constructor</code>関数に渡す<code>arg</code>ハッシュキーに該当する値</a>はハッシュリファレンスになっています。ハッシュであるから、リストと違って順番は無視されます。</p>

<p>その順番は、ハッシュキーをハッシュ関数に通して得られるハッシュ値の順番なので、これは<code>perl</code>のエディションやバージョンによって異なるのはいかにもそれっぽいです。</p>

<p>そして、Windows環境でテストした際には、このハッシュ値の順が「たまたま」循環依存しない順番であったために、<code>lazy_build</code>が奏功して依存の逆順でも動く処理となっていて、問題が生じなかったのではないだろうか......という推測です。つまり、たまたまWindowsだから免れたというのではなく、ハッシュキーの構成によってはWindows環境でも起き得たり、*nix環境では起き得なかったりする、と整理出来ます。</p>

<h2>いずれにせよ注入順は肝になる</h2>

<p>いずれにせよ、たまたま動いたからといってクラスをその名称でソートして<code>inject_class</code>に突っ込んだのは、大いに反省するべきところです。実際、<code>MooseX::Orochi</code>のPODでも、<a href="http://search.cpan.org/~dmaki/Orochi-0.00006/lib/MooseX/Orochi.pm#ANNOTATIONS_WITH_MooseX::Orochi">ANNOTATIONS WITH MooseX::Orochi</a>節にある通り<code>inject_class</code>の順番に気を使っていることが分かります。</p>

<pre><code class="perl">$c->inject_class($_) for qw(
  MyApp::Logger
  MyApp::Schema
  MyApp::Model::Foo
  MyApp
);</code></pre>

<p>私の場合、それに気付いてはいたのですが見逃していたという次第で、ただ単に気付かないよりも問題の根が深く、忸怩たる思いです。</p>

<p>「<a href="http://mt.endeworks.jp/d-6/2008/03/neurotic-perl-hacker.html">神経質（A型）なPerlハッカーあるある</a>」で</p>

<blockquote>
  <p>use Module; 宣言を書く時、全部ABC順にしないとイライラする。</p>
</blockquote>

<p>とまで、ソースが整然であることを求道していた牧さんが、何故敢えてそこでクラスのソートをしなかったのか、PODを読んで自ずと理解することを求められているような気がしました。</p>

<h2>余談: やはりMooseの型は偉大だ</h2>

<p>余談ですが、こうした問題を出来るだけ早期に発見するためにも、<code>isa</code>や<code>does</code>は満遍なく指定しておきたいものです。</p>

<p>確かに、Shawn M Mooreさん(sartakさん)は、性能面に鑑みると型を頻繁には使わないことを<a href="http://blog.eorzea.asia/2009/09/post_65.html">YAPC::Asia特別研修</a>で勧めていらっしゃいました。しかし、私のような技術不足の人間は、本番環境ではともかく、少なくても開発環境で一通りのものが動くまでは、転ばぬ先の杖として、また文書化の一環としても、是非指定しておきたいと思うのです。無論、本番環境で当該部分をコメントアウトする折衷案はあり得ることです。</p>
]]>
    </content>
</entry>

<entry>
    <title>Moose/Mouse用フックメソッドをPod::Coverageの対象から外す方法</title>
    <link rel="alternate" type="text/html" href="http://blog.eorzea.asia/2009/12/post_83.html" />
    <id>tag:blog.eorzea.asia,2009://1.83</id>

    <published>2009-12-03T17:14:00Z</published>
    <updated>2009-12-05T20:11:02Z</updated>

    <summary>Moose/Mouseベースのクラスをテストする際には、本筋とは離れたところで一...</summary>
    <author>
        <name>Gardejo</name>
        
    </author>
    
        <category term="雑記" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="moosemouse" label="Moose/Mouse" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="Perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="test" label="test" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://blog.eorzea.asia/">
        <![CDATA[<p><code>Moose</code>/<code>Mouse</code>ベースのクラスをテストする際には、本筋とは離れたところで一工夫が必要になることがあります。</p>

<p>例えば以前の記事「<a href="http://blog.eorzea.asia/2009/08/post_46.html">Arkアプリケーションの開発者テストでTest::Perl::Criticを使う</a>」では、<a href="http://search.cpan.org/perldoc?Test::Perl::Critic"><code>Test::Perl::Critic</code></a>に於いて、<code>use Moose</code>などで<code>use strict</code>構文も代替した場合でも、<a href="http://search.cpan.org/perldoc?Perl::Critic::Policy::TestingAndDebugging::RequireUseStrict"><code>Perl::Critic::Policy::TestingAndDebugging::RequireUseStrict</code></a>に引っ掛からないようにする方策を例示しました。</p>

<p>これに関連して、メソッド（やファンクション）についてPOD内での言及が網羅されているかを検査する<a href="http://search.cpan.org/perldoc?Test::Pod::Coverage"><code>Test::Pod::Coverage</code></a>で、<code>Moose</code>/<code>Mouse</code>用の一部メソッドの記述を省いてしまいたい場合があります。</p>

<p>具体的なメソッドは、例えば</p>

<ul>
<li><code>BUILDARGS()</code></li>
<li><code>BUILD()</code></li>
<li><code>DEMOLISH()</code></li>
</ul>

<p>などのフックポイントです。</p>

<p>私は、PODというものはモジュールの<em>使用者</em>向けの資料であって、内部実装について<em>開発者</em>へ向けて事細かく書くような資料ではないと思っています。場合によりけりですが、基本的にはそうした考えに基づいてPODを書いているつもりです。</p>

<p>そうすると、例えば<code>BUILDARGS()</code>に於いてどのようなパターンで引数の読み替えをするか（例えば<code>Int</code>なスカラー値1つを渡されたら<code>{ epoch =&gt; $value }</code>に読み替えるなど）を書くよりも、素直に<code>new()</code>についての記述を設けた方が良いということになります。</p>

<p>ということで、PODにそれらを書かずに、<a href="http://search.cpan.org/perldoc?Pod::Coverage"><code>Pod::Coverage</code></a>自体の機能を活用することで、「ためにする文書化」（手段の自己目的化）を避けることにしましょう。</p>

<pre><code class="perl">all_pod_coverage_ok(
    {
        also_private => [qw(
            BUILDARGS
            BUILD
            DEMOLISH
        )],
    },
);</code></pre>

<p>具体例としては、拙作<a href="http://github.com/gardejo/p5-dbicx-modeler-generator"><code>DBICx::Modeler::Generator</code></a>の開発者テストである<a href="http://github.com/gardejo/p5-dbicx-modeler-generator/blob/master/xt/pod_coverage.t"><code>xt/pod_coverage.t</code></a>などを挙げておきます。</p>

<p>なお、Kwaliteeを高くすることなどを目的とした「やせ我慢」について以下で補足しておきます。</p>
]]>
        <![CDATA[<h2>嗚呼、やせ我慢</h2>

<h3>Kwalitee対策</h3>

<p>ディストリビューションの品質を測る一指標であるKwaliteeを向上するためには、若干バッドノウハウ気味な工夫を強いられる場合があります。</p>

<p>例えば上記の<code>use strict</code>絡みでは、<code>Module::CPANTS::Analyse</code> 0.85および<code>Test::Kwalitee</code> 1.01の状態では、回避策を見出せませんでした。従って、冗長なようですが<code>use strict</code>（と<code>use warnings</code>）を明示的にコードに書くことで無理矢理都合を付けています。</p>

<h3><code>Devel::Cover</code>対策</h3>

<p><code>Devel::Cover</code> 0.64, <code>Pod::Coverage</code> 0.20, <code>Test::Pod::Coverage</code> 1.08の環境では、本稿で折角対策したはずのメソッド説明の省略が引っ掛かってしまいます。</p>

<p>ただ、これは何とか出来そうな予感がするので、時間のあるときにでも調べてみたいと思います。</p>

<h3>やせ我慢は程々に</h3>

<p>無理にバッドノウハウを重ねても、「ためにする対策」に陥ってしまいかねません。そうすると、無理のあるコードを書いてしまうことになります。</p>

<p>例えば<code>Devel::Cover</code>のPOD網羅率などは、<code>BUILD()</code>の説明を書くことによってドキュメントの焦点がぼやけてしまい、かえってユーザーにとって害をなしてしまうとも考えられませんでしょうか。</p>

<p>牧さん(lestrratさん)も『モダンPerl入門』p.234で</p>

<blockquote>
  <p>そもそも再現不可能な状況もあり得るのでカバレッジ100%という数値にこだわる必要はありません</p>
</blockquote>

<p>と言明しているように、こうした箇所で無理に数値を稼ぐ必要はないはずです。</p>

<p>負担のない範囲で、かつ、将来に亘る保守を妨げない範囲に限って細々と対策することとして、その域を超えるような対策は素直に諦めるのが良いと思います。</p>

<h2>脱・慈善事業</h2>

<p>こうした「ためにする文書化」は、無駄で無益であるばかりでなくて有害ですらあります。仕事以外ではやりたくないですね。仕事でもやりたくないというのが本音ですが、私は建前を前面に押し出している小心者です。しかしながらこのブログの所在は会社に露見しているので、週明け頃に私の席が無くなっている可能性があります。</p>

<p>私も以前はこうした<em>雇用創出</em>的な意味合いすら透けて見える慣行（関連情報：「VBAを使うのはずるい」で有名な「<a href="http://okwave.jp/qa5419623.html">マクロを組んで作業するのは実力ではないですか？</a>」）を打ち破ろうとしたことがあります。開発・運用費の締め付けが厳しいという割に、こうした慈善事業を営むようなお茶目な会社ではいけない、筋肉質な会社にならなければならない、などと。しかし金融ユーザー系システム子会社というものは石橋を叩いても渡らないものなのか、私の説得力の欠乏によるものなのか、多分後者だとは思うのですが、ともかく諦めざるを得ないということがありました。</p>

<p>「ためにする文書化」を避けられる現場では、焦点を絞った文書化を是非試みてください。</p>
]]>
    </content>
</entry>

<entry>
    <title>Perlクラスのアンロード方法(Class::Unload使用版)</title>
    <link rel="alternate" type="text/html" href="http://blog.eorzea.asia/2009/11/post_81.html" />
    <id>tag:blog.eorzea.asia,2009://1.81</id>

    <published>2009-11-28T04:08:55Z</published>
    <updated>2009-11-28T04:29:09Z</updated>

    <summary>Perlでクラス（モジュール）をアンロードする方法として、Class::Unlo...</summary>
    <author>
        <name>Gardejo</name>
        
    </author>
    
        <category term="雑記" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="cpan" label="CPAN" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="Perl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://blog.eorzea.asia/">
        <![CDATA[<p>Perlでクラス（モジュール）をアンロードする方法として、<a href="http://search.cpan.org/perldoc?Class::Unload"><code>Class::Unload</code></a>を使っています。</p>

<pre><code class="perl">Class::Unload->unload('Some::Unneeded::Class');</code></pre>

<p>当初、<a href="http://d.hatena.ne.jp/perlcodesample/">木本さん(perlcodesampleさん)</a>による「<a href="http://d.hatena.ne.jp/perlcodesample/20091101/1246274997">クラスをアンロードする方法</a>」の記事や、そこで言及されている<a href="http://search.cpan.org/perldoc?Class::MOP::Class"><code>Class::MOP::Class::DESTROY()</code></a>を参考にして、以下のようなアンロードメソッドも書いてみました。その後、用途に適合する<code>Class::Unload</code>モジュールがCPANで公開されていることが分かったので、自分の場合はこれを活用させていただこうと思った次第です。</p>

<p>いつの日か<code>Class::Unload</code>がどうしても使えない場面に立ち会ってしまったら、これを引っ張り出してこようと思います。「<a href="http://slashdot.jp/~taro-nishino/journal/493208">だが、私はCPANを使えない！</a>」の全ての処方箋が通用しないという、あまりぞっとしない場面ですが......。</p>

<pre><code class="perl">sub _unload_class {
    my ($self, $class) = @_;

    my @route_to_class = split '::', $class;

    # unload class in target library which is dump target of generated classes
    # cf. http://d.hatena.ne.jp/perlcodesample/20091101/1246274997
    # below codes stolen from Class::MOP::Class::DESTROY()
    {
        no strict 'refs';

        # delete inheritance information from @ISA
        @{
            $class . '::ISA'
        } = ();

        # delete class symbol from symbol table
        %{
            $class . '::'
        } = ();

        # delete class symbol from upper namespace
        delete ${
            join '::', @route_to_class[0 .. $#route_to_class - 1], q{}
        }{
            $route_to_class[-1] . '::'
        };

        # delete loading information
        delete $INC{
            (join '/', @route_to_class ) . '.pm'
        };
    }

    return;
}</code></pre>

<p>なお、上記はとあるクラスのメソッドとして実装していますが、<code>$self</code>は使っていないので、単なるサブルーチンにも出来ます。</p>

<p>ところで、普通に暮らしているだけではクラスをアンロードしたいと思う場合が殆ど全くありません。アンロードしたいという稀少な事例の一つとして、拙作の<a href="http://github.com/gardejo/p5-dbicx-modeler-generator"><code>DBICx::Modeler::Generator</code></a>でクラスをリロードするという例を掲げておきます（該当箇所は<a href="http://github.com/gardejo/p5-dbicx-modeler-generator/commit/fcf4b0de4e84b94d8f6a908bb23f9192f6a5eec7"><code>fcf4b0de...</code>コミット</a>に於ける<a href="http://github.com/gardejo/p5-dbicx-modeler-generator/blob/fcf4b0de4e84b94d8f6a908bb23f9192f6a5eec7/lib/DBICx/Modeler/Generator/Class.pm#L147"><code>DBICx::Modeler::Generator::Class</code>の147行目</a>です）。</p>

<p>このモジュールについては稿を改めてご紹介するつもりです。</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Perlでtrim(さらに完全版)</title>
    <link rel="alternate" type="text/html" href="http://blog.eorzea.asia/2009/11/post_80.html" />
    <id>tag:blog.eorzea.asia,2009://1.80</id>

    <published>2009-11-25T03:30:37Z</published>
    <updated>2009-11-28T04:06:50Z</updated>

    <summary>「perl で trim(完全版)」や「ハッシュ変数に存在しないキーを指定した場...</summary>
    <author>
        <name>Gardejo</name>
        
    </author>
    
        <category term="雑記" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="perl" label="Perl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://blog.eorzea.asia/">
        <![CDATA[<p>「<a href="http://yamamotoplog.blog38.fc2.com/blog-entry-2.html">perl で trim(完全版)</a>」や「<a href="http://d.hatena.ne.jp/zetta1985/20091110/1257867584">ハッシュ変数に存在しないキーを指定した場合の値は何？</a>」という記事をはてブで拝見しました。Perlでいかにtrimする（前後の空白を取り除く）か、という命題です。しかし、残念なことに、文字コードによってはこれでもまだ完全ではありません。</p>

<ul>
<li>モダンなPerlでは、プログラム内部では文字列の文字コードをUTF-8で扱い、必要に応じて入力時にデコード/出力時にエンコードする方法が一般的です。</li>
<li>こうした常套句については、コードスニペットをコピペするより、CPANモジュールを出来るだけ使うと好ましいです。理由は「<a href="http://d.hatena.ne.jp/tokuhirom/20090321/1237629165">かなり使えるPerl正規表現のまとめ</a>」の通り。今回の場合、<a href="http://search.cpan.org/perldoc?String::Util"><code>String::Util</code></a>の<code>trim()</code>が使えます。</li>
</ul>

<p>ということで、モダンに<code>trim</code>する場合には、以下のように書けます。</p>

<pre><code class="perl">use strict;
use warnings;

use utf8;

use String::Util qw(trim);
use Test::More;

# half-width space : 半角スペース
is trim(' foo'),  'foo' => 'half prefix';    # 接頭スペース
is trim('bar '),  'bar' => 'half suffix';    # 接尾スペース
is trim(' baz '), 'baz' => 'half circumfix'; # 接周スペース

# full-width space : 全角スペース
is trim('　foo'),   'foo' => 'full prefix';
is trim('bar　'),   'bar' => 'full suffix';
is trim('　baz　'), 'baz' => 'full circumfix';

# 両対応
is trim('　 foo'),    'foo' => 'both prefix';
is trim('bar 　'),    'bar' => 'both suffix';
is trim('　 baz 　'), 'baz' => 'both circumfix';

done_testing();
__END__</code></pre>

<p><code>use utf8</code>しつつUTF-8でテストスクリプトを保存することで、全角スペースも（<code>trim()</code>の中でも使われている正規表現である）<code>\s</code>に該当するようになります。</p>

<p>実際にアプリケーションで使う場合には、<a href="http://search.cpan.org/perldoc?Encode"><code>Encode</code></a>を使って外から来た文字列は<code>decode()</code>して、外に出す文字列は（必要に応じて）<code>encode()</code>することになります。出力はアプリ作者側でどうにでも出来るので、特に指定する必要がない場合にはUTF-8のままで問題ないでしょう。日本の携帯電話向けには、Shift-JISなどと適宜変えることになります。入力側は<a href="http://search.cpan.org/perldoc?Encode::Guess"><code>Encode::Guess</code></a>辺りで日和っておくといい感じです。</p>

<p>勿論、モダンな環境を使えない場合や、CPANモジュールが使えない場合（実際は「<a href="http://slashdot.jp/~taro-nishino/journal/493208">だが、私はCPANを使えない！</a>」の通り、あまりないです）も多々あるわけで、そうした場合にはトラックバック先に挙げられているような手法を使うのが良いと思います。他にも、「<a href="http://d.hatena.ne.jp/chaichanPaPa/20071213/1197549259">PerlでTrimする！</a>」という記事もあります。</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Mooseロールに実装したメソッドをmemoizeする方法</title>
    <link rel="alternate" type="text/html" href="http://blog.eorzea.asia/2009/11/post_79.html" />
    <id>tag:blog.eorzea.asia,2009://1.79</id>

    <published>2009-11-10T16:43:38Z</published>
    <updated>2009-11-12T15:43:19Z</updated>

    <summary>Mooseクラスでのクラス定数は、MooseX::ClassAttributeで...</summary>
    <author>
        <name>Gardejo</name>
        
    </author>
    
        <category term="開発日誌" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="moosemouse" label="Moose/Mouse" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="Perl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://blog.eorzea.asia/">
        <![CDATA[<p>Mooseクラスでのクラス定数は、<code>MooseX::ClassAttribute</code>で定義する方法もありますが、素直なのはクラスメソッドとして実装してしまうことでしょう。これならば、ロールとの相性も良いです。</p>

<p>しかし、クラス定数（のように使うクラスメソッドの戻り値）が単純な値であればともかく、何かの値を元に計算して導出するような代物だった場合、クラス定数（のように......以下略）を使う度に計算されたのではたまりません。</p>

<p>こうした場合には、<a href="http://search.cpan.org/perldoc?Memoize"><code>Memoize</code></a>によるメモ化(memoization)が定番の処方箋となります。また、（もはやメモ化の文脈での例としては定番である）フィボナッチ数の計算など、クラス定数として使うものでないメソッドについても、同様にメモ化は強力な最適化方法論です。</p>

<p>Mooseクラスでは単純に<code>Memoize</code>モジュールを使えば良いのですが、Mooseロールでは少々込み入った手順で使う必要があることが分かったので、備忘録的に書いておきます。</p>
]]>
        <![CDATA[<h2>Mooseクラスにあるメソッドのメモ化</h2>

<p>まず、Mooseクラスの例です。素直に<code>memoize</code>関数を使えます。</p>

<pre><code class="perl">{
    package Foo;

    use Moose;
    use Memoize;

    use namespace::clean -except => [qw(meta)];

    memoize qw(bar);

    sub bar {
        warn "bar\n";
        return;
    }

    __PACKAGE__->meta->make_immutable;
}
{
    package main;

    my $foo = Foo->new;
    $foo->bar;
    $foo->bar;
}</code></pre>

<p><a href="http://search.cpan.org/perldoc?Attribute::Memoize"><code>Attribute::Memoize</code></a>による<code>Memoize</code>アトリビュートを使うことも可能です。なお、大変こんがらがり易いのですが、<code>Memoize</code>アトリビュートというのはMooseのアトリビュートではなくて、Perlの（サブルーチンや変数に付与する）アトリビュートです。</p>

<pre><code class="perl"># ...

    use Moose;
    use Attribute::Memoize; # またはuse Attribute::Util qw(Memoize);

    use namespace::clean -except => [qw(meta)];

    sub bar : Memoize {
        warn "bar\n";
        return;
    }

# ...</code></pre>

<h2>Mooseロールにあるメソッドのメモ化</h2>

<h3>ロール消費クラスからメソッドが見えない</h3>

<p>ロールでは単純には行きません。以下は<code>Can't locate object method "bar" via package "Foo"</code>という例外を送出します。もう少し正確に定義すると、<code>Foo-&gt;meta-&gt;has_method('bar')</code>は偽になります。ロール内でメモ化したメソッドは、ロールを消費するクラスからは見えない状態にあるのです。</p>

<pre><code class="perl">{
    package FooBase;

    use Moose::Role;
    use Memoize;

    use namespace::clean;

    memoize qw(bar);

    sub bar {
        warn "bar\n";
        return;
    }

    1;
}
{
    package Foo;

    use Moose;

    use namespace::clean -except => [qw(meta)];

    with qw(
        FooBase
    );

    __PACKAGE__->meta->make_immutable;
}
{
    package main;

    my $foo = Foo->new;
    $foo->bar;
    $foo->bar;
}</code></pre>

<h3><code>memoize</code>にサブルーチンリファレンスを設定する</h3>

<p>上記のように嵌ったのでググってみたところ、<code>moose@perl.org</code>メーリングリストで<a href="http://thread.gmane.org/gmane.comp.lang.perl.moose/793/focus=797">Memoizing role methods</a>という、そのものずばりの質疑応答がありました。</p>

<p>有名なMSTことMatt S Troutさんによると、</p>

<ol>
<li><code>Memoize</code>のマニュアルには、<code>memoize</code>関数にはメソッド名だけでなくサブルーチンリファレンスも渡せると書いてある</li>
<li><code>memoize</code>関数の戻り値として、メモ化でラッピングしたサブルーチンリファレンスが返るとも書いてある</li>
<li><code>__PACKAGE__-&gt;meta-&gt;add_method('foo_method' =&gt; memoize(sub { ... }));</code>とすれば、メモ化ラッピングサブルーチンに名前を付けて、消費元のクラス(consumer class)にメソッドを生やせる</li>
<li>もしくは<code>memoize('foo_method')</code>の戻り値であるサブルーチンリファレンスを<a href="http://search.cpan.org/perldoc?Sub::Name"><code>Sub::Name</code></a>の<code>subname</code>に食わせることで、元のメソッド名を乗っ取って、メモ化ラッピングサブルーチン自体が呼ばれるようにすることが出来る</li>
</ol>

<p>ということです。</p>

<p><code>subname</code>の戻り値をさらにグロブリファレンスに入れる理由は、<code>Sub::Name</code>のPODに書いてあります。おまじないだと思って書くことにしましょう。</p>

<h3>現在の私の実装</h3>

<p>上記を踏まえて、私は現在のところ以下のように実装しています。別の話題（別途記事を設ける予定の「実行時まで遅延させてMooseの型を生成・適用する方法」）の実現可能性調査で使った<a href="http://gist.github.com/230058">Gist: #230058</a>から例示します。</p>

<pre><code class="perl"># ...

sub _memoize {
    no strict 'refs';
    foreach my $method (qw(
        _numbers            _names
        _names_to_numbers   _numbers_to_names
        to_number           to_name
        maximum_number      maximum_name
        minimum_number      minimum_name
    )) {
        *{$method} = subname __PACKAGE__ . '::' . $method => memoize($method);
    }
}

__PACKAGE__->_memoize;

# ...</code></pre>

<p>メモ化したい対象を<code>foreach</code>のリストに突っ込むだけで、後はいい感じに動いてくれます。</p>

<h2>Mooseロールにあるメソッドに<code>Memoize</code>アトリビュートを付与する</h2>

<p>これだけでも基本的には満足出来るのですが、メモ化するメソッドの一覧を書くことは、少々面倒です。</p>

<p>希望としては、メソッド側に<code>Memoize</code>アトリビュートを付与しつつ、各メソッドを列挙することなしに名前空間のマジックに連携させることです。</p>

<h3>メソッドに<code>Memoize</code>アトリビュートを付与すること自体は可能</h3>

<p>まず、メソッド側に<code>Memoize</code>アトリビュートを付与すること自体が出来る、という確認です。</p>

<pre><code class="perl"># ...

sub _memoize {
    no strict 'refs';
    foreach my $method_name (qw(
        _numbers            _names
        _names_to_numbers   _numbers_to_names
        to_number           to_name
        maximum_number      maximum_name
        minimum_number      minimum_name
    )) {
        *{$method} = subname __PACKAGE__ . '::' . $method => \&{$method};
    }
}

sub _numbers : Memoize {
    # ...
}

__PACKAGE__->_memoize;

# ...</code></pre>

<p>これで問題なく想定の挙動をしてくれます。しかし、これでは何の解決にもなっていませんね。かえって、各メソッドと<code>_memoize</code>メソッドの両方でメモ化対象を指定することになるだけ、多重保守の愚を犯してしまいます。<a href="http://ja.wikipedia.org/wiki/Don%27t_repeat_yourself">DRY</a>でないということです。</p>

<h3>メソッドに<code>Memoize</code>アトリビュートが付与されているかを調査する</h3>

<p>メソッド側で<code>Memoize</code>アトリビュートを付与しさえすれば、後は何もしなくて良い......ということが理想です。そのためには、<code>_memoize</code>メソッドに於いて全メソッドを見て回って、各々に<code>Memoize</code>アトリビュートが付いているかどうかを確認し、付いていれば<code>subname</code>の流れに乗る、ということが出来れば良いわけです。</p>

<pre><code class="perl"># ...

use attributes qw();            # 流石にgetという名前はインポートしたくない
use List::MoreUtils qw(any);    # でもanyはいいんです（オレオレ二枚舌基準）

# ...

sub _memoize {
    my $clss = shift;

    foreach my $method ($class->meta->get_all_methods) {
        no strict 'refs';
        *{ $method->name } = subname $class . '::' . $method->name
            => $method->body
                if any { $_ eq 'Memoize' } attributes::get($method->body);
    }

}

# ...</code></pre>

<p>ところが、上記の実装は動きません。ロールには<code>meta</code>メソッドがない（ロールは<code>Moose::Object</code>を持っていない）ためです。</p>

<p>それでは、ロールを消費するクラスのメタオブジェクトを見ようとすると、<code>$consumer_class-&gt;meta</code>となるようにロールを消費するクラスの側で<code>__PACKAGE__-&gt;_memoize</code>する方法などが考えられます。</p>

<p>しかしその案も駄目です。クラス側で<code>_memoize</code>を呼んだ時には、既にロールはコンパイルされていますので、ロールで<code>Memoize</code>アトリビュートを付けたメソッドは<code>foreach</code>のリストには入ってきません。</p>

<p>なお、ここまでしれっと書いていますが、そもそも<code>attributes::get</code>は組み込みアトリビュート(<code>locked</code>, <code>method</code>など)以外のアトリビュートが帰ってこないようです。従って、実はメソッドが<code>Memoize</code>アトリビュート付きかどうかを判別する方法が、本日現在の私には分からないというお粗末な事情があります。</p>

<h3>サブルーチン定義時に何とかMemoizeする</h3>

<p>後からメソッドを洗うことを諦め、メソッドを定義した時点でメモ化しつつ<code>subname</code>の仕組みに乗っかる案もありました。</p>

<pre><code class="perl"># ...

*foo = subname __PACKAGE__ . '::foo' => sub : Memoize {
    # foo本来の実装
};

*bar = subname __PACKAGE__ . '::bar' => sub : Memoize {
    # bar本来の実装
};

# ...</code></pre>

<p>しかし、無名サブルーチンへのアトリビュートの適用は出来ない（と理解している）ため、これも動きません。</p>

<p>ここまで来れば別に<code>Attribute::Memoize</code>を使わずとも良いわけで、以下のような形でなら定義出来ます。周り巡って出発地点に戻ったような、少々異様なコードになりました。</p>

<pre><code class="perl"># ...

{
    no warnings 'once';
    *foo = subname __PACKAGE__ . '::foo' => memoize(sub {
        # foo本来の実装
    });

    *bar = subname __PACKAGE__ . '::bar' => memoize(sub {
        # bar本来の実装
    });
}

# ...</code></pre>

<p>だったら素直に以下のようにした方が直感的かも知れません。いずれにせよ微妙ですが......。</p>

<pre><code class="perl"># ...

{
    no warnings 'once';
    *foo = subname __PACKAGE__ . '::foo' => \&foo;
    sub foo : Memoize {
        # foo本来の実装
    }

    *bar = subname __PACKAGE__ . '::bar' => \&bar;
    sub bar : Memoize {
        # bar本来の実装
    }
}

# ...</code></pre>

<h3>まとめ ～ 敗北宣言</h3>

<p>開き直ってロールを消費するクラス側でメモ化してしまう手もありますが、それでもやはりDRYではありません。Perlのアトリビュート周りも、MooseやClass::MOPの奥深い部分も、私は殆ど理解せずにブラックボックス的に使ってしまっているので、もう少し勉強をしてみたいです。</p>

<p>MSTさんも「<code>Memoize</code>のマニュアルをちゃんと読まない人達のために、<code>Moose</code>のドキュメントに追記が必要ですか？」と記しているように、もしかしたらご立腹されているのかも知れません。ごめんなさい、ちゃんとドキュメントを読みます。</p>

<p>機会があったら試行錯誤して雪辱を果たそうと思います。</p>
]]>
    </content>
</entry>

<entry>
    <title>Mooseクラスのコンストラクター引数でハッシュとハッシュリファレンスを同一視する方法</title>
    <link rel="alternate" type="text/html" href="http://blog.eorzea.asia/2009/11/post_78.html" />
    <id>tag:blog.eorzea.asia,2009://1.78</id>

    <published>2009-11-10T16:34:21Z</published>
    <updated>2009-11-11T15:17:03Z</updated>

    <summary>Mooseクラスの生成時に、コンストラクター引数として与えられたハッシュまたはハ...</summary>
    <author>
        <name>Gardejo</name>
        
    </author>
    
        <category term="開発日誌" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="moosemouse" label="Moose/Mouse" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="Perl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://blog.eorzea.asia/">
        <![CDATA[<p>Mooseクラスの生成時に、コンストラクター引数として与えられたハッシュまたはハッシュリファレンスに着目して処理を行いたい場合があります。</p>

<p>例えば、初期化ハッシュキーを跨いだ検証などが挙げられます。<a href="http://blog.eorzea.asia/2009/10/post_72.html"><code>trigger</code>の使い方についての記事</a>で説明用に作った、<a href="http://gist.github.com/raw/211073/b22f2404fca8398fe328775484978843ac9d233b/era_role.pl">元号と西暦のアトリビュートを持つ昭和クラス</a>で想定してみます。</p>

<p>元号と西暦の両方を指定された場合、その両方のアトリビュートが未指定になります。<code>undef</code>という値が入っているのではなく、<code>has_imperial_era</code>などの<code>predicate</code>メソッドの戻り値が偽であるという意味です。</p>

<p>それでは困るので、コンストラクター引数に指定するのは元号と西暦のどちらか一方のみに制限する......という要件が出て来たこととします。その場合、ハッシュとハッシュリファレンスの両方でキーを見付ける処理を<code>BUILDARGS</code>に書くのではなく、親クラス(最終的な親は<code>Moose::Object</code>)の<code>BUILDARGS</code>を呼ぶようにすると、素直に書けます。</p>

<pre><code class="perl"># ...

around BUILDARGS => sub {
    my $next  = shift;
    my $class = shift;
    # ここでは@_はハッシュかも知れないしハッシュリファレンスかも知れない

    # 親クラス(Moose::Object)のハッシュリファレンス化はBUILDARGSに任せる
    my $init_args = $class->$next(@_);  # ここではハッシュリファレンス

    confess 'Initialization argument must be '
          . 'any one of imperial_era or christian_era'
            if exists $init_args->{imperial_era} 
            && exists $init_args->{christian_era};

    return $init_args;
};

# ...</code></pre>

<p>こんなものは常識なのでしょうけれども、意外とこういう初歩的なところの認識が甘くて、今までは（後述するように）ハッシュリファレンスのみを食べるような偏屈APIを撒き散らしていました。反省反省。</p>

<p>以下は補足情報です。</p>
]]>
        <![CDATA[<h2>メソッドモディファイヤーを使わない場合</h2>

<p>親クラス(<code>Moose::Object</code>)の<code>BUILDARGS</code>を修飾せず、自クラスで<code>BUILDARGS</code>クラスメソッドを定義しても、親クラスの<code>BUILDARGS</code>を呼べば同じ事です。</p>

<pre><code class="perl"># ...

sub BUILDARGS {
    my $class = shift;

    my $init_args = $class->SUPER::BUILDARGS(@_);

    confess 'Initialization argument must be '
          . 'any one of imperial_era or christian_era'
            if exists $init_args->{imperial_era} 
            && exists $init_args->{christian_era};

    return $init_args;
}

# ...</code></pre>

<h2>親の<code>BUILDARGS</code>を使わない場合</h2>

<p>Mooseのコンストラクターは、デフォルトではハッシュリファレンスかハッシュを受け付けます。自分のBUILDARGSクラスメソッド内で、コンストラクター引数がハッシュリファレンスであるかハッシュであるかを判断する処理を書くのは、とても面倒です。</p>

<pre><code class="perl"># ...

sub BUILDARGS {
    my $class = shift;

    # @_がハッシュであるかハッシュリファレンスであるかを判別する処理は、
    # Moose::Object::BUILDARGSと同じことなので面倒
    # ...
}

# ...</code></pre>

<p>自分のクラスではコンストラクター引数にハッシュリファレンスのみを受け付ける（ハッシュは受け付けない）と決めてしまえば、例えば以下のようにも書けるでしょう。</p>

<pre><code class="perl"># ...

sub BUILDARGS {
    my $class = shift;

    if (@_ == 1 && ref $_[0] eq 'HASH') {
        confess 'Initialization argument must be '
              . 'any one of imperial_era or christian_era'
                if exists $_[0]->{imperial_era} 
                && exists $_[0]->{christian_era};
        return $_[0];   # もしくは$class->SUPER::BUILDARGS($_[0]);
    }
    else {
        return $class->SUPER::BUILDARGS(@_);
    }
}

# ...</code></pre>

<p>ただ、ハッシュを敢えて拒否するような理由がない限りは、費やすべき労力はそれほど変わらないので、素直に<code>Moose::Object::BUILDARGS</code>を呼んだ方が良いと考えます。</p>

<h2>余談: ハッシュやハッシュリファレンス以外の引数を使いたい場合</h2>

<p><code>Moose::Manual::Construction</code>では、それ以外の場合（例えばスカラー値など）の対処法が書かれています。今回の要件とは違いますが、後輩への説明用に余談として述べておきます。</p>

<p><code>Person</code>クラスは、米国在住者の背番号（つまりは一意に識別出来る、<code>id</code>）である社会保障番号（<code>ssn</code> : Social Security Number）の文字列を渡すだけでオブジェクトを生成してくれると便利だ、という例です。</p>

<pre><code class="perl"># ...

has 'ssn' => (  # 社会保障番号
    is          => 'rw',
);

# ...

around BUILDARGS => sub {
    my $next  = shift;
    my $class = shift;

    if (@_ == 1 && ! ref $_[0]) {
        return $class->$next(ssn => $_[0]);
    }
    else {
        return $class->$next(@_);
    }
};

# ...</code></pre>

<p>昔のバージョンの<a href="http://search.cpan.org/perldoc?Moose::Manual::Construction"><code>Moose::Manual::Construction</code></a>では、メソッドモディファイヤーで親を修飾するのではなく、自クラスでBUILDARGSクラスメソッドを実装するように書かれていましたが、これも要は同じ事です。</p>

<pre><code class="perl"># ...

sub BUILDARGS {
    my $class = shift;

    if (@_ == 1 && ! ref $_[0]) {
        return {
            ssn => $_[0],
        };
        # 必要に応じて、以下のようにする方が良いかも知れません
        # $class->SUPER::BUILDARGS({ssn => $_[0]});
    }
    else {
        return $class->SUPER::BUILDARGS(@_);
    }
}

# ...</code></pre>

<h2>余談: <code>BUILD</code>か<code>BUILDARGS</code>か</h2>

<p><code>BUILD</code>の引数は、コンストラクター引数にハッシュを渡そうがハッシュリファレンスを渡そうが、一律にハッシュリファレンスとなっています。従って、技術的には以下のように<code>BUILD</code>でバリデーションロジックを設けることも不可能ではありません。</p>

<pre><code class="perl"># ...

sub BUILD {
    my $self = shift;

    confess 'Initialization argument must be '
          . 'any one of imperial_era or christian_era'
            if exists $_[0]->{imperial_era} 
            && exists $_[0]->{christian_era};

    return;
}

# ...</code></pre>

<p>しかし、既にオブジェクトを作ってしまった後に、そのオブジェクトの初期化変数を検証するのは、順序が逆転しています。おかしな値を拒絶するのは出来るだけ早い段階の方が良いので、今回の場合は<code>BUILDARGS</code>でフックしています。</p>

<p>勿論、生成されたオブジェクトのアトリビュートを跨いだ検証などは、素直に<code>BUILD</code>を使えば良いです。</p>

<p>この辺りは、初期化時に行いたい処理によって、<code>BUILDARGS</code>にフックするのか<code>BUILD</code>にフックするのかを決めれば良いでしょう。迷ったら、早めに死ぬように<code>BUILDARGS</code>を選ぶのが無難です（そして、きちんと検証出来ていることをテストで確かめましょう）。</p>
]]>
    </content>
</entry>

<entry>
    <title>ORMスキーマとドメインモデルを統合する方法・分離する方法</title>
    <link rel="alternate" type="text/html" href="http://blog.eorzea.asia/2009/10/post_76.html" />
    <id>tag:blog.eorzea.asia,2009://1.76</id>

    <published>2009-10-24T09:08:32Z</published>
    <updated>2009-10-25T15:39:54Z</updated>

    <summary>MVCのModelをWAFから切り離しつつ、Modelも（DBとの仲立ちをさせる...</summary>
    <author>
        <name>Gardejo</name>
        
    </author>
    
        <category term="開発日誌" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="dbic" label="DBIC" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="github" label="github" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="model" label="Model" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="moosemouse" label="Moose/Mouse" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="orマッパー" label="O/Rマッパー" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="Perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="waf" label="WAF" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://blog.eorzea.asia/">
        <![CDATA[<p>MVCのModelをWAFから切り離しつつ、Modelも（DBとの仲立ちをさせる）ORM用スキーマと（ビジネスロジックを書く）ドメインモデルとで分けたいと思い、ここ数日調査や試行をしています。私はPoEAAを読んで、かっとなって「どうせ趣味で書くならドメインモデルしかない！」と思い込んでいます。これがまず出発点です。今回の記事は、そのモデルの守備範囲をどうしようか、というお話です。</p>

<p>まず、CatalystなどのWAFからMVCのMを切り離すことについては、牧さん(lestrratさん)の『モダンPerl入門』(pp.116-121)などで明快に解説されています。</p>

<p>次に、サービスクラスとモデルクラスの使い分けについても、dannさんのCatalystCon #1での<a href="http://www.slideshare.net/techmemo/catalyst-367905">CatalystからModelを切り離せ - MVCのMのあるべき姿 -</a>の発表でも言及があります。</p>

<p>それでは、ドメインモデルはDAO/DTOやORMの方面まで面倒を見るべきなのでしょうか。</p>

<p>今回細々と開発しているFF14ユーザー向けウェブサービスである<a href="http://eorzea.asia/amikeco/">Amikeco</a>では、ORMとしてDBIx::Classの使用を想定しています。また、サービスクラスやモデルクラスは、Mooseクラスを想定しています。</p>

<p>というような状態での具体的な実装方法について、調べてみたところいくつかの類型があるので、試行してみての感想を添えて備忘録として書いておきます。</p>

<ol>
<li>MooseクラスでDBIx::Classを継承して、ドメインモデルにスキーマを兼務させる</li>
<li>DBICx::Modelerを使って、スキーマクラスとモデルのMooseクラスを分離する</li>
<li>MooseX::DBICを使う</li>
<li>永続化非対象の情報をどう持つか</li>
<li>番外編: Moosified ORMを使う</li>
<li>まとめ</li>
</ol>
]]>
        <![CDATA[<h2>1. MooseクラスでDBIx::Classを継承して、ドメインモデルにスキーマを兼務させる</h2>

<h3>1.1. 概要 : モデルクラスにスキーマクラスを継承させて兼務させる</h3>

<p>一番定番なのがこれだと思います。モデルクラスにスキーマを継承させて兼務させる方法です。</p>

<p><a href="http://search.cpan.org/perldoc?DBIx::Class::Manual::FAQ#Misc">DBIx::Class::Manual::FAQ</a>でも、<q>How do I store my own (non-db) data in my DBIx::Class objects?</q>として触れられています。</p>

<p>注意点としては、Moose 0.62_02以降では、（警告を回避するために）<code>__PACKAGE__-&gt;meta-&gt;make_immutable(inline_constructor =&gt; 0)</code>することでしょうか。また、非Mooseクラスの継承には<a href="http://search.cpan.org/perldoc?MooseX::NonMoose">MooseX::NonMoose</a>が定番で、牧さんの<a href="http://github.com/lestrrat/pixis">Pixis</a>もこの方法を使っています。</p>

<h3>1.2. 定番の手法</h3>

<p>基本的にはこれが良いと思います。PerlMonksでも<a href="http://www.perlmonks.org/?node_id=757426">DBIx::Class and Moose</a>などのいくつかの議論で話題に上りましたし。</p>

<p>dannさんの発表の通り、単純なCRUD処理であれば生モデルを扱いたいところなので、ドメインモデルとDxOやORMが一緒になっていても違和感はないのかもしれません。巨大なアプリケーションでなく、比較的小さめのアプリケーションを作るには、お手軽さはやはり見逃せません。そもそも、「スキーマと一緒で何か気持ち悪い」という私の主観を無視すれば、巨大なアプリケーションでも有用な手法と言えます。</p>

<h3>1.3. ORM依存性を減らしたい</h3>

<p>しかしやはり私はこれらを分けたいという思いがあります。</p>

<p>まず、特定のDxOやORMに依存した書き方になることは避けたいのです。よしORMを変えようといった場合に、モデル＆スキーマクラスから、スキーマ部分を置換するようなことが必要となります。</p>

<p>勿論、ORMを変えようだなんて、そんなことが実際問題として開発中に起こり得るかというと、あまり考えられません。</p>

<p>さらに、これはDBIx::Class::Schema::Loaderの工夫次第で無視出来ると思います。ZIGOROuさんのはてダにある<a href="http://d.hatena.ne.jp/ZIGOROu/20080318/1205828357">DBIx::Class::Schema::Loaderの手動スキーマ生成、初心者向けチュートリアル</a>の「別のINCにテンプレ」の手法を使えば、最終的に生成されるクラスはともかく、少なくとも開発者が書くファイルでは素のスキーマクラスへ追加する部分（ビジネスロジック等）のみが現れるからです。これは好みの問題だと思います。</p>

<h3>1.4. DBのスキーマの成長を漏らさず取り込みたい、しかも楽に</h3>

<p>私にはもう一つの懸念があって、それはDBIx::Class::Schema::Loaderの実行に制約が起きる文脈があるという点です。例えばDBIx::Class::Rowに生やすカラムの名前が付いたアクセッサーメソッドをモディファイ出来ないという問題です。</p>

<p>これは、DBIx::Class::Schema::Loaderが、生成したスキーマクラスに別のテンプレートを突っ込む際に、そのテンプレートの中身が（perlに）評価されるためです。もう少し噛み砕くと、そのテンプレートの記述だけで一つのPerlクラスとして成立していなければならないという制約があります。</p>

<p>DBIX::Class::Schema::LoaderがDBから引っこ抜いて自動生成したスキーマクラスは、例えば以下の<code>/lib/MyApp/Schema/Foo.pm</code>のようになります。</p>

<pre><code class="perl">package MyApp::Schema::Foo;

use strict;
use warnings;

use base 'DBIx::Class';

__PACKAGE__->load_components("UTF8Columns", "Core");
__PACKAGE__->table("foo");
__PACKAGE__->add_columns(
  "id",
  {
    data_type => "INTEGER",
    default_value => undef,
    is_nullable => 1,
    size => undef,
  },
  "password",
  {
    data_type => "VARCHAR",
    default_value => "''",
    is_nullable => 0,
    size => 255,
  },
);
__PACKAGE__->set_primary_key("id");


# Created by DBIx::Class::Schema::Loader v0.04006 @ 2009-10-25 23:57:56
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:uy8PqmDawAHTTN08+aH+Jw


# You can replace this text with custom content, and it will be preserved on regeneration
1;</code></pre>

<p>そして<code>@INC</code>に追加する、別途用意するテンプレートが以下の<code>/schema/lib/MyApp/Schema/Foo.pm</code>のように書かれていたとします。</p>

<pre><code class="perl">package MyApp::Schema::Foo;

use Moose;
use MooseX::NonMoose;

extends qw(
    DBIx::Class
);

use Digest::SHA qw(sha256_hex);

use namespace::clean -except => [qw(meta)];

has 'hashed_password' => (
    is          => 'ro',
    lazy_build  => 1,
);

sub _build_hashed_password {
    sha256_hex($_[0]->password);
}

after password => sub {
    return
        if @_ > 1;
    $_[0]->clear_hashed_password;
};

__PACKAGE__->meta->make_immutable(inline_constructor => 0);
1;</code></pre>

<p>ここで、<code>__PACKAGE__-&gt;add_columns('password')</code>した段階で、行オブジェクトには<code>password</code>アクセッサーメソッドが生えるのですが、そんなことを知らないテンプレート側では、ベタに<code>after password =&gt; sub { ... }</code>などと書いても、「<code>password</code>なんてメソッドは継承ツリーのどのクラスにもいないよ」(<code>The method 'password' was not found in the inheritance hierarchy for MyApp::Schema::Foo</code>)と怒られる訳なんですね。</p>

<p><ins title="実はテンプレをスキーマにコピペしても動きませんでした。ごめんなさい。" datetime="2009-10-26T00:25:00+09:00"><em>追記</em> : どうも私が使い方を根本的に勘違いしていたようで、まるっとテンプレートをコピペしても<code>password</code>メソッドが見つからないのは変わりませんでした。<code>after id</code>では問題ありません。別のスキーマで、PRIMARY KEY指定したcolumn名に<code>after</code>した時には動いたので、それと混同していました。いずれにせよ、クラス内で<code>use base 'DBIx::Class'</code>した後で再度<code>extends 'DBIx::Class'</code>している箇所などが危険なので、素の<code>DBIx::Class::Schema::Loader</code>では難しいところがあります。ZIGOROuさんの<q>「差分を直に書く方法」</q>であれば問題ないという訳です。</ins></p>

<p>そう何度も頻繁にDBの定義を変えることは考えにくいので、単なる私の杞憂と言ってしまえばそれまでです。しかし私は基本的におっちょこちょいなので、出来ればドメインモデルより奥側の世界は自動生成だけで済ませたいところです。（以前の<a href="http://blog.eorzea.asia/2009/08/post_54.html">ER図描画ツール探しの記事</a>で言及したり、YAPC::Asia 2009の特別研修の特別質疑応答コーナーで牧さんとMillsさんに紹介していただいた）MySQL Workbenchで吐いた<code>CREATE</code>文があれば、スキーマを自動生成しつつ独自実装部もテンプレートからはめ込んむということを、<em>スクリプト一発で</em>やってくれる仕組み（その例は<a href="http://gist.github.com/217006">Gist #217006</a>に上げました）は、是非大事にしたいと思います。</p>

<p>テンプレートの内容を文字列展開するようにDBIx::Class::Schema::Loaderの自作版を作る手もあるかと思い付きましたが、実際に手を動かすのが億劫で、断念しました。</p>

<h2>2. DBICx::Modelerを使って、スキーマクラスとモデルのMooseクラスを分離する</h2>

<h3>2.1. 概要 : スキーマクラスへ被せる皮をモデルクラスに提供する</h3>

<p>なんともわがままというか自己中な考えを書きましたが、それではモデルクラスとスキーマクラスを分けるならば、どのようにすべきでしょうか。</p>

<p>15分くらい、ロールとしてスキーマクラスとの架け橋を造ろうとしていましたが、色々考えなければいけないことが多すぎると思い至りました。</p>

<p>そもそもこんな私の思い自体、何とも自己中でありますけれども、しかしそれほど突飛なことを考えているつもりはなかったので、きっと世界のどこかで誰かがいつか何かを作っているんじゃないか、と思って見つけたのがRobert Krimenさんの<a href="http://search.cpan.org/perldoc?DBICx::Modeler">DBICx::Modeler</a>です。</p>

<p>使い方はテストスクリプトの通りですが、MyApp::Model::Fooモデルクラスで<code>use DBICx::Modeler::Model</code>しておけば、相対するMyApp::Schema::Fooスキーマクラスの行オブジェクト用アクセッサーも使いつつ、自分でアトリビュートだろうがメソッドモディファイヤーだろうが好きに書けるのがいい点です。</p>

<h3>2.2. 分けると精神的には楽</h3>

<p>これにしても結局はDBICx::Modelerに依存してはいるのですが、他のORM用にもこうしたラッパーがあれば、ビジネスロジックとスキーマを峻別したまま、ラッパーの何を使うかだけを切り替えれば対応が出来るという点は見逃せません（そのラッパーをDIする手もあるでしょうし）。</p>

<p>DBIx::Class::Schema::Loaderで<code>MyApp::SchemaとMyApp::Schema::*</code>はばんばん自動生成しつつ、<code>MyApp::Model::*</code>はそれに影響を受けずに悠々と書けるという案配です。</p>

<h3>2.3. Moose 0.90以降の警告を回避する対応</h3>

<p>ところで、Moose 0.90以降だと、DBICx::Modeler 0.004がクローニングを<code>$self-&gt;new</code>で行っている箇所でMooseが警告を出します。将来的には警告ではなくエラーになるので、些細なものですが対応をしてみました。</p>

<ul>
<li><a href="http://github.com/gardejo/dbicx-modeler/commit/5dadb20b3bf1ac36cd05c605bf860d3086d4408f"><code>http://github.com/gardejo/dbicx-modeler/commit/5dadb20b3bf1ac36cd05c605bf860d3086d4408f</code></a></li>
</ul>

<p>要は<code>(blessed $self)-&gt;new</code>に変えただけですが、ともあれpull requestもしてみました。</p>

<blockquote>
  <p>Hello Robert, I updated my branch with the fixing issue where Moose warned against using deprecated cloning. If you like this trivial patch, could you please merge it into your branch?</p>
</blockquote>

<p>ありがたいことにマージをしていただき、DBICx::Modeler 0.005としてCPANに上げていただいています。実はCPANモジュールにパッチをお送りするのはこれが初めてで、些細な差分ですが採用いただいてとても嬉しかったです。</p>

<p>後になって思えば、本件対応用のトピックブランチを切った方が良かったかと、少々後悔しています。また、2行だけ差し替えてテストケースを2個追加したという今回の場合、</p>

<ul>
<li>RTチケットを切ってパッチを送ることで、問題の所在やその対応を（衆目に晒して）是非を問うのが良いのか</li>
<li>開発に直結している方法として、githubでforkしてcommitしてpushしてpull requestした方が良いのか</li>
<li>両方した方が良いのか</li>
</ul>

<p>といった悩みもあります。取り敢えず2番目の手法を選びましたが、今後もどうすべきかを考えたいところです。</p>

<h2>3. MooseX::DBICを使う</h2>

<p>Stevan Littleさん(stevanさん)の<a href="http://github.com/stevan/moosex-dbic/">MooseX::DBIC</a>というモジュールもあります。2009年10月23日現在、まだCPANには上がっていませんが、これもgithub上でリポジトリが公開されています。</p>

<p>これは1.と同じ類型で、スキーマクラスとMooseモデルクラスを兼務させるためのものです。</p>

<p>もし1.を考えている場合、このMooseX::DBICが成長すれば、有力な選択肢となるかも知れません。こちらも大変期待の持てる作品です。</p>

<h2>4. 永続化非対象の情報をどう持つか</h2>

<p>例えば、<code>forename</code>（名）と<code>surname</code>（姓）がDBに格納される場合で、<code>fullname</code>（氏名）をどう持つか、という備考です。</p>

<h3>4.1. 手動<code>trigger</code>を<code>after</code>で使う</h3>

<p>これと同じような例を<a href="http://blog.eorzea.asia/2009/10/post_72.html"><code>trigger</code>についての備忘録</a>で記述しましたが、今回は<code>trigger</code>は使えません。そもそも<code>forename</code>や<code>surname</code>はDBIx::Class::Rowに生えたアクセッサーメソッドであって、モデルであるMooseクラスのアトリビュートとして存在している訳ではないからです。</p>

<p>ということで、<code>after</code>を使って、自前でアクセッサーがゲッターとして使われたのかセッターとして使われたのかを（引数の個数を見て）判断する必要があるわけです。</p>

<h3>4.2. DBIx::Class::VirtualColumnsを使う</h3>

<p>無理にアトリビュートで持とうとしなくても、ORM側で「他の列と同じように読み書き出来るけど、永続化はしない」という、融通を利かせることが出来ます。それが<a href="http://search.cpan.org/perldoc?DBIx::Class::VirtualColumns">DBIx::Class::VirtualColumns</a>という素敵なモジュールです。</p>

<p>例によってPixisを読んで知ったモジュールですが、これを活用することでも、素直にDB外の情報を持ち回ることが出来て、いい感じに実装出来そうです。</p>

<h3>4.3. 個別のメソッドとして実装する</h3>

<p>例えば名と姓を合体させて氏名を作る処理は、毎回導出しても悪いわけではありません。勿論性能面での問題等は考慮が必要ですが、単に<code>sub fullname { $_[0]-&gt;forename . q{ } . $_[0]-&gt;surname }</code>してしまえば事足りる場合だって少なくないと思います。</p>

<p>氏名を求めることを振る舞いと見るか、氏名という導出情報を行が持つというように見るか次第で、私は後者の説に立つので4.1.か4.2.を採用したいと考えています。</p>

<h2>5. 番外編: Moosified ORMを使う</h2>

<p>これまでDBIC前提で書いてきましたが、Mooseで書かれたORMを活用する手もあります。これなら、一緒にしようが分けようが、諸々のことを考えなくて済みます。</p>

<p><a href="http://search.cpan.org/perldoc?KiokuDB">KiokuDB</a>や<a href="http://search.cpan.org/perldoc?Fey::ORM">Fey::ORM</a>など、面白そうなORMがあります。まだ邦語情報が少ないのですが、すぐにアプリで使わないにしても、少しずつこれらの中身も知っておきたいと思っています。</p>

<h2>6. まとめ</h2>

<p>結局、まずは分離しようということで、DBICx::Modelerにお世話になってプロトタイピングしてみるつもりです。</p>

<p>現在はまだ実現可能性調査の段階なので、この記事は大きなアプリケーションの開発を通じて得られるであろう知見が全く反映されていません。従って、素直にDBIC（やその拡張）の機能を活用した方法が一番だということになるかも知れません。</p>

<p>そもそも金融ユー子なのにエンタープライズアプリケーションの何たるかをろくに理解していないので、もっとちゃんとPoEAAを読もうと思います。</p>
]]>
    </content>
</entry>

<entry>
    <title>DIコンテナーの採用は一種の代償行動なのかも知れません</title>
    <link rel="alternate" type="text/html" href="http://blog.eorzea.asia/2009/10/post_75.html" />
    <id>tag:blog.eorzea.asia,2009://1.75</id>

    <published>2009-10-21T16:24:24Z</published>
    <updated>2009-10-21T16:40:39Z</updated>

    <summary>前の記事の論旨が微妙に（かなり？）飛躍していることに気付いたので補足しておきます...</summary>
    <author>
        <name>Gardejo</name>
        
    </author>
    
        <category term="雑記" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="di" label="DI" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="Perl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://blog.eorzea.asia/">
        <![CDATA[<p><a href="http://blog.eorzea.asia/2009/10/post_74.html">前の記事</a>の論旨が微妙に（かなり？）飛躍していることに気付いたので補足しておきます。</p>

<p>まず、DIパターンやDIコンテナーを使うことの目的は、直接的には、モジュール間（より具体的には、例えばドメインモデルとORMというようなレイヤー間）の結合性を疎にすることです。</p>

<p>「Mooseのアトリビュートへ依存オブジェクトを持たせることでも疎結合に出来る」というdannさんの指摘（<a href="http://dann.g.hatena.ne.jp/dann/20080915/p1">DIとは何か 番外編 - DIコンテナを使わずにModelのTestabilityを高める方法</a>）が一つの具体例ですが、元々Perlは（動的言語であるので）イントロスペクション（オブジェクトの中身を実行時に参照すること）のみならず実行時のDI自体はお手の物です。従って、DIがなければ死にそうなくらい大変かというと、必ずしもその通りではありません。</p>

<p>ただ、あまり根を詰めずとも試験容易性（テスタビリティー）の向上という利益が得られるという点で、DIコンテナーのお世話になる費用対効果が大きいと判断しました。私は怠け者なのです。</p>

<p>さらに、DI採用によって将来的に（今回は使用を一旦留保した）新進気鋭のモジュールに切り替え易くするという狙いもあります。これは「新進気鋭のモジュールを活用する実装を一旦断念して、定番のモジュールを活用することにした」という自分自身の負い目に対する<a href="http://ja.wikipedia.org/wiki/%E9%98%B2%E8%A1%9B%E6%A9%9F%E5%88%B6#.E7.BD.AE.E3.81.8D.E6.8F.9B.E3.81.88">代償行動</a>のようですが、これこそが今回DIコンテナーのお世話になることに決めた最大の理由だと自己分析しています。</p>

<p>ということで、何故突然DIコンテナーを実用してみようかと思ったのか、その辺りの事情についての補足でした。前段と後段の内容の結節点となるこの補足がないと、何が何だか分かりませんでしたね。補足があっても寝不足気味なので変なことを書いているおそれがありますが。</p>
]]>
        

    </content>
</entry>

</feed>
