Home

日記
ガット張り替えEdit

RDS002TOURとRQS11HGの両方をポリプラズマ1.28/面圧58pに張り替え。しばらく使っていなかったRQS11HGだけど、ヘッド寄りに3×3gの錘を追加して復活させる予定。

最近はフォアハンド、ボレー、スマッシュはだいぶまともになってきたけれども、バックハンドとサーブがまだまだ安定していないんで、当面はその二つが課題。

バックハンドは、基本両手打ち、浅いボールをたたくときだけ片手打ちという変則スタイルを練習中。もともとは全部両手打ちにするつもりだったんだけど、浅い球だけはフットワーク+膝を使って両手打ちの打点に入るよりも、足をさぼって片手打ちの打点で打つ方が確率も高いし、球の威力もあるんで。

サーブはフラット気味のファーストはだいぶ安定してきたけれども、セカンドがまだ試行錯誤中。スピンサーブはトスが難しくて安定にはほど遠い状態。スライスサーブはいいときはいいんだけど、入らない日はいつまでたっても修正が効かず、どうにも日によってばらつきが大きすぎる。結局実戦ではへなちょこサーブしかセカンドは打てていないんだけど、そろそろセカンドもまともに振り切るサーブを安定して打てるようになりたいところ。

といった感じで、相変わらずテニスは続けているんでした。週5くらいのペースでテニスをやっているんで、自転車に乗る暇が全然ない。あっちも心拍系強化のためにやっておきたいんだけど、テニスもハードコートが多いと足のダメージが大きいんで、自転車と両立させるのは結構難しいんだよな。あと圧倒的に時間が足りていないし。

Published At2007-07-02 00:00Updated At2007-07-02 00:00

日記
MM/Memoのドメインを変更しましたEdit

MM/Memoのドメインを、http://1470.net/mm/からhttp://mmmemo.1470.net/mm/に変更しました(1470.netリニューアル版の方の負荷対策のためです)。自動的にリダイレクトするようにしていますので、今まで通り利用できるはずですが、修正漏れ等による不具合等ありましたらおしらせください。

Published At2007-06-26 00:00Updated At2007-06-26 00:00

日記
「TrackBackはもうなかったことにしてはどうか?」とは? - Ogawa::MemorandaEdit

URL間のlinkageを提供する外部サービスを実現して、ブログからは適当なAPIを用いてそのlinkage情報を利用するようにする

ってのは、blogmapの頃からトライしているネタなんだよなー。ちなみに今は亡きblogmapとは、RSSフィードからエントリーごとに含まれるリンク(URL/Amazon商品)情報を解析し、サイトやエントリーごとのリンク/被リンク情報を提供するサービスだった。海外には地図系のblogmapサービスがあるけど、それとは別(それより古かった)。

ただ、blog黎明期(もともとはWeb日記リンク集時代からHTML解析ベースでやっていた)のデータ量が少ない頃はよかったけど、blog時代になってデータ量が爆発的に増えると、どんどん必要なサーバーリソースが増え続けてしまい、さらには大量のspam blogによって耐spam機能を持っていなかったblogmapのシステムは破綻してしまった。

そこで、MM/Memo(ソーシャルブックマーク)を使って、自動的に収集されたデータ(URL)に対して、人力の重み付けを行ったりすることで、耐spam用の情報を得ようと思ったりもしたんだけど、自動収集されたデータとソーシャルブックマークに登録されるデータではその量が圧倒的に違いすぎて、そういう用途では使えなかった。

しょうがないんで、blogmapのシステムを捨て去り、新しく1470.netリニューアル版を作った。blogmapではupdate pingで更新情報が送られてくるサイトのデータを収集していたんだけど、そういうやり方だとspam系データがあまりにも多くなりすぎるんで、1470.netでは情報収集先に人力フィルターを通すようにした。

具体的には、ユーザーは自分がチェックしたいサイトのフィード群を登録し、そのサイト群内での情報の解析(ランキング/新着) をみられるようにした。

たとえば俺の場合は、 これらのサイトのフィード を解析対象として登録しておき、それによって、

という解析情報を得られるようにしている。

この登録フィードは基本的にはRSSリーダーに登録しているものほぼそのまま(OPMLでインポートした)んだけど、RSSリーダーでいちいち全部見ている暇がない場合は、ひとまずこういう解析情報をチェックしておくと、流行りものの状況がなんとなくわかるようになる。

で、こういう風に自分が情報をチェックしたいサイトのフィードを登録してもらうことで、spamサイトではないサイトのフィードを選別し、それによってspamの少ない優良なサイトのフィード群から収集したデータを元にした解析を行おうというアプローチ。

ただ、このアプローチだと基本的に収集するデータ量が少なくなりすぎる。spamが少ないのはいいんだけど、spamじゃないデータも少なくて、元々の目的だったリンク/被リンク情報の解析情報としては、あまりにも物足りないものになってしまう。

たとえばここの場合、 http://1470.net/site/tdiary.ishinao.net なんてURLで、サイト単位の被リンク情報が閲覧できるけど、ここで被リンク情報を見ても、ほとんど有用な情報がとれていない。複数の被リンク情報があるかと思ったら、ソーシャルブックマークサービスとかの新着情報経由だったりするのがほとんど。

ちなみに1470.netの場合は、ドメインのみではなく、 http://1470.net/site/tdiary.ishinao.net/2007 みたいに、パスの前方一致で絞り込むこともできるんで、ディレクトリ単位での言及チェックにも対応できる。エントリー(URL)単位での言及チェックは、http://1470.net/uri/http://tdiary.ishinao.net/20070606.html%23p01 みたいな感じね。というのはここでは本題ではないんだけど。

で、何が言いたいかというと、たくさんのnot spamなフィード情報を1470.netに登録していただけると、データ収集先が増えてもっと有用な情報が得られるようになるかもしれないんで、よろしくお願いします。1470.netにユーザー登録(はてなかTypeKeyのアカウントが使えます)してから、RSSリーダーとかからエクスポートしたOPMLをインポートをするだけで登録できますんで。ちなみにBloglinesはよく壊れたOPMLファイルをエクスポートするので注意してください。

Published At2007-06-12 00:00Updated At2007-06-12 00:00

技術日記
起動ファイルのコードのスコープEdit

どうでもいいけど、ちょっと気になること。

Zend Frameworkでは、起動ファイルにいろいろ初期化コードを書いていくけど、そこで使った変数はグローバル変数になってしまうことになる。たとえば、

$config = new Zend_Config_Xml('/path/to/config.xml');
Zend_Registry::set('config', $config);

とかして読み込んだconfigオブジェクトは、普通はZend_Registryにセットしておいて、必要に応じてZend_Registry::get('config')して使うけれども、実際はアクションコントローラの中とかで、

global $config;

とかすればアクセスできてしまう。かといって、わざわざ、

$config = new Zend_Config_Xml('/path/to/config.xml');
Zend_Registry::set('config', $config);
unset($config);

とまでは書かないよね。

じゃあグローバルスコープじゃないようにしようかと、起動ファイルの中身を、

function main()
{
// 各種初期化処理
}
main();

とかmain()関数でくくって書けばいいかなーと思ったりしたんだけど、それもいまいちぱっとしない気がする。どうせなら、

class Application
{
public function __construct()
{
$this->_init();
$this->_run();
}
protected function _init()
{
//初期化コード
}
protected function _run()
{
//実行
}
}
new Application();

までやっちゃった方が融通が利くか(staticメソッドのみで書いて、インスタンス化させずに動かした方がきれいか)。

っつーか、起動ファイルの中身をグローバルスコープでフラットに書いていると、可読性が悪くて嫌になってこない?

Published At2007-06-06 00:00Updated At2019-12-30 23:52

技術日記
Zend_Aclのresourceの解決Edit

Zend_Aclで、roleの方はスキーマ定義の段階でだいたい決まることが多いだろうし、それを解決するタイミングもユーザー識別の段階でほぼ確定だろうけど、resourceの方はどうやって解決するのが妥当だろう?

ドキュメントにある例では、resourceを指定せず(すべてのresourceに対して)roleごとに操作権限を設定するようになっているけど、よく使われるのは(すべてのresourceに対する)操作権限を管理するパターンではなく、どのresourceにアクセスできるかを管理するパターンだろう。たとえば、管理ツールには管理者のみがアクセスできる、とか。

そう言う場合、やっぱりmodule=resourceと考えて、Zend_Auth_Plugin_Abstract::preDispatch()あたりで、認証結果から確定したrole+リクエストから抜き出したmodule=resourceとして、$acl->isAllowed()するのが常道かな。module単位よりも細かい単位でアクセス制御したい場合は、function getResourceName($request)みたいなメソッドを用意して、requestから対応するresourceを解決するようにするとか。

ただ、SNSみたいにresourceとroleの関係を動的に解決しなければならないことが多いアプリケーションの場合、Zend_Aclをどう使うのがいいのかはまだ未解決。プラグインとかの共通層では対応が難しそうだから、roleとresourceの関係は抽象化した形で登録しておいて、アクションコントローラの末端でgetResource()とgetRole()を実装して突き合わせるしかないかな。それとも末端でローカルなZend_Aclオブジェクトを生成(=resourceもroleもローカルな定義を作り直す)した方がいいんだろうか。

ちなみに、ようやくZend_Session、Zend_Auth、Zend_Aclを実践的に使ってみているけど、思ったよりもだいぶ使いやすくなっていた。Zend_AuthとZend_Auth_Adapterの関係がちょっとわかりにくかったけど。

Published At2007-06-06 00:00Updated At2019-12-30 23:51

日記
しょうもないバグを見つけたEdit

Zend_Logでmaskとorしているのを見つけたとき以来のしょーもないバグ。まだこんなのが残っているのか。

ちなみになんでこれを見つけたのかというと、ErrorControllerの中で、

$this->getResponse->setHttpResponseCode(403);

をした場合に、なぜかviewRendererでデフォルトのテンプレートがレンダリングされないという症状にはまったから。「Zend_Controller_Response_Abstract::setHttpResponseCode(403)でisRedirect()がtrueにセットされる」→「Zend_Controller_Action_Helper_ViewRenderer::postDispatch()で、render()するかどうかの条件に!$this->getResponse()->isRedirect()を見ている」という原因ね。

Published At2007-06-06 00:00Updated At2007-06-06 00:00

技術日記
ようやくViewの初期化手順が分かったEdit

標準設定状態でのView周りの初期化処理の流れがようやく理解できた。

  • Zend_Controller_Front::__construct()で、viewRendererがZend_Controller_Action_HelperBroker::addHelper()される
  • Zend_Controller_Front::dispatch()内で、Zend_Controller_Dispatcher::dispatch()される
  • Zend_Controller_Action::__construct()が実行され、その中でZend_Controller_Action_HelperBroker::__construct()が実行される
  • Zend_Controller_Action_HelperBroker::__construct()内で、viewRenderer::init()が実行される
  • viewRenderer::init()内で、viewRenderer::initView()が実行される
  • 初回のviewRenderer::initView()でのみ、Zend_Viewオブジェクトが生成され、2回目以降は作成済みのZend_Viewオブジェクトを使い回す
  • viewRenderer::initView()内では、Zend_Viewオブジェクトの生成以外のViewの設定(現在のリクエストに対応したパスの解決など)は、毎回(_forward()されるたびに)行われる
  • viewRenderer::initView()内で、Zend_Controller_Action::$viewにviewRendererの持つViewオブジェクトをセットする
  • これで、アクションコントローラ内のメソッドでは、$this->viewで、viewRendererと共通のViewオブジェクトを利用することができる

なのね。てっきりZend_Controller_Action::initView()の方がメインだと思って、それが呼ばれる場所を探していたよ。Zend_Controller_Action::initView()の方は、viewRendererがない場合用のZend_View生成場所なのね。

ただ、viewRendererの有無を意識したくなければ、アクションコントローラ内では直接$this->viewを使わず、$this->initView()経由でViewオブジェクトを扱うようにした方がいいのかな?

あと、こういう仕組みならば、viewRendererを利用している場合に限り、カスタムView(たとえばZend_View_Smarty)をあらかじめviewRenderer::setView()しておくことで、アクションコントローラ内で$this->viewとか$this->initView()とかして使うことができそうだ。viewRendererを使わない場合は、Zend_Controller_Action::initView()とかを書き直したアクションコントローラを使う必要が出てくるんだろう。

Published At2007-06-05 00:00Updated At2019-12-30 23:52

技術日記
ZF1.0RCのZend_Viewでlayout機能Edit

もうlayout機能がないビューは使いたくないんだけど、Zend Framework 1.0RCになっても、Zend_Viewには標準でlayout機能が搭載されていないらしい。昔layout機能のproposalが出ていた記憶があるけど、あれってどうなってるのかな? Zend Frameworkの開発Wikiにつながらないから、状況がわからん。

前はZend_Viewのラッパーを書いてlayout機能を追加していたけど、1.0RCのZend_Viewはもはやラッパーを書くのは無理っぽいな。テンプレートエンジン差し替えとかコントローラとの連携とかまで考えたラッパーはとても書けそうにない。一発こっきりだったら書けるかもしれないけど、とてもバージョンアップ対応できそうにないし。

しょうがないんで、Zend_Viewをラップする以外の方法でlayout機能を実現しようと思ったんだけど、今のところ思いついたのはアクションコントローラのpostDispatch()でlayout処理を実現するアプローチ。

class FooController extends Zend_Controller_Action
{
public function postDispatch()
{
$response = $this->getResponse();
$view = $this->initView();
$view->contents_for_layout = $respoinse->getBody();
$response->setBody($view->render('path/to/layout.phtml');
}
}
<!-- ヘッダとかごちゃごちゃ -->
<?php echo $this->contents_for_layout; ?>
<!-- フッタとかごちゃごちゃ -->

みたいな感じね。

これはこれで一応動きそうではあるけど、Zend Framework 1.0RCでlayoutしたい場合は、こんな感じでやる派が多数派でしょうか?

Published At2007-06-04 00:00Updated At2019-12-30 23:52

技術日記
mb_convert_kanaの'a'と'rn'は違うのかEdit

元は、

/ ↑全角の斜線は強制的に半角に変換しちゃうのか…。

http://1470.net/user/shingo/2007/05/31#m_134678

というメモで、メモのコメント欄はmb_convert_kana($var, 'KVas')がフィルタとして設定されていた。半角全角カナ英数のみをそろえるだけで、記号は変換かけていないつもりだったんだけど、試しに、mb_convert_kana('/', 'KVas')すると、見事に「/」が「/」に変換される。

結論としては、mb_convert_kana('/', 'a')でも変換がかかった。aオプションって、マニュアルには『「全角」英数字を「半角」に変換します。』と書かれているけど、その下のAオプションのところには『("a", "A" オプションに含まれる文字は、U+0022, U+0027, U+005C, U+007Eを除く U+0021 - U+007E の範囲です)。』という注釈がついている。んで、文字コード表で該当の範囲を見ると、がーん、'a'だと結構な数の記号が対象になっちゃってるじゃん。この記号の取捨選択の意図がよくわからん。

まあともかく、mb_convert_kana($var, 'KVas')じゃなくて、mb_convert_kana($var, 'KVrns')にしておいたほうがいいな。

Published At2007-05-31 00:00Updated At2019-12-30 23:57

技術日記
Zend Framework(1.0RC)もだいぶ複雑になったなーEdit

ようやくZend Framework 1.0RCのMVC周りの概要がつかめてきたんだけど、昔(0.6以前)読んだときと比べるとだいぶ複雑になっているなー。

MVC周りの結合度があがった

前は、シンプルなフロントコントローラ、ルーター、ディスパッチャー、アクションコントローラが疎結合して連携しつつ、それとは独立したシンプルなビューがある、って感じの構成で、ざっと関連ソースをながめれば全体像が把握できたんだけど、もうそんなシンプルな構成じゃなくなっている。

まず、以前は独立していたビューが、現在のバージョンではかなり密にコントローラ周りと結合している。といっても、それなりにインターフェースは整えられているんで、分離不可能になっている訳じゃないけれども、標準状態では一体化して動作する前提になっていて、古い(0.6以前の)知識で扱おうとするとかなりとまどう(特にViewRenderer周りの挙動がわかりにくかった)。

モジュールの導入

あと、以前はアクションコントローラやビューのディレクトリは、それぞれ一つだけ用意するような構造になっていて、そのターゲットとなるアプリケーションのスケールがそれほど大きくない感じだったんだけど、現在のバージョンでは、「モジュール」というアクションコントローラやビューディレクトリを複数管理するための仕組みが追加されている。おそらくは、一つのWebサイト(アプリケーション)で複数のサービス(モジュール)を実装するような、今までよりも大きなスケールに対応できる設計なんだろう。

モジュールの導入により、MVC周りの複雑さがかなり増している。今まではルーティングの結果は、コントローラ名+アクション名+パラメータに解決されていて、ソースコード的には、コントローラクラス+アクションメソッドを追えば良かったんだけど、現在はそれにプラスしてモジュール名という要素もオプショナルに解決されるようになった。モジュール名付きでルーティングが解決された場合は、ランタイムで(コントローラやビューの)ディレクトリのスコープが変わるような動作イメージになってしまうため、コントローラクラス+アクション名だけじゃなくて、収録ディレクトリレベルでソースを追う必要が出てくる。

標準でコントローラ周りと連携して動作するビューは、ランタイムで解決されるモジュールと自動的に連携するようになっているんで、標準で提供されるコントローラ+ルーター+ビューを使っているぶんには、「まあそういうもんだ」って感じで使えるだろう。

でも俺みたいに、Zend FrameworkのMVC周りをラップした自前のフレームワークを作っている人間には、非常に扱いにくい仕組みになってしまった。昔と違って、複数箇所でコントローラやビューが結合しているため、単純にコントローラ(あるいはビュー、あるいはルーター)クラスをラップしたクラスで置き換えるだけでは、うまく動かない可能性が高い。特にオプション設定+アクションヘルパーなんかを経由して、遠回りに結合している部分(たとえばViewRenderer)なんかは、扱いが面倒だ。

現在のMVC周りのまとめ

昔のZend Framework(のMVC)は「取り替え可能なコンポーネント群で構成された、シンプルな疎結合のMVCフレームワーク」と紹介できたけれども、現在のZend Framework(のMVC)は「充実した拡張性を持つMVCフレームワーク。単純な拡張(機能追加)は容易だが、各コンポーネント間の結合は密なので、大規模な拡張(コンポーネント入れ替え)は難易度が高い」って感じかなー。

その他目に付いた主な変更点

って概要レベルの話だけでなく、目について主な変更点も上げておこう。

モジュール

さっきも書いたけれども、モジュールという複数のアクションコントローラ+ビューを管理する概念が追加されている。これがおそらく一番大きな変更じゃなかろうか。互換性のためにモジュールがあってもなくてもそれなりに動作するような実装となっており、それがMVC周りのコンポーネントのコードの可読性を下げていて、ラッパー開発者にはつらいとこ。

アクションヘルパー

あと、新しくアクションヘルパーが追加されている。従来はヘルパーは、ビュースコープで使えるビューヘルパーだけだったけど、今回はアクションコントローラレベルのヘルパーが追加された。ちなみにアクションヘルパーはアクションコントローラ内のメソッドスコープだけでなく、グローバルな(アクションヘルパーブローカーのスタティックメソッド経由)スコープでアクセスできる。従来は、アクションコントローラよりも上のレベルで共用したいロジックは、グローバルなクラス(あるいはグローバルなファンクション)に実装するしかなかったけど、これでアプリケーションスコープで共用ロジックを置く場所ができた。

ビューエンジン

ビューは、新しくエンジンという概念が追加されて、従来のPHPコードを使って記述するビューだけでなく、Smartyとかのテンプレートエンジンを使えるようになった。らしい。というのは、レポジトリを見ても、いまだに他のテンプレートエンジンを使った実装が見あたらないから。MLとかを見ると公式のZend_View_Smarty実装があるみたいなのに。いったいどこにあるんだろう?(といっても、あまり真面目に探してないけど)

入出力ラッパー(Request/Response)

あと、だいぶ前からだけど、入出力にPHPの標準入出力をそのまま使わず、Request/Response系オブジェクトを経由するような仕組みになっている。この辺は(ラッパーを作ろうと)実装を追っていくと結構複雑で面倒くさい部分だけど、標準で使うぶんには従来とさほど変わらないかな? テストとかを作るときにはだいぶ楽になるだろう。

Zend_Db_Tableの拡張

そういやZend_Db_Tableは実装(およびその元となる規約)がだいぶ変わったっぽい。あと、リレーションをたどる機能も追加された模様。ソースをながめた限りでは、機能が少なくてそのままでは用途が限られていた昔のバージョンとはだいぶ変わって、かなり実用的に使えるような雰囲気になっている。ただ、相変わらずモデルクラスをロードする仕組みは特にないっぽいけど、Zend_Loaderでもつかえってことなのかな?

その他

今のところMVC周り以外はほとんど見ていないけれども、AuthとかAclとかの認証・権限管理系のコンポーネントも標準化されていたり、各種ユーティリティクラス系もだいぶ充実している模様。前に見たときにはなかったバリデーション系クラスもちゃんとできているし。っつーか、昔のフィルターとバリデーターがごっちゃになっている仕組みは良くなかったし、それと比べるとだいぶいい感じになっているように見える(ざっと見ただけだけど)。っつーか、なんかWEBXP_FilterとかWEBXP_Validatorと似たような実装になっているなー。

Published At2007-05-31 00:00Updated At2019-12-30 23:57