<?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>2009-12-31T15:32:09Z</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>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>

<entry>
    <title>開発近況: モジュール群を冒険から安定へ (でもDIコンテナーに着目中)</title>
    <link rel="alternate" type="text/html" href="http://blog.eorzea.asia/2009/10/post_74.html" />
    <id>tag:blog.eorzea.asia,2009://1.74</id>

    <published>2009-10-19T15:04:44Z</published>
    <updated>2009-10-19T17:59:16Z</updated>

    <summary>ここのところPerl勉強日誌的な記事が続いていますが、ff14.nameとff1...</summary>
    <author>
        <name>Gardejo</name>
        
    </author>
    
        <category term="開発日誌" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="breadboard" label="Bread::Board" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="di" label="DI" 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勉強日誌的な記事が続いていますが、<a href="http://ff14.name/">ff14.name</a>と<a href="http://ff14.asia/">ff14.asia</a>の開発は細々と続いています。それはもう申し訳ないほどに細々としていますが......（一方で、「やや真面目なサイト」としてサイドバーに晒してあるエスペラント日本語翻訳システムは、かなり遅滞気味です）。</p>

<p>これらサービスのそもそもの開発動機の一つが自分自身の勉強ということもあって、色々と新進気鋭のモジュールを試しながら使わせていただこうとして出発点を置きましたが、少なからぬ依存モジュールの数々を、新進気鋭のモジュールではなく、定番系のモジュールに切り替えようとしています。これは、定番系の重厚長大モジュールでさえ深く使い込んでないのに、新進気鋭の軽薄短小なモジュールを巧く使いこなせずに開発が遅滞するということが、早すぎる最適化の一類型に当てはまるのではないか、という危惧に由来するものです。最終決定はまだ先ですが、10月20日版の<a href="http://ff14.name/#dependencies">主要依存(予定)モジュール</a>などでは、その辺りの弱気が透けて見えるかも知れません（「or」の前後をかなり入れ替えています）。</p>

<p>具体的には、例えば</p>

<ul>
<li>やっぱりまだまだRDB的な考えからKVS的な考えに切り替えが出来ない私は、Data::Modelではなく、まずはDBIx::Classで一通りを組んでみようと考えを改めました</li>
<li>出来るだけAny::Moose経由でMouseを使うようにしていたのですが、まずはMooseの豊富な拡張モジュール（MooseX::*）にお世話になってプロトタイピングにいそしもうとしました</li>
</ul>

<p>などという点です。</p>

<p>この方針の転換は、すべて私の能力の至らなさによるものです。8月中旬頃まで色々試行錯誤をしていたのですが、色々な使いどころの妙を得ずに開発をしていて、プロトタイピング自体で蹴躓くことが多かったという体験があります。ということで、最初から完成形のアプリケーションを作れるわけでは当然ないにせよ、まずは形を作ってからそれから新進気鋭のモジュールの使用を試みようというような、私の身の丈にあった開発をしようと思います。モジュールそれ自体が冒険的ということでは全くなくて、モジュールを自分が十全に使いこなせないという冒険的な開発を改め、多少なりとも安定的にプロトタイプを作れることを優先するということで。</p>

<p>などと書いた舌の根も乾かぬうちにというか打鍵音も静まらぬうちに......。</p>
]]>
        <![CDATA[<h2>DI（dependency injection : 依存性注入）の魅力に触れてみました</h2>

<p>実は今回、上述の「主要依存(予定)モジュール」に、牧さん(lestrratさん)のDIコンテナーである<a href="http://search.cpan.org/perldoc?Orochi">Orochi</a>をしれっと差し込んでいます。この辺り、「身の丈に合ったモジュールの組み合わせを使う」方針の不徹底さが知れようものです。ただ、DIコンテナーで疎結合にすると後々楽になりそうなので、（メリットとデメリットは多々あるでしょうが）まずはメリットに着目してみました。</p>

<p>Orochiは、4月のYokohama.pmテクニカルトークでお話があった、<a href="http://github.com/lestrrat/bread-board">Bread::Boardの牧さんfork版</a>の流れをくむものだと理解しています。（同梱の）MooseX::Orochiでいい感じに定義出来る優れものです。</p>

<p>COBOLとJavaの会社なのにJavaのDIについて恥ずかしながら知らなかったので、当時はググって以下のような情報源に当たりました（殆どdannさんの記事にお世話になっています）。</p>

<ul>
<li><a href="http://catalyst.g.hatena.ne.jp/dann/20080308/1204978139">PerlのDIコンテナ - Bread Board</a></li>
<li><a href="http://catalyst.g.hatena.ne.jp/dann/20080404/1207323076">Catalyst+ DIでアプリケーションのCatalystへの依存を切り離す</a></li>
<li><a href="http://dann.g.hatena.ne.jp/dann/20080911/p1">DI(Dependency Injection)とは - 第1回</a></li>
<li><a href="http://dann.g.hatena.ne.jp/dann/20080913/p1">DI(Dependency Injection)とは - 第2回</a></li>
<li><a href="http://itpro.nikkeibp.co.jp/free/ITPro/OPINION/20050216/156274/">Java開発を変える最新の設計思想「Dependency Injection（DI）」とは </a></li>
</ul>

<p>そのときはBread::Board採用の億劫さが勝ってしまっていたのですが、牧さんのブログで先週金曜の晩に<a href="http://mt.endeworks.jp/d-6/2009/10/things-ive-done-while-using-test-mysqld.html">Test::mysqldとかでテスト走らせる際に行ったいろんな事。</a>という記事で言及があり、日曜辺りからOrochiを触り始めてみました。</p>

<p>そうした結果、比較的手軽に（無理せずに）DIコンテナーを使えることが今回分かって、積極的に使っていこうとしているところです。OrochiのPODに記載してある通り、Bread::Boardが進化すれば、そちらにお世話になることになると思います。</p>
]]>
    </content>
</entry>

<entry>
    <title>Mooseアトリビュートのオプション指定順についての私案</title>
    <link rel="alternate" type="text/html" href="http://blog.eorzea.asia/2009/10/post_73.html" />
    <id>tag:blog.eorzea.asia,2009://1.73</id>

    <published>2009-10-17T07:25:14Z</published>
    <updated>2009-12-23T13:25:21Z</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" />
    <category term="style" label="style" 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>この指定順について、私はこれまで結構場当たり的に決めていました。軸足となるのはやはり<code>Moose::Manual</code>や<code>Moose::Cookbook</code>の例になりますが、一旦整理してオレオレルールというかオレオレガイドラインを考えてみようと思いました。</p>

<p>あまりにも毎回ばらばらだとコードが明快でなくなりますし、その逆で並び順次第でコードがより分かりやすくなるなら、やっておいて損はないものだと思います。</p>

<p>とはいってもこれはあくまで<em>ネタ</em>なので、どうか真に受けないようにしてください。</p>

<p>それでは、Moose 0.92時点でのオプション指定順私案をご紹介します。</p>

<ol>
<li><code>metaclass</code></li>
<li><code>traits</code></li>
<li><code>is</code></li>
<li><code>accessor</code></li>
<li><code>reader</code></li>
<li><code>writer</code></li>
<li><code>isa</code></li>
<li><code>does</code></li>
<li><code>coerce</code></li>
<li><code>weak_ref</code></li>
<li><code>auto_deref</code></li>
<li><code>init_arg</code></li>
<li><code>required</code></li>
<li><code>lazy</code></li>
<li><code>lazy_build</code></li>
<li><code>predicate</code></li>
<li><code>clearer</code></li>
<li><code>default</code></li>
<li><code>builder</code></li>
<li><code>trigger</code></li>
<li><code>handles</code></li>
<li><code>documentation</code></li>
</ol>

<p>これらの並び順の意図などは、以下で補足しています。</p>
]]>
        <![CDATA[<h2>原則</h2>

<p>整理にあたっては、以下のような原則を敷いたつもりです。</p>

<ul>
<li>クラスを利用する側の視点に立つ</li>
<li>類似オプションはまとめる</li>
<li>汎化したオプションを先に、特化したオプションを後に</li>
<li>よく使うオプションを先に</li>
<li>他のオプションを上書きするオプションは、上書きされるオプションの後に</li>
</ul>

<p>一番大事なのは冒頭の原則です。自分がそのクラスのことを何も知らないと仮定して、コードを読み下すならばどんな順番で情報が提供されていると嬉しいか、それを第一に考えました。</p>

<p>自分が他人になりきるために、</p>

<ul>
<li>大企業らしく「ためにするドキュメント」が山ほどあるのに、</li>
<li>真に必要な情報が全くなく、或いはS/N比が劣悪な膨大な情報の森に隠れていて、</li>
<li>それらの情報や「情報の在処」が口伝やら一子相伝やらで属人的環境の内部で完結しているという素敵な職場で、</li>
<li>前任者が心を病んで退職したことによって口伝が失われたチームがあって、</li>
<li>そこに自分が火消し役として飛び込んだ</li>
</ul>

<p>......と脳内設定してロールプレイを試みてみましたが、<em>何故か</em>そういう想定がリアルに感じられる今日この頃です。</p>

<p>悲しい自虐ネタはさて措いて、その他は「まずは概論、続いて各論」「後出しじゃんけんをしない」という作法とも捉えることが出来ようかと思います。また、コードは往々にして成長するものであって、後になってオプションを追記する場合があると考えると、似たようなオプションが固まっていた方が何かと便利でしょう。</p>

<p>気を付けたいのは、後にあるから重要でない、という整理が成立しないことです。<code>documentation</code>などの補足的なものを除けば、どれも重要です。ですが、オサレなディナーが食前酒やらオードブルから始まるように、順序立ててオプション（＝料理）を提供する観点があってもいいのではないでしょうか。なお、私はオサレなディナーの体験がないので、上記は想像に基づく比喩であります。</p>

<p>もう少し大衆的に書くと</p>

<ul>
<li>取り敢えずビール</li>
<li>挨拶</li>
<li>乾杯</li>
<li>歓談</li>
<li>中締め</li>
<li>歓談</li>
<li>一本締め</li>
<li>別の飲み屋で二次会</li>
<li>カラオケボックスで三次会</li>
<li>締めは屋台でラーメン</li>
</ul>

<p>という高カロリーな打ち上げでしょうか。これなら自信を持って書けます！（あれ、何の話をしていたんでしたっけ）</p>

<h2>1. アトリビュート全体に関わる情報</h2>

<ul>
<li><code>metaclass</code></li>
<li><code>traits</code></li>
</ul>

<p>アトリビュートそのものをいじるものなので、これら2つは最初に書きたいところです。
その二つの順番としては、<code>metaclass</code>は1つだけ、<code>traits</code>は複数指定出来るので、<code>metaclass</code>を先にしておきたい。これはハンバーガー屋に行って注文する際に、サイドメニューよりもメインメニューを先に指定することに似ています。この方が「頭でっかち」にならず、据わりがよいように思えます。</p>

<h2>2. アクセッサー関連</h2>

<ul>
<li><code>is</code></li>
<li><code>accessor</code></li>
<li><code>reader</code></li>
<li><code>writer</code></li>
</ul>

<p>次に、そのアトリビュートへのアクセッサーを書きます。アトリビュート全体に関わる、メタ的な情報を除けば、アクセッサーの情報が最も基本となるからです。</p>

<p><code>is</code>が最初なのは、<code>is</code>の設定が他のプロパティーで上書きされるからです。例えば、</p>

<pre><code class="perl">has 'foo' => (
    is          => 'rw',
    writer      => '_set_foo',
);</code></pre>

<p>のように。
残り3種のうち、<code>accessor</code>は<code>reader</code>と<code>writer</code>をまとめたものですので、汎用的なプロパティーと見なせるので先にします。</p>

<p><code>reader</code>と<code>writer</code>では、読む頻度よりも書く頻度が低いので、<code>reader</code>を優先しました。</p>

<h2>3. 型関連</h2>

<ul>
<li><code>isa</code></li>
<li><code>does</code></li>
<li><code>coerce</code></li>
<li><code>weak_ref</code></li>
<li><code>auto_deref</code></li>
</ul>

<p>アクセッサーの情報を提供すると、読もうとか書こうとかという気になりますので、引き続いてアクセス対象のアトリビュートの型を規定します。つまり、読もうとする値がどんな型であるか、または、書こうとする値がどんな型でなければならないか、という情報を提供するのです。</p>

<p>型変換を規定する<code>coerce</code>は、「<code>isa</code>で定義した型でなければ、変換を試みるよ」という情報なので、<code>isa</code>の後に来るのが自然でしょう。どんな型かという、読み書き両方に使う情報である<code>isa</code>が先に来るべきです。</p>

<p><code>weak_ref</code>と<code>auto_deref</code>は、型とは直接関係ありませんがここで規定します。というのも、<code>weak_ref</code>は「何らかのリファレンスを持つんだけれども、弱いリファレンスとして持つことにするよ」という情報なので、<code>isa</code>で「何らかのリファレンス」を規定した直後に来るのが分かりやすいです。<code>auto_deref</code>も同様で、「何らかのリファレンスを持つんだけれども、デリファレンスして返すことにするよ」という情報だと整理出来ます。</p>

<p>これらは<code>coerce</code>と同様に、一種の内部的な振る舞いを規定する情報なのですが、<code>coerce</code>よりは頻度が低いことから、<code>coerce</code>の後に書くようにしました。</p>

<p>また、<code>does</code>は<code>isa</code>と同じ位置にあるのが自然です（<code>isa</code>とは排他です）。</p>

<h2>4. コンストラクター引数関連</h2>

<ul>
<li><code>init_arg</code></li>
<li><code>required</code></li>
</ul>

<p>続いて、コンストラクター引数関連の情報です。</p>

<p>コンストラクター引数に何を与えようかという情報は、それはつまり型です。型とコンストラクター引数の順番が逆では違和感があります。</p>

<p>また、コンストラクター引数で値を設定する場合は、セッター（ミューテーター）で値を設定する場合の特殊例として捉えることも出来ます。<em>特殊</em>というのはやや過剰な表現ですが、「新たに作成して、それを使う」という場面を想定すると、そこに「（既にあるものを）使う」ことが包含されていることに気付きます。時系列から見れば、確かに「コンストラクターを呼んで、それから使う」という順番ですが、オブジェクトを自分で明示的に作るとは限りらず、出来合いのオブジェクトを使うことがあるので、やはり時系列にこだわらない方が良いでしょう。</p>

<p>この2つでは、「その引数が必須かどうか」を気にするより、まずは「どんなキーで指定すべきか」という情報の方が（APIの伝え方として）重要なので、<code>init_arg</code>を先にしています。</p>

<h2>5. 値の設定状況と遅延設定</h2>

<ul>
<li><code>lazy</code></li>
<li><code>lazy_build</code></li>
<li><code>predicate</code></li>
<li><code>clearer</code></li>
</ul>

<p>値をただ使うだけでなく、値が存在しているか否かという情報が必要になることもあるでしょう。また、値を消去する場合もあるでしょう。情報を取得する<code>predicate</code>が先、情報を更新する（この場合は値を消去する）<code>clearer</code>が後になります。<code>clearer</code>はAPIとして公開しない（頭に<code>_</code>を付ける）こともあるので、説得力が増される感じがします。</p>

<p>遅延設定というのは内部情報であって、APIの外側では知らなくて良い情報なのですが、<code>lazy_build</code>が真だと<code>predicate</code>, <code>clearer</code>, <code>builder</code>が自動的に設定される都合上、<code>lazy_build</code>が先に来るのが道理です（<code>lazy</code>と<code>lazy_build</code>を両方指定すること自体は、エラーにも警告にもなりません）。</p>

<p>また、<code>lazy</code>の場合でも、<code>lazy</code>したからにはデフォルト値が必要になるので、後述の<code>builder</code>か<code>default</code>よりも先行させる必要があります。<code>lazy</code>は<code>predicate</code>や<code>clearer</code>は直接関係がないのですが、<code>lazy_build</code>は<code>lazy</code>の強化版という位置付けなので、<code>lazy_build</code>よりも先に来るのが妥当です。</p>

<h2>6. デフォルト値関連</h2>

<ul>
<li><code>default</code></li>
<li><code>builder</code></li>
</ul>

<p>上記で<code>lazy</code>や<code>lazy_build</code>が来たので、デフォルト値はここで規定します。両方一緒に指定することは出来ないので、この2つでは順番という概念自体がありません。</p>

<p>両方指定すると、Class::MOP 0.94 (+ Moose 0.92)では、以下のようなエラーとなります。</p>

<pre><code>Setting both default and builder is not allowed.
</code></pre>

<p>また、<code>initializer</code>については、それを使わずに<code>builder</code>を使うべきなので、順番にリストアップすること自体をしていません。</p>

<h2>7. トリガー</h2>

<ul>
<li><code>trigger</code></li>
</ul>

<p>トリガーはここで登場させます。</p>

<p>APIの内部で完結する処理ではあるのですが、<a href="http://blog.eorzea.asia/2009/10/post_72.html">前の記事</a>でご紹介したように、自分のアトリビュート<code>password</code>と別のアトリビュート<code>hashed_password</code>が足並みを揃えた値であることを宣言する意図を持つことが往々にしてあります。</p>

<p>これは一種の「アトリビュートはどんなものか（属性）」という情報なので、これまでの<code>is</code>以来続いてきた流れに乗ってここで書くのが自然です。「アトリビュートで何が出来るか（振る舞い）」という<code>handles</code>の後に書いたのでは、振る舞いの後に属性が再登場するようで、ちぐはぐな感じを受けてしまいます。</p>

<h2>8. 委譲</h2>

<ul>
<li><code>handles</code></li>
</ul>

<p>これまで連綿と書いてきた「属性」の情報ではなく、「振る舞い」の情報になる委譲の規定は、ここでようやく出現します。</p>

<p>アトリビュートの「状態」という固まりを定義した後に、「ところでこれまで定義したこのアトリビュートなんだけど、こういうAPIを提供するよ」という情報が出て来るのが自然でしょう。メソッド（<code>sub</code>）よりも先にアトリビュートを書く（<code>has</code>）ことと同じです。</p>

<h2>9. 文書化</h2>

<p>最後に、コードにドキュメントを埋め込むという観点で、<code>documentation</code>を規定します。「そのアトリビュートが何であるか」という情報なので、冒頭に書いた方が良いのではないかとも思いましたが、敢えて最後に書きます。</p>

<p>というのも、初っ端からダラダラと文字列を重ねてしまうと、Mooseで宣言的に書けるコードの小気味よさを削いでしまうのではないか、と思ったからです。</p>

<p>その値が何であるかという端的な情報は、そもそもアトリビュート名で持つようにするのが、自己説明的な良いコードです。そしてそれはオプションに先行して記述されます。</p>

<pre><code class="perl">has 'name' => (
    is              => 'rw',
    isa             => 'Str',
    documentation   => q{Customer's name (without title)},
);</code></pre>

<p>何とも投げやりな<code>documentation</code>ですが、ともあれ、そのアトリビュートが「名前」であるというのは、いちいち<code>documentation</code>を見るまでもなく、<code>has</code>の右隣に書いてあるのでそれで事足ります。</p>

<p>また、<code>is</code>や<code>isa</code>などで表現しきれない情報を書くという観点や、敢えて指定したオプションについての言及をするという観点に則ると、やはり端的なオプション指定の後に来るのが得策だと思います。</p>

<h2>拡張オプション</h2>

<p>オプションを拡張するようなトレートを適用した場合は考えどころで、これもオレオレ基準を作っておきたいです。</p>

<p>あまり好例が思いつかないのですが、例えば<a href="http://search.cpan.org/perldoc?MooseX::Aliases"><code>MooseX::Aliases</code></a>による<code>alias</code>オプションならば、アクセッサー定義系だと整理することが出来るので、<code>is</code>, <code>accessor</code>, <code>reader</code>, <code>writer</code>の後に添えるのがよいのではないでしょうか。</p>

<p>また、<a href="http://search.cpan.org/perldoc?Moose::Cookbook::Meta::Recipe2"><code>Moose::Cookbook::Meta::Recipe2</code></a>などにある<code>label</code>オプションならば、例えばウェブアプリケーションを想定した場合で、アトリビュート<code>name</code>の入力欄である<code>input</code>要素の傍にいる<code>label</code>要素の値として使うことを想定した場合に、<code>documentation</code>の前辺りに細々と書いておくのが良いと思います。そうでないと、ロジックを規定する記述に表示関連の記述を混ぜ込んでしまうからです。</p>

<p>なお、余談ついでに言及しておくと、ロジックと表示を分離する観点に立つと、<code>label</code>に生の文字列を入れるのは気持ち悪いです。実際にはラベル識別子のようなものを設定して、（MVCの）ビュー側で<code>$item-&gt;label_of_name</code>などとしてリソース情報（<code>*.po</code>由来の<code>*.mo</code>なり、DBなり）から生の文字列を引っこ抜いてくるようにすると、後々楽になります。その際、ユーザーの設定言語を使うようにすれば、国際化にも容易に対応出来ます。</p>

<h2>まとめ</h2>

<p>CSSであれば、益子貴寛さんの『Web標準の教科書 - XHTMLとCSSでつくる"正しい"Webサイト』(pp.403-404)などでも紹介されているように、Mozilla.orgによる案（<a href="http://www.mozilla.org/css/base/content.css"><code>http://www.mozilla.org/css/base/content.css</code></a>）があります。PerlのTMTOWTDI（「やり方は一つではない」）な文化が好きなのですが、かといって完全な自由だと不安になる私は、拠り所となる物が欲しかったので、取り敢えず叩き台を作ってみることにしました。</p>

<p>指定順に正解などはなく、人それぞれの方法があります。オレオレガイドラインが正しいだなんて、欠片も思っていません。「べき」「それが自然」「妥当だ」などと断定調で書いていますが、これはあくまで自分向けの台詞のつもりです。Mooseで宣言的なプログラミングをしていると、断定調で「AはBだ。CはDだ。EはFとGが出来る」などと書けてしまうので、その癖がつい出てしまいました（本当ですか）。</p>

<p>また、この柔いオレオレガイドライン自体も、他の多くのコードを拝見させていただく体験を通じて、今後に考えが変わって修正しないとも限りません。いわば緩やかな指針として、半ばネタ的に整理してみたというのが事の次第でした。</p>

<p>もし何か、</p>

<ul>
<li>「自分はこうしているよ」</li>
<li>「そこの順番は逆だろう、常識的に考えて」</li>
<li>「おいおい、hogehogeオプションが漏れているぞ」</li>
<li>「私も金融ユー子ですが、迫真のロールプレイが他人事に思えなくて貰い泣きしました」</li>
</ul>

<p>......などのご意見・ご感想・ご提案・その他諸々がありましたら、このブログやSBSのコメントなどで教えていただけると幸いです。</p>

<h2>余談ついでに......アトリビュートの豊富なオプションはあなたの武器です</h2>

<p>改めてひっくり返してみると、Mooseのアトリビュートが持つオプションの豊富さに驚かされます。こんなに沢山オプションがあると、何かわくわくしてきますね。初めてMooseのマニュアルを読んだとき（当時はまだまとまった日本語訳はありませんでした）、不十分な理解ながらも、これまでやってきた或る種の「ためにする処理」の有象無象へばっさばっさとDSLで切り込んでいく感じを受けて、かなり興奮したことを思い出しました。それは、初めて標準Cライブラリーについての文書を読んだとき、ソフトウェアを使う側から作る側への橋を渡り始めたときの興奮にも似た感触でした。</p>

<p>こんな記事をここまで読んだ方でMoose/Mouseを使っていない方は殆どいらっしゃらないと思いますが、もしまだMoose/Mouseを使ったことがない方でも、オプションの多さに圧倒されて萎えないでください。これらはあなたを悩ませるために敵陣から飛んできた矢ではなくて、あなたが武器として使えるように矢筒に入った矢なのです（そうら、ファットカンマが矢に見えてくる見えてくる......）。</p>

<p>アトリビュート以外にも、Moose/Mouseという武器庫には多くの武器がまだまだあります。Moose/Mouseを使って、めくるめくポストモダンオブジェクト指向プログラミングの世界を体験しましょう！</p>
]]>
    </content>
</entry>

<entry>
    <title>Mooseのtriggerの効果的な使い方 ～ lazyとclearerとの併用</title>
    <link rel="alternate" type="text/html" href="http://blog.eorzea.asia/2009/10/post_72.html" />
    <id>tag:blog.eorzea.asia,2009://1.72</id>

    <published>2009-10-15T17:33:50Z</published>
    <updated>2009-10-18T08:01:42Z</updated>

    <summary>Mooseのtriggerの効果的な使い方について、遅ればせながら先の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の<code>trigger</code>の効果的な使い方について、遅ればせながら先のMoose入門研修で始めて知りました。簡単なサンプルコードスニペットも用意出来たので、まとめておきます。</p>

<p>この記事の対象読者としては、私と同じ<code>Moose</code>初心者の方々を想定しています。</p>

<ol>
<li>そもそも<code>trigger</code>とは何か</li>
<li>具体的な使いどころ</li>
<li>もし<code>trigger</code>がなければ......</li>
<li><code>lazy</code>した導出先のアトリビュートを<code>clear</code>すべき</li>
<li>具体例の数々（サンプルコードスニペット付き）</li>
<li>まとめらしくないまとめ</li>
</ol>
]]>
        <![CDATA[<h2>1. そもそも<code>trigger</code>とは何か</h2>

<p><code>trigger</code>はMooseのアトリビュートに付加できるオプションの一つです。</p>

<p><a href="http://search.cpan.org/perldoc?Moose::Manual::Attributes"><code>Moose::Manual::Attributes</code></a>（の、石垣さん(charsbarさん)による<a href="http://github.com/jpa/Moose-Doc-JA">日本語版</a>）から引用すると、</p>

<blockquote>
  <p>アトリビュートに値がセットされたときにかならず呼ばれるサブルーチンです。</p>
</blockquote>

<p>とあります。</p>

<p><code>trigger</code>オプションの値はサブルーチンリファレンスを取ります。勿論、匿名サブルーチンリファレンスも設定出来ます。</p>

<pre><code class="perl">trigger => \&triggered_method</code></pre>

<p>または</p>

<pre><code class="perl">trigger => sub { ... }</code></pre>

<p>などです。</p>

<h2>2. 具体的な使いどころ</h2>

<h3>2.1. ゲッターでは何もせずにセッターの時だけ何かしたい</h3>

<p>例えば<code>after</code>などのメソッドモディファイヤーの用途として例示されている</p>

<ul>
<li>ログ取得</li>
<li>デバッグ</li>
</ul>

<p>などの<em>稼働範囲をさらに限定する</em>使い方があります。ゲッターの時は何もせずにセッターの時だけ処理したい場合などに使います。</p>

<p><code>$thing-&gt;foo();</code>として<code>thing</code>の<code>foo</code>アトリビュートの値を取得する場合には何もせずに、<code>$thing-&gt;foo(1);</code>とした場合に<code>warn "foo attribute is changed";</code>と表示するなどといった場合です。</p>

<h3>2.2. アトリビュート間に関数従属の関係がある</h3>

<p>しかし、さらによくある例としては、或る<code>foo</code>アトリビュートが他の<code>bar</code>アトリビュートの計算元となる場合でしょう。<code>bar</code>アトリビュートが<code>foo</code>アトリビュートによって導出されるということです。語弊を恐れずにRDB的な用語を使うと、<em><code>bar</code>アトリビュートが<code>foo</code>アトリビュートに関数従属する</em>場合であるとも表現できます。</p>

<p><a href="http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=gitmo/moose-presentations.git;a=tree;f=moose-class">Moose入門研修のスライド</a>（<a href="http://github.com/gardejo/moose-presentations">拙訳</a>）には、<code>password</code>（平文パスワード）と<code>hashed_password</code>（ハッシュ化パスワード）という好例が紹介されています。</p>

<p>なお、ハッシュ化パスワードについて補足しておきます。アプリケーションによっては、保安上の観点から、平文パスワードをDBに生で保存せずに、平文パスワードのハッシュ値を保存する設計にすることがあります（認証時には、ユーザーが入力した平文パスワードをハッシュ化し、DBから取り出したハッシュ値と突き合わせます）。ハッシュ化・ハッシュ値についてご存じない方は、暗号化のようなものだと思ってください。</p>

<p>閑話休題。ここで、<code>hashed_password</code>は<code>password</code>をハッシュ関数に入れて出て来た値なので、これら二つの値は足並みが揃ったものでなくてはなりません。つまり、<code>password</code>が変わったならば、それに対応して<code>hashed_password</code>も変わらなければ（<code>password</code>を使って再計算しなければ）なりません。</p>

<p>クラスを使う側がそんな作業を行うのは馬鹿げています。アプリケーションで<code>password</code>を変える場所毎に<code>hashed_password</code>に値を設定するのは大変ですし、漏れが出るに決まっています。さらに、<code>hashed_password</code>に入れる値を<code>password</code>から計算するのは、<code>password</code>アトリビュートを持つクラス側がやるべき仕事のはずです。</p>

<p><code>trigger</code>を使えば、<code>password</code>が変更されたタイミングにフックして、<code>hashed_password</code>を再計算することを、APIの内側で完結した処理として実装することが出来ます。</p>

<h2>3. もし<code>trigger</code>がなければ......</h2>

<p>もし<code>trigger</code>がないと、例えば下記のような見苦しいコードを都度書かなければなりません。</p>

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

has 'foo' => (
    is          => 'rw',
    isa         => 'Any',
);

around foo => sub {
    my ($next, $self, @args) = @_;

    # 引数がなければゲッター
    return $self->$next
        unless scalar @args;

    # セッター
    my $return_value = $self->$next(@args);

    # ここにやりたい処理を書く

    return $return_value;
};

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

<p>或いは、以下のように。</p>

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

has 'foo' => (
    is          => 'rw',
    isa         => 'Any',
    writer      => 'set_foo',
);

after set_foo => sub {
    my $self = shift;

    # ここにやりたい処理を書く

    return;
};

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

<p>これでは宣言的なコーディングが出来ませんよね。「セッターの時にこれをしたい」というプログラマーの意図を端的に表現するには、<code>trigger</code>で言明する方が遙かに分かりやすいです。</p>

<ins title="afterで引数を読むことが可能だった" datetime="2009-10-16T12:00:00+09:00">

<p><em>追記</em> : うっかりぽん。<code>after</code>メソッドモディファイヤーでは、引数を「変える」ことは出来ませんが、「読む」ことは出来ました（ここでは、存否を見ています）。従って、少しだけ簡単に、以下のように書けます......といっても、やはり<code>trigger</code>を使った方が楽ですね。</p>

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

    has 'foo' => (
        is          => 'rw',
        isa         => 'Any',
    );

# ...

    after foo => sub {
        my ($self, @args) = @_;

        # 引数がなければゲッター
        return
            unless scalar @args;

        # セッターなのでここにやりたい処理を書く
    };

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

</ins>

<h2>4. <code>lazy</code>した導出先のアトリビュートを<code>clear</code>すべき</h2>

<p>この記事の一番大事な点はここです。</p>

<p>ここまで<code>trigger</code>によって<code>password</code>を使って<code>hashed_password</code>を再計算するなどと書いてきましたが、実はこれはあまり良くない例です。Moose入門研修の内容の通り、<em><code>lazy</code>と<code>clearer</code>を使うべき</em>でしょう。</p>

<p>理由は<code>lazy</code>と同様で、導出先のアトリビュートでは値を常時抱えている必要がないからです。プログラムの終了まで、もしくは情報源となるアトリビュートに値が再設定されるまで、導出先のアトリビュートはアクセスされないかも知れません。従って、次回アクセスされてから導出しても（遅延設定しても）問題ないのです。</p>

<p><code>lazy</code>と<code>clearer</code>の組み合わせによって、以下のような素直な実装を簡単に実現出来ます。</p>

<pre><code class="perl">package Things;

use Moose;

has 'number' => (   # 数
    is          => 'rw',
    isa         => 'Num',
    trigger     => sub {
        $_[0]->clear_inverse;
    },
);

has 'inverse' => (  # 逆数
    is          => 'ro',
    isa         => 'Num',
    init_arg    => undef,
    lazy_build => 1,
);

sub _build_inverse {
    1 / $_[0]->number;
}

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

<p>挙動は以下の通りです。</p>

<ol>
<li><code>$things-&gt;number(42);</code>によって（またはコンストラクター引数で<code>Things-&gt;new(number =&gt; 42)</code>などとして）導出元アトリビュートである<code>number</code>が設定される</li>
<li><code>number</code>アトリビュートの<code>trigger</code>で、<code>$things-&gt;clear_inverse</code>が呼ばれる</li>
<li><code>inverse</code>アトリビュートが未設定の状態になる</li>
<li><code>$things-&gt;inverse</code>を呼ぶ</li>
<li><code>$things-&gt;_build_inverse</code>というビルダーメソッドで逆数を（再）設定する</li>
</ol>

<p>もし4.が呼ばれなければ、5.の逆数の計算もしないという仕組みです。再設定用として別に編集メソッドも用意する必要もありません（すべて<code>builder</code>メソッドが面倒を見てくれます）。</p>

<p>後述しますが、相互に導出し合っているようなアトリビュート群があった場合、さらにひどいことになります。<em>是非<code>clearer</code>を使いましょう</em>。</p>

<h2>5. 具体例の数々（サンプルコードスニペット付き）</h2>

<p>延々と書き連ねてきましたが、コードを見た方が早いので、いくつか具体例をご紹介しましょう。</p>

<h3>5.1. 一方向の単純導出の場合</h3>

<p>まずはこれまで使っていた<code>password</code>と<code>hashed_password</code>の例です。アトリビュートの関係性をアスキーアートで図示すると、以下のようになります。</p>

<pre><code>password ----&gt; hashed_password
</code></pre>

<p>これは上記4.の実装方法と全く同じです。</p>

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

use Digest;

# ...

has 'password' => (
    is          => 'rw',
    isa         => 'Str',
    trigger     => sub {
        $_[0]->clear_hashed_password;
    },
);

has 'hashed_password' => (
    is          => 'ro',
    isa         => 'Str',
    init_arg    => undef,
    lazy_build  => 1,
);

sub _build_hashed_password {
    my $digest = Digest->new('SHA-256');
    $digest->add($_[0]->password);

    return $digest->hexdigest;
}

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

<p>テストの形をしたサンプルコードは、<a href="http://gist.github.com/211069">gist #211069</a>として上げておきました。</p>

<p>今回の説明とは関係ないので上記では書きませんでしたが、いくつか余談を書いておきます。</p>

<h4><code>trigger</code>で<code>clearer</code>を指定する際の注意点</h4>

<p><code>password</code>で、直接<code>trigger =&gt; \&amp;clear_hashed_password</code>と書きたいかも知れませんが、これは出来ません。<code>has 'password'</code>した時点では<code>hashed_password</code>は宣言されていないので、つまり<code>hashed_password</code>の<code>lazy_build</code>によってMooseが生成してくれる<code>clear_hashed_password</code>メソッドも存在しないからです<ins>（と理解していましたが、エラーではなく警告が出るだけなので、エラーメッセージ通りに解釈するのが正しそうです）</ins>。試しに書いてみると、Moose 0.92では以下のような警告が出ます。</p>

<pre><code>You are overwriting a locally defined method (clear_hashed_password) with an accessor
</code></pre>

<p>従って、素直に匿名サブルーチンリファレンスを渡すべきです。</p>

<p>勿論、<code>hashed_password</code>と<code>password</code>の<code>has</code>の書き順を逆転させれば<code>trigger =&gt; \&amp;
clear_hashed_password</code>と書くことは出来ますが、</p>

<ul>
<li>導出先アトリビュートが導出元アトリビュートより先に書いてあるとコードの据わりが悪い</li>
<li><code>has</code>の書き順次第で挙動が変わるのは、Mooseに詳しい人でないと分かりにくい（別の人がコードを修正したときに動かなくなる可能性がある）</li>
</ul>

<p>というような理由により、無精なことはやめておいた方が得策だと思います。後者などは、例えばロールで<code>requires</code>したメソッドが<code>has</code>で定義するアトリビュート名（アクセッサー）だった場合に、クラス側で<code>has</code>の後に<code>with</code>を書かないと駄目だという問題に似ていて、なかなか厄介な問題です。</p>

<h4><code>hashed_password</code>の防衛</h4>

<p><code>hashed_password</code>では</p>

<ul>
<li><code>is =&gt; 'ro'</code>して読み取り専用にする</li>
<li><code>init_arg =&gt; undef</code>してコンストラクターでも設定出来ないようにする</li>
</ul>

<p>ということをしています。</p>

<p>そもそも、<code>hashed_password</code>から<code>password</code>を導出することは出来ません。そもそもハッシュ化とは一方向の変換を前提としているようなものなのですから。従って、<code>hashed_password</code>はクラス内部でのみ設定されるようにしておくことが良いでしょう。</p>

<p>より安全にするには、<code>hashed_password</code>で<code>clearer =&gt; '_clear_hashed_password'</code>などとして、クリア用のメソッドをプライベート然とした名前にすることです。</p>

<h4>どこまで制約を掛ける？</h4>

<p><code>hashed_password</code>を<code>MyApp::Types</code>などで規定した<code>StrAsHexSHA256</code>というような型にするのは考えどころです。（場合によっては）過ぎたるは及ばざるがごとし、になるかも知れません。というのも、上記のように<code>hashed_password</code>の値の設定はAPI内部で完結しているので、API外部から変な値が入ってくることがないからです（カプセル化の原則が守られている限りに於いては、つまり<code>$things-&gt;{hashed_password} = 'foo'</code>などとされない限りは）。</p>

<p>誤りを出来るだけ早期に検知するよう、防衛的なプログラミングをするには、制約を是非掛けておきたいところです。値の計算結果が常に正しいことを、アサーションのように書いておくという意味合いです。</p>

<p>しかし値が何度も再設定されうる場合には、Shawn M Mooreさん(sartakさん)が研修で仰っていたことの受け売りですが、パフォーマンス面での問題が出ないかを気にしておいた方が良いでしょう。</p>

<h4>どこまでPBPに準拠する？</h4>

<p>PBP(&quot;Perl Best Practices&quot;, 邦訳は『Perlベストプラクティス』)に準拠していない記述がいくつかあります。</p>

<p>まず、パフォーマンスを気にして、<code>trigger</code>や<code>builder</code>では<code>$_[0]</code>という記述を使っています。アプリケーションロジックであれば<code>$self = shift;</code>するのが良いでしょう。また、何も返さないことを明示する<code>return;</code>を書いても良いでしょう。しかし、</p>

<ul>
<li>そのサブルーチンやメソッドが極めて単純な宣言的な記述である</li>
<li>今後それが成長することはほとんど考えられない</li>
</ul>

<p>というようなオレオレ基準に合致すると考えたため、記述を意図的に端折っています。</p>

<pre><code class="perl">trigger => sub {
    $_[0]->clear_hashed_password;
},</code></pre>

<p>という記述と、</p>

<pre><code class="perl">trigger => sub {
    my $self = shift;

    $self->clear_hashed_password;

    return;
},</code></pre>

<p>という記述のどちらを選ぶかは、基本的には好みの問題です。</p>

<p>業務では「好み」を忖度出来ませんので、コーディング標準として「1センテンスで記述可能な<code>clearer</code>や<code>builder</code>では、<code>return;</code>を明示せず、<code>my $self = shift;</code>としない」などと決めてしまう手もあります。</p>

<h4>ファットカンマの左辺はクォート不要だよね</h4>

<p>その通りです。</p>

<p>ですが、派生クラスで継承したアトリビュートで<code>has '+foo' =&gt; ...</code>などとするので、面倒から基底クラス側でも<code>has 'foo' =&gt; ...</code>してしまえという個人的な好みで書いています。</p>

<p>一方、メソッドモディファイヤーによって修飾される対象のメソッド名はクォートしていません。アトリビュートは「物」のようなものと理解してクォートして<em>名前を付ける</em>一方、メソッドは「振る舞い」なので<em>書き下す</em>ような感触なので、こちらは付けていません。PBPでも言及されているような慣習的な命名規則によれば、メソッド名に<code>qr{[a-z\d]}i</code>以外の文字を使うことが殆ど全くない上に、アトリビュートでクォートした最大の理由である継承による<code>+</code>付与がないので、こちらは無精しています。</p>

<p>まあ、全部付けるなら付けるで、しゃっきりした方がいいとは思います。</p>

<h3>5.2. 複数の導出元がある場合</h3>

<p>次に、<code>name</code>（名前）と<code>title</code>（敬称）から、メールなどの<code>addressee</code>（名宛て）を導出する例で考えてみましょう。アトリビュートの関係性をアスキーアートで図示すると、以下のようになります。</p>

<pre><code>name  --+
        +-&gt; addressee
title --+
</code></pre>

<p>これは前項の応用編です。<code>addressee</code>の<code>builder</code>は<code>name</code>と<code>title</code>を使うので、<code>name</code>と<code>title</code>それぞれで<code>clear_addressee</code>を呼べば良いです。</p>

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

has 'name' => (
    is          => 'rw',
    isa         => 'Str',
    trigger     => sub {
        $_[0]->clear_addressee;
    },
);

has 'title' => (
    is          => 'rw',
    isa         => 'Str',
    trigger     => sub {
        $_[0]->clear_addressee;
    },
);

has 'addressee' => (
    is          => 'ro',
    isa         => 'Str',
    lazy_build  => 1,
);

sub _build_addressee {
    $_[0]->title . q{ } . $_[0]->name;
}

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

<p>これも<a href="http://gist.github.com/211070">gist #211070</a>に保存しています。</p>

<h4><code>_build_addressee</code>の書きぶり</h4>

<p><code>addressee</code>が多くのアトリビュートに依拠するならば、<code>_build_addressee</code>メソッドでは<code>sprintf</code>を使った方がコードが綺麗になります。</p>

<p>また、もし<code>title</code>が<code>is =&gt; Maybe[Str]</code>（つまり<code>is =&gt; 'Undef | Str'</code>）だった場合には、</p>

<pre><code class="perl">defined $_[0]->title ? $_[0]->title . q{ } . $_[0]->name
                     :                       $_[0]->name;</code></pre>

<p>となるでしょう。</p>

<h4>各アトリビュートをより堅くする</h4>

<p>例えば業務アプリケーションなどでは以下のようなことをすると思います。</p>

<ul>
<li><code>name</code>は<code>first_name</code>（または<code>forename</code>）と<code>last_name</code>（または<code>family_name</code>やら<code>surname</code>やら）に分けるべき</li>
<li>それらの名前の文字長はDBスキーマの<code>varchar(XXX)</code>などと足並みを揃えた制約を施す（<code>subtype</code>を使う）と堅い</li>
<li><code>title</code>は<code>enum(Mr. Ms. Mrs. Miss Dr.)</code>などの選択式にする方が堅い</li>
</ul>

<h3>5.3. 循環的に導出し合っている場合</h3>

<p>例えば<code>imperial_era</code>（和暦）と<code>christian_era</code>（西暦）の関係がこれに当たります。アスキーアートによるアトリビュートの関係性は以下の通りです。</p>

<pre><code>imperial_era &lt;---&gt; christian_era
</code></pre>

<p>これは双方のアトリビュートが共に「導出元であり導出先である」と整理出来ますので、以下のように書けます。</p>

<pre><code class="perl">package Syouwa;

# ...

our $Delta = 1925;

has 'syouwa_era' => (       # 昭和X年
    is          => 'rw',
    isa         => 'Int',
    lazy_build  => 1,
    trigger     => sub {
        $_[0]->clear_christian_era;
    },
);

has 'christian_era' => (    # 西暦X年
    is          => 'rw',
    isa         => 'Int',
    lazy_build  => 1,
    trigger     => sub {
        $_[0]->clear_syouwa_era;
    },
);

sub build_syouwa_era {
    return $_[0]->syouwa_era + $Delta;
}

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

<p><a href="http://gist.github.com/211073">gist #211073</a>には、下記の余談にあるロール版とサブクラス版それぞれを例示するコードを保存しました。</p>

<h4>続・<code>trigger</code>で<code>clearer</code>を指定する際の注意点</h4>

<p><code>syouwa_era</code>で<code>trigger =&gt; \&amp;clear_christian_era</code>などと書きたくても駄目なことは、5.1節でご紹介しました。後に書いた西暦の方では（既に<code>clear_showa_era</code>が存在するので）<code>trigger =&gt; \&amp;clear_showa_era</code>すること自体は可能ですが、記述を統一しておいた方が分かりやすいでしょう。また、そうしておくと、後述のように、トリガーで複数の処理を行いたい場合にも、当該匿名サブルーチン内に処理を書き加えるだけで済みます。</p>

<h4>年の制約</h4>

<p>より正しくは昭和に<code>where { 1 &lt;= $_ &amp;&amp; $_ &lt;= 64}</code>という制約を施すべきです。
また、西暦も<code>where { 1 &lt;= $_ }</code>すべきでしょう。紀元前は考慮していません。</p>

<h4>各アトリビュートのリファレンスを持つ場合</h4>

<p>リファレンスによって同一オブジェクト内のアトリビュート間での依存性を表現する場合でも、（異なるオブジェクトのアトリビュート間での循環参照時と同様に）<code>weak_ref =&gt; 1</code>することを忘れないようにしてください。</p>

<h4>サブクラス化するかロール化する</h4>

<p>上記では昭和クラスを想定していましたが、これはいまいちです。なぜなら、明治・大正・平成などに流用が効かないクラスになっているからです。</p>

<ul>
<li>西暦を持つロールと、各元号クラスに分ける</li>
<li>元号抽象クラスと、昭和具象クラスに分ける</li>
</ul>

<p>などの方法で、固定部分と可変部分を峻別しましょう。</p>

<p>ついでに、クラス変数として持っている<code>our $Delta</code>も、<code>MooseX::ClassAttribute</code>を使ったりロール側で定義するアトリビュートにしたり（その場合は<code>build_delta</code>を<code>requires</code>することになります）と、手を入れておくことも出来ます。</p>

<h4>他の例</h4>

<p>西暦と<a href="http://ja.wikipedia.org/wiki/%E7%A5%9E%E6%AD%A6%E5%A4%A9%E7%9A%87%E5%8D%B3%E4%BD%8D%E7%B4%80%E5%85%83">皇紀</a>でも大体似たようなものですが、実際には旧暦などを考えなければいけないので気を付けてください。</p>

<p>拙作<a href="http://search.cpan.org/perldoc?MooseX::Types::Locale::Language"><code>MooseX::Types::Locale::Language</code></a>（ISO 639-1の言語コードの制約と型変換）でも、これと同じ状況の例をサンプルコード<a href="http://search.cpan.org/src/MORIYA/MooseX-Types-Locale-Language-0.003/examples/complex.pl"><code>MooseX-Types-Locale-Language-0.003/examples/complex.pl</code></a>として付属しています。なお、このモジュールについては別の機会に記事を書くつもりです。</p>

<h4>もし<code>clearer</code>を使わないなら......</h4>

<p>もし<code>clearer</code>を使わずに関係先のアトリビュートを直接その場で設定しようとするなら、以下のような厄介なことを解決しなければなりません。</p>

<ul>
<li>無限ループを防ぐ仕組みを仕込まなければなりません</li>
<li><code>builder</code>と同じ処理を書かなければなりません</li>
</ul>

<p>無限ループについてですが、これは以下のようにして発生します。</p>

<ol>
<li><code>$era-&gt;imperial_era(1);</code>で元号を設定する</li>
<li>元号の<code>trigger</code>によって、<code>$self-&gt;christian_era( $self-&gt;imperial_era + $Delta );</code>などとして西暦を設定する</li>
<li>西暦の<code>trigger</code>によって、<code>$self-&gt;imperial_era( $self-&gt;christian_era - $Delta );</code>などとして元号を設定する</li>
<li>2.に戻る</li>
</ol>

<p>これを防ぐ方法は、例えば以下の通りです。</p>

<ul>
<li>セッターメソッドをアトリビュート名とは別の名称にする</li>
<li>トリガーには匿名でないサブルーチンリファレンスを設定する</li>
<li>呼び元のメソッド名を見て、ループを断ち切る</li>
</ul>

<p>具体的な動きとしては、以下のようになります。</p>

<ol>
<li><code>$era-&gt;_set_imperial_era(1);</code>で元号を設定する</li>
<li>元号の<code>trigger</code>で<code>$self-&gt;_build_by_imperial_era</code>を呼ぶ</li>
<li>2つ前のメソッドが<code>_set_christian_era</code>ではないので、<code>$self-&gt;_set_christian_era( $self-&gt;imperial_era + $Delta );</code>として西暦を設定する</li>
<li>西暦の<code>trigger</code>で<code>$self-&gt;_build_by_christian_era</code>を呼ぶ</li>
<li>2つ前のメソッドが<code>_set_imperial_era</code>なので、<code>$self-&gt;_set_imperial_era</code>は呼ばずにループを断ち切る</li>
</ol>

<p>メソッド名を得る実装としては、<code>(caller(2) )[3]</code>で得られる完全修飾メソッド名を使うことになります。</p>

<p>......ああっ、なんて面倒くさいのでしょうか！　とてもやっていられませんが、実はMoose入門研修受講前の私は正にそれをやっていました。私の失敗例も<a href="http://gist.github.com/211088">gist #211088</a>として晒しておきましょう。<em>これはひどい</em>。</p>

<h3>5.4. さらなる応用例</h3>

<p>上記5.3の最後に<a href="http://search.cpan.org/perldoc?MooseX::Types::Locale::Language"><code>MooseX::Types::Locale::Language</code></a>での例を掲げました。これは</p>

<pre><code>alpha2 &lt;---&gt; name
</code></pre>

<p>という関係性でしたが、<a href="http://search.cpan.org/perldoc?MooseX::Types::Locale::Country"><code>MooseX::Types::Locale::Country</code></a>（ISO 3166-1の国コードの制約と型変換）ではさらに複雑になっています。</p>

<pre><code>   +------&gt; alpha2 &lt;------+
   |           ^          |
   v           |          v
numeric &lt;------+------&gt; name
   ^           |          ^
   |           v          |
   +------&gt; alpha3 &lt;------+
</code></pre>

<p>何かの悪い冗談のようですが、これも結局は関係先全ての<code>clearer</code>を呼んで、<code>builder</code>では関係先のどれかの値を使うようにすればよいのです。</p>

<p>サンプルコード<a href="http://search.cpan.org/src/MORIYA/MooseX-Types-Locale-Country-0.000/examples/complex.pl"><code>MooseX-Types-Locale-Country-0.000/examples/complex.pl</code></a>の中身を少し転載しておきます。</p>

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

    use MooseX::Types::Locale::Country qw(
        Alpha2Country
        Alpha3Country
        NumericCountry
        CountryName
    );
    use Locale::Country;

# ...

    has 'alpha3' => (
        is          => 'rw',
        isa         => Alpha3Country,
        init_arg    => '_alpha3',
        coerce      => 1,
        lazy_build  => 1,
        writer      => '_set_alpha3',
        trigger     => sub {
            $_[0]->clear_alpha2;
            $_[0]->clear_numeric;
            $_[0]->clear_name;
        },
    );

# ...

    sub _build_alpha3 {
          $_[0]->has_alpha2
            ? country_code2code
                ( $_[0]->alpha2,  LOCALE_CODE_ALPHA_2, LOCALE_CODE_ALPHA_3 )
        : $_[0]->has_numeric
            ? country_code2code
                ( $_[0]->numeric, LOCALE_CODE_NUMERIC, LOCALE_CODE_ALPHA_3 )
        :
              country2code
                ( $_[0]->name,    LOCALE_CODE_ALPHA_3 );
    }

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

<p><code>predicate</code>オプション（省略時は<code>lazy_build</code>オプションの有効時には<code>has_ATTRIBUTE</code>）を使っているのが着目点です。</p>

<h2>6. まとめらしくないまとめ</h2>

<p><code>trigger</code>と<code>clearer</code>と<code>lazy</code>を組み合わせて使う、それが要点です。</p>

<p>上記5.3.では、<code>trigger</code>と<code>clearer</code>と<code>lazy</code>の組み合わせを知らなかった時期の醜悪なコードを恥を忍んで晒しました。私のような<code>Moose</code>初心者の方には、これを反面教師としていただけるかも知れません。</p>

<p>Mooseは大変強力です。Mooseを使ってプログラミングする時、「これって気持ち悪い書き方だよね」と思ったら、<code>Moose::Manual</code>や<code>Moose::Cookbook</code>を漁りましょう。きっと洗練された素直な書き方が出来るはずです。</p>

<p>無駄なことを頑張って仕上げるようなガチムチな仕事は避けましょう。<em>大いなる自戒</em>を込めて......。</p>

<p><ins title="トリガーされるメソッドへのモディファイヤーの適用について補足" datetime="2009-10-18T16:50:00+09:00"><em>追記</em> : <cite>三宅さん(nekoyaさん)の<a href="http://b.hatena.ne.jp/studio-m/20091018#bookmark-16746813">はてブコメント</a></cite>で、<q>triggerは一つしか書けないけど、afterは追加できるという違いは大きいと思う</q>という指摘をいただきました。単に導出先の値をリセットしたいだけならば<code>clearer</code>を使えば済みますが、ロールなどで<code>trigger</code>されるメソッドの挙動をいじりたい場合には、メソッドモディファイヤーも有用ですね。なお、メソッドモディファイヤーを<code>clearer</code>のメソッドに適用するという合わせ技も出来ますので、夢が拡がります。</ins></p>
]]>
    </content>
</entry>

</feed>
