2009年2月17日火曜日

python code reading for WEB

Python力を高めるためのライブラリコードリーディング

私もDjangoからPythonに入った口ですが、
今もDjangoからPythonにはいる人が多いと思います。

まず読みたいのがこの記事。
Why so many Python web frameworks?

いかにフレームワークを作るのが簡単かがわかり、自分で作ってみたくなる。
「ここで、Djangoなんかたいしたことないじゃん。
もっといいのを私は作れるよ!」
といって色々便利なフレームワークを組み合わせてみると、
ほかのフレームワークのよいところがはじめて見えてくる。

こうして色々試すとようやく「仕事」で使う上でのDjangoの魅力をようやく理解できる。
もちろん、Djangoには欠点がある。
contrib.authの融通の利かなさとか、
modelsがややお間抜けとか、
Routingのエラーメッセージとか、
templatetagの仕様だとか、
動的なFormとか。
解決したライブラリををそれぞれ作ってみたけど、個人使用ならともかく公開はできない。
ただ、解決方法をIRCでねちっこくつぶやくだけ。
だって、メンテしたくないから。
もっといい方法を思いついたら飛び移りたいじゃん。


っと、脱線してしまったけど、
とりあえず、最初にDjangoを読むよりは、個別のライブラリを読むほうが入門しやすい。
フレームワーク以前のPythonの言語自体については、
Code Like a Pythonista: Idiomatic Pythonを読んでください。

みんな、Pythonを愛してください。

2009年2月13日金曜日

Tag Filesystem

stowを使って新しいパッケージなどを試験的に導入したりしていますが、
インストールやらアンインストールって面倒です。

ふと、ファイルシステムがタグベースならアンインストールが楽なのにと気づいた。
インストールして、依存ライブラリにタグをつけていけば明快です。
reference countingと同じ。

実行属性やPATHなどの環境変数、シンボリックリンクの問題も解決するのにな。

まあ、タグだけだとファイルの指定が大変になりそうなので、
適切な解決方法が出るまでは階層構造と併用になりそうですが。

TagFSなど、すでに実装もあるみたいですね。

2009年2月12日木曜日

Clojure

InfoQ: JRuby and Clojure - A Good Match?
Clojureの1.0が近い。





WSGIやRakeみたいなものがあると、俄然やる気が出てくる。
LancetはAntがLisp風になっただけ。
Rakeのインパクトには勝てません。
Ringを見てみたけど、サンプルも少ないのでいまいち。
あまりよさそうには見えない。

SinatraみたいにRouteが散ると、多人数でカオスになっちゃうんだよね。

Clojureはまだまだだと思っているけど、使ってみた人いるかな?


個人的にはJVM言語はGroovyが圧倒的にお勧め。
Pythonよりも好きかも。
Javaの大規模開発もGroovyで始めて徐々にJavaに移行するようにすればいいのにと思っている。
今度、Javaで仕事がきたらやってみたいな。

2009年2月3日火曜日

Django for PHP

Pluf
出ました。
いや、出てました。
すばらしい。

テンプレートエンジン以外はPure PHPと言うところがウリの一つです。

まずURL設定。

$ctl = array();
$base = Pluf::f('idf_base');

$ctl[] = array('regex' => '#^/p/([\-\w]+)/review/$#',
'base' => $base,
'priority' => 4,
'model' => 'IDF_Views_Review',
'method' => 'index');

$ctl[] = array('regex' => '#^/p/([\-\w]+)/review/(\d+)/$#',
'base' => $base,
'priority' => 4,
'model' => 'IDF_Views_Review',
'method' => 'view');

$ctl[] = array('regex' => '#^/p/([\-\w]+)/review/create/$#',
'base' => $base,
'priority' => 4,
'model' => 'IDF_Views_Review',
'method' => 'create');
return $ctl;

うん、まあこんな感じだろうね。
重複も多いし、modelとmethodで分かれているから、少し長い。
あと、分割も標準の方法が見つからないのでもう一工夫ほしいところ。


viewは見慣れたコード。
名前付き引数がないので$match[1]になることと、
名前空間がないので、名前が長くなることがおしい。

public function updateItem($request, $match)
{
$item = Pluf_Shortcuts_GetObjectOr404('Todo_Item', $match[1]);
$new_data = $item->getData();
if ($request->method == 'POST') {
$form = Pluf_Shortcuts_GetFormForModel($item, $request->POST);
if ($form->isValid()) {
$item = $form->save();
$url = Pluf_HTTP_URL_urlForView('Todo_Views::viewList',
array($item->list));
return new Pluf_HTTP_Response_Redirect($url);
}
} else {
$form = Pluf_Shortcuts_GetFormForModel($item, $item->getData());
}
return Pluf_Shortcuts_RenderToResponse('todo/item/update.html',
array('page_title' => 'Update a Todo Item',
'item' => $item,
'form' => $form));
}



テンプレート

{extends 'todo/base.html'}

{block body}
<h2>{$list.name}</h2>

{if $items}
<ol>
{foreach $items as $item}
<li><a href="{url 'Todo_Views::viewItem', array($item.id)}">{$item.item}</a></li>
{/foreach}
</ol>
{/if}

<p><a href="{url 'Todo_Views::addItem', array($list.id)}">Create a new item</a> | <a href="{url 'Todo_Views::updateList', array($list.id)}">Update the list</a></p>
{/block}

すばらしい。
文句のつけようがありません。
まあ、テンプレートエンジンだから当然か。
ところどころPHPの流儀を守っているところがさすがです。

しっかりテストクライアントが付いているところが粋です。

$client->post('/login/', array('login' => 'toto',
'password' => 'secret'));
$client->get('/privatepage/');
$reponse = $client->get($url, array('optional_get_param' => 'toto'));
$this->assertEqual(200, $response->status_code);
// print $response->content;
// print_r($response->template);


モデル

class Todo_Item extends Pluf_Model
{
public $_model = __CLASS__;
// ここに定義を書く
function init()
{
// テーブル名。設定ファイルでprefix設定可能
$this->_a['table'] = 'todo_items';

// クラス名を書く。PHPって自分のクラス名を取れなかったっけ?
$this->_a['model'] = 'Todo_Item';

// フィールド定義
$this->_a['cols'] = array(
// 残念ながらID定義は必要
'id' =>
array(
'type' => 'Pluf_DB_Field_Sequence',
'blank' => true,
),
'item' =>
array(
'type' => 'Pluf_DB_Field_Varchar',
'blank' => false,
'size' => 250,
'verbose' => __('todo item'),
),
'completed' =>
array(
'type' => 'Pluf_DB_Field_Boolean',
'default' => false,
'verbose' => __('completed'),
),
'list' =>
array(
// おまちかね。関連設定。verboseがrelated_nameになる。
'type' => 'Pluf_DB_Field_Foreignkey',
'blank' => false,
'model' => 'Todo_List',
'verbose' => __('in list'),
'help_text' => __('To easily manage your todo items,'.
'you are invited to organize your todo items in lists.'),
),
);
}

get_ + lower case name of the related model + _list
で関連リストが取れます。
でもどうでしょうね。
定義も単純だし、Selectも弱いので、こればっかりは様子見か。


FormはDjangoに忠実。
すばらしいです。
これは使いやすい。
ちゃんとFormForModelがあるので安心。
このFormと他ORMのアダプタをいくつか書いたほうがいいんじゃないのかな。
clean_nameなどのValidationも健在。


middlewareもあるし、
Dispatcherも「おっ!」と思うほどシンプル。
さらになんと、CodeIgniterよりも速い!
残念ながら、Djangoとディレクトリ構成が違うため、
規模が大きくなると散らかってしまうかも。
このあたりはLoaderを書き直してほしい。


面白いことに、このソースが配布されている
http://projects.ceondo.com/自体がPlufで書かれています。
git,svn,hgに対応したSourceBrowser,CodeReviewerにIssueTracker。
非常によいサンプルになり、なおかつ、読みやすいことがわかるのでとてもよい。
http://projects.ceondo.com/p/indefero/
この規模がこれだけ読みやすいなら個人的な用途は十分まかなえそうです。
PHPのソースで読みやすいと感じたのは久しぶりです。

これが広まれば、きっとPHPからDjangoへ流れる人が増えるはず。
PHP派もDjango派も目いっぱい布教しましょう。
オススメです。