PHPでアノテーション

アノテーションとは

プログラミングでは、コード中に登場する要素(クラス、メソッドなど)に対して、それ自体に関する情報(メタデータ)を注記できる仕組みのことをアノテーションという。「このメソッドはテスト用である」「ここでコンパイラは警告を出してはならない」「このメソッドはオーバーライドである」などの情報を付記し、コンパイル時や実行時に参照させることができる。

IT用語辞典

このように説明されるアノテーションですが、その源流を調べてると次の文章に出会いました。

アノテーションとは、JDK 1.5で新たに追加される言語仕様であり、Javaコード上でメタデータ(コードそのものではなくコードに関する付加情報)を記述可能にする。これは、マイクロソフトC#における属性(attribute)に相当するシンタックスで、アノテーションはそれを後追いした仕様といえる。

2004年の@ITnoの記事です。

つまりJavaのアノテーションはC#のアトリビュートに強く影響を受けたものみたいです。
そのことについてC#の作者、アンダース・ヘルスバーグ氏のインタビューが@ITのC#への期待。アンダースからの返答という記事の中で見つかりました。

■Java言語の進化(例:Annotationなど)についてどのように考えているか?

アノテーション(Annotation)に関しては、.NETの属性(Attribute)のJavaバージョンといえると思うが、このように.NETで実装してきていることを、やはりJavaでも行ってきているという印象だ。実際にJavaの最新バージョン5.0に搭載された新機能の中で、(先ほどのアノテーションも含めて).NETに触発されて導入されたと思われるものがいくつもある。

その.Netの属性ページではこのように説明されています。

属性は、プログラムにメタデータを追加します。 メタデータは、プログラム内で定義されている型に関する情報です。 すべての .NET アセンブリに、指定した一連のメタデータが含まれ、そこにはそのアセンブリ内で定義されている型および型のメンバーが記述されています。 カスタム属性を追加すると、必要な任意の追加情報を指定できます。

アセンブリ全体、モジュール全体、クラスやプロパティなどの小さいプログラム要素に、1 つ以上の属性を適用できます。

属性は、メソッドやプロパティの場合と同じ方法で引数を受け取ることができます。

プログラムは、リフレクションを使用することにより、そのプログラム専用のメタデータや他のプログラム内のメタデータを調べることができます。

Javaの注釈ではこのように説明されています。

注釈はプログラムのセマンティクスに直接影響しませんが、ツールやライブラリがプログラムを扱う方法に影響します。そのため、実行中のプログラムのセマンティクスに影響する場合があります。注釈はソースファイル、クラスファイル、または実行時にリフレクションとして読み取ることができます。

PHPでのアノテーション

PHPはアノテーションはネイティブサポートさていませんが、”Status: Under Discussion”のアノテーション提案があります。

Class Metadataという前の提案は否決されたようです

アノテーションの定義

class ReflectionAnnotation
{
    private $value;
 
    public function __construct(\stdClass $value)
    {
        $this->value = $value;
    }
 
    public function getValue()
    {
        return $this->value;
    }
}

アノテーションの表記

/**
 * Foo class.
 *
 * @Entity {"repositoryClass": "FooRepository"}
 * @Table  {"name": "foos"}
 *
 * @author "Guilherme Blanco"
 */

class Foo
{
  // ...
}

アノテーションの利用

$reflClass = new \ReflectionClass('Foo');
var_dump($reflClass->getAnnotations());

PHPの言語としてのサポートにが無いのにも関わらず、現在多くのライブラリ・フレームワークでアノテーションがサポートされています。なぜアノテーションを必要と考えるのでしょうか?提案者はこのように説明しています。

Why do we need Class Metadata?

Frameworks in general rely on metadata information in order to correctly work. They can use it for many purposes:

  • phpUnit Providing meta functionality for test cases, examples: @dataProvider for test data iteration, @expectedException for catching exceptions, etc.
  • Doctrine For Object-Relational mapping, examples: @Entity, @OneToOne, @Id, etc.
  • Zend Framework Server classes Used to automate mappings for XML-RPC, SOAP, etc.
  • FLOW3 for dependency injection and validation
  • Symfony2 for routing rules
  • Others One clear thing that comes to my mind is Validation, Functional Behavior injection (which could take advantage of Traits), etc. Also, any Framework could take advantage of it somehow.

So, any meta mapping injection could be easily achieved via the implementation of a centralized Annotations support.

The .NET framework uses Data Annotation: http://www.asp.net/mvc/tutorials/validation-with-the-data-annotation-validators-cs

An advantage here is the .net framework will process some annotations and inject behavior into the compiled source code.

It’s important to note that annotations exist in java and .net but many strong use cases exist in these languages to provide hints to the compiler (@NotNull).

他に自分が知ってる範囲では、Java Beanの影響を強く受けたDIngやRESTful PHP frameworkのRecessZend Framwork2のDiでもアノテーションが使われています。

ネイティブサポートがないという事はPHPでDocCommentの部分1 をPHPでパースしなくてはならなく、速度的にも不利なところがあるのですが、このようにPHPでもフレームワーク・ライブラリを中心に使われるようになってきているようです。デ・ファクトと言えるようなライブラリがないのか、各ライブラリが独自でパースしてるものが多く、GuiceクローンのアノテーションベースのDIコンテナ Ray.Di を実装したときも最初はそうしていました。

Doctrine\Commons\Annotations

ORMで有名なDoctrineですが、ORMの他にもプロジェクトがいくつか登録されていてライブラリとしてdoctrine ORM使用しているものを単体使用できるようになっています。2

Docotrine Commonsというライブラリがあります。

Common

The Doctrine Common project is a library that provides extensions to core PHP functionality.

“PHPの機能を拡張するライブラリです”という説明で、Doctrineが使っているAutoloaderやCacheもあるのですが、注目はDoctrine Annotations3 です。

RFC提案されてるようにアノテーションを扱います。

アノテーションの定義

@Annotation、@Targetは Doctrineが使用するアノテーションのアノテーションです。
このアノテーションはクラスとメソッドにアノテートすることができます。

/**
 * Inject
 *
 * @Annotation
 * @Target("CLASS")
 * @Target("METHOD")
 *
 * @package    Ray.Di
 * @subpackage Annotation
 */

final class Inject implements Annotation
{
}

setDbメソッドを@Injectとアノテートしました。

    /**
     * @Inject
     *
     * @param DbInterface $db
     */

    public function setDb(DbInterface $db)
    {
        $this->db = $db;
    }

アノテーションの利用

$reflMethod = new ReflectionMethod('MyCompany\Entity\User', 'setDb');
$methodAnnotations = $reader->getMethodAnnotations($reflMethod);

これで全てのアノテーションが取得できます。
あるいは以下のようにして特定アノテーションの値が取得できます。

$methodAnnotation = $reader->getMethodAnnotation($reflMethod, $annotation);

Doctrine\Common\Annotations\AnnotationReader が標準的なアノテーションリーダーです。 (Symfony2では標準でサービスコンテナに登録されてるようです)。
他にはそのAnnotationReaderを利用するCachedReader、use文による名前解決を行わない、より簡素な SimpleAnnotationReaderがあります。

またReaderを使わずパースライブラリとして使いたいなら、doc内のアノテーションを行うDoctrine\Common\Annotations\DocParser や PHPスクリプトを解析してのuse文の名前解決を行う Doctrine\Common\Annotations\PhpParser も有用だと思います。use文の名前解決については Symfony2のブログ Symfony2: アノテーションが改善されましたも参考になると思います。4

※他にはaddendum , php-annotationsというライブラリもあります。

Conclusion

PHPではアノテーションのネイティブサポートはなく、以前は使用はあまり一般的ではありませんでした。しかしPHPUnitでもすっかりおなじみのようにメタプログラミングを実現するためのツールとしてPHP界でも認知されつつあります。自作のライブラリやアプリケーションでも Doctrine Annoattion を用いれば利用の敷居は下がります。速度的な懸念も CachedReaderを使用したり、Configrationに用いたりすることで問題にならない場合も多いでしょう。

ではどのように使うのが良いのでしょうか?広く使われてる割にはなかなかベストプラクティス系の記事が見つかりませんが、1つ見つけました。興味ある方は一読すれば参考になると思います。

Annotations Gotchas and Best Practices

Ray.DiでもこのDoctrine Annotationを採用しリファクタリングを行いました。


  1. リフレクションで取得できます []
  2. (Zend Frameworkのように)このようにライブラリ・ファーストとして部分をライブラリとして単体使用できるのが、最新フレームワークの特徴だと思います []
  3. このドキュメントは2.1のものです []
  4. Fabienさんの記事で、@masakielasticさん翻訳の記事です []

BEAR.Sunday Note

BEAR.Sunday NoteというBEAR.Sundayのスライドを用意しました。
アーキテクチャやアイデアを図や付箋紙でノートのように書いてアップデートしていこうと思います。

体系的でちゃんととしたものではありませんがが、”アジャイルメモ”のように使って行く事で、
アイデアや設計がより整理されるかもと考えました。


PHP: Dis Is It.

昨日2011.12.17にPHP Apocalypse というイベントで”PHP: Dis Is It”と題した発表をしました。
PHP Disを、そのDisそのものよりDisのありようやDis周辺つまり”Meta Dis”視点で考察を行い、PHPという言語のネイチャーを探ろうとしました。

PHPに未来を感じる方いますか?

「PHPに未来を感じる方いますか?」こういう質問をされた発表者の方がいました。僕は勢いよく…と言わないまでも挙手したのですが、周囲を見渡してみると自分一人のようでした。その方の発表では「恐らくPHPは緩やかな下降線を辿っていくと、現在ターミナル医療のような状態だ」というような趣旨の発言で、TL見る限りはそれに同意する方も少なくないようでした。1 

Inconsistency

inconsistency(一貫性の欠如)という誰もが認めるPHPの欠点をキーワードにその原因を”混血”にあるという仮説を立てます。そしてそのInconsistencyを「PHP Disそのもの」にも適用し、本当に言語として駄目設計なら、そのPHP批判にもConsistencyがあるはずなのでは?2 そこにConsistencyが無ければどういう理由なのだろうと考察します。

X Sucks

ソフトウエアバッシングというのはPHPだけではありません。時代を通じでずっと存在し、あらゆる言語にあり、OSにあり、UNIXにもあります。UNIXはいわば”Mother of Software” 過去から今日にいたってあらゆるソフトウエアのファンデーションなのではないか?それを「時代遅れの異臭のするOS」という批判、歴史的で最大の、しかもUNIX制作者によるUNIX批判を紹介しました。そしてその批判の挫折、失敗の考察を紹介し、ではPHPはどうなのかと繋げます。

最良の者が生き残るのではない

最も強いものが生き残るのではなく、最も賢いものが生き延びるわけでもない。
唯一、生き残るのは変化できるものだけである。

ダーウィンの名著「種の起源」での一節です。PHPは強いアイデンティティを持ちません。3 過去現在に渡って躊躇なく変化してきました。そしてその変化の度に少なからず批判を受けてきたように思います。4 

しかし、その変化し続けるという姿勢が、その変化そのものより重要なのであり、5 自分はそこに未来を見る。これが僕の「 This Is It」です。このように「Dis Is It」で始まったプレゼンテーションを「This Is It」で結びました。

Outlook is Gold.

伝えたかった事はもう一つあります。

物事には常に多面性があって自分たちが見ているのは、常にコインのどちらか片方でしかない。

物事を深く広く知れば知るほど、この単純な真実に敬意を示し、反対の立場や考えの異なる人に対する物言いに慎重さや思慮深さが出てくる..ところが現実はそれとは全く反対の方は少なくありません。

「環境に適用しようと変化し続けるものには未来がある可能性が高い」コンピュータ言語の生存をダーウィニズムになぞらえたこの自分の主張も、その多面性のある対象の一考察でしかありません。高名な専門家の、驚くほど一面的でチープな批判を目にした時「これも何かその理由があるんだろう、専門性が視野狭窄に繋がってるのか」そうやって常にその考察背景とアウトルックを問いかけ続ける事ができ、「コインの片側だけで語ってないか?」と疑問を持ち続ける事ができる限り、自分の”self-desciprineランプ”はグリーンに点灯できてるんじゃないかと思います。エンジニアとして、あるいは問題解決の多面性に対峙する仕事人として、もう少し長く生存できるんじゃないかと考えてます。

「アウトルック にこそ価値がある」…これがもう一つ伝えたかった事です。 67

自分でタイトルを決めてpublicな場で発表するのはこれが初めてでした。聞いて下さった方、主催関係者の方々、みなさんありがとうございました。


  1. つまり自分は少数派だったのですが、同時にだからこそ発表の価値もあるのではと思いました。 []
  2. 名前空間やクロージャなど誰もが指摘してた欠陥が少なくなってきた現在のPHPなら尚更です []
  3. カリスマによる強いグランドデザインがありません []
  4. 「だから、PHPにXXXなんか要らないんだって」XXXに色々な言葉がはいってきたように思えます。 []
  5. マクルーハンの「メディアはメッセージである」とおなじように []
  6. 物事の視点、見解 []
  7. http://lists.sugarlabs.org/archive/iaep/2009-July/006940.html []

BEAR.Sunday Prototype Preview

BEAR.Sunday Framework dev2

先日、BEAR.Sundayの紹介をSymfony勉強会で行いました。トヨタ車の愛好クラブに出向いてマツダ車の魅力を語るようなもので、またSymfony2というPHPのフレームワークの中でも最も成熟したフレームワークを愛好してる方々にHello Worldしか出力できないつくりかけのフレームワークを語るという事でもあり、大変恐縮したのですが成り行きでそういう事になりました。最初は汎用技術だけを話していたのですがこれは面白いかもと思うBEARの一部分も紹介し、一部の方に大変な興味を持ってもらい熱心に聞いていただきました。こちらも刺激とインスピレーションをいただき、整理にもなりました。ここに感謝を持ってそのHello Worldアプリの紹介をしたいと思います。

https://github.com/koriym/BEAR.Sunday
https://github.com/koriym/BEAR.Sunday/tree/dev2/apps/00-helloworld-min

(このプロトタイプ作成の目的は全体構成を確認、評価することと、オブジェクトグラフのキャッシュの可否、メソッドインターセプトを利用したリソースオブジェクトのAOP実装、ラフなパフォーマンス評価、ビューとページの構成評価などです。詳しくはGitHubにあります。)

Hello World

BEAR.Sundayでは、MVCフレームワークのC=コントローラーにあたる部分をPageリソースが担当します。
最小構成に近いページはこのようになります。

class Hello extends Page
{
    public $code = 200;

    public function __construct()
    {
    }

    public function onGet($name)
    {
        $this->body = 'Hello ' . $name;
        return $this;
    }
}

ページリソースはページコントローラーの役割を持ちます。HTTPをモデルにした、code, headers, bodyの公開されたpublicプロパティを持ちますが、継承元はメソッドを持ちません。またビューオブジェクトも持ちません。代わりにリクエストメソッドに応じたインターフェイスメソッドがあります。ページのGETリクエストに対してonGet()が対応します。

ページの仕事(関心)はテンプレートに何かをセットする事ではなく、自らを構成する事です。最も大事なのはページの状態(code プロパティ)です。デフォルトは200=OKです。それ以外の場合、例えばこのページリソースは$nameを受け取らないとページが構成できないとします。その場合「リクエストに不正がある」400(=Bad Request)をセットします。

    public function onGet($name)
    {
        if (is_null($name)) {
            $this->code = 400;
            return $this;
        }
    }

たったことだけの事で400 Bad Requestは大げさでしょうか?それはアプリケーションのビューが決めます。表現と構成は別の関心です。例えばそれは「名前を入力して下さい」という画面かもしれませんし、AJAXアクセスに対して400 Bad RequestというHTTPコードと何が足りないかを示すJSONかもしれません。ページはどう表現されるかは関心を持たずに、自らの状態を構成する事だけに専念します。

ステータスコード

基本的には以下のようなHTTPステータスコードに準じたもので決定します。1

            // 103-199   Unassigned
            '200' => 'OK',
            '201' => 'Created',
            '202' => 'Accepted',
            '203' => 'Non-Authoritative Information',
            '204' => 'No Content',
            '205' => 'Reset Content',
            '206' => 'Partial Content',
            '207' => 'Multi-Status',
            '208' => 'Already Reported',
            // 209-225   Unassigned
            '226' => 'IM Used',
            // 227-299   Unassigned
            '300' => 'Multiple Choices',
            '301' => 'Moved Permanently',
            '302' => 'Found',
            '303' => 'See Other',
            '304' => 'Not Modified',
            '305' => 'Use Proxy',
            '307' => 'Temporary Redirect',
             // 308-399   Unassigned

繰り返しますがこれがどのようなHTTP出力となるかはビューの仕事(関心)です。そのまま出力されるかもしれませんし、2XXは全て200で出力するかもしれません。出力実装の事は考えず、ページはページの事だけを考え自らを構成します。これはプレゼンテーション(ビュー)はページ状態の反映(プロジェクション)でなければならないという考えに基づきます。どのように表現されるかページは最後まで知りません。

リクエストメソッドも同様です。GET, POST以外のリクエストが現状のWebサーバーやHTML4では難しい、とは考えません。別のレイヤーがそのリクエストを担い解決します。ページは純粋な動詞を持ったHTTPが普通に使われる世界にいるように記述します。

この単純な例ではページのコンテンツをbodyプロパティにセットする事で自らを構成しました。code=200でbodyにメッセージの入った単純なページです。

リソースクライアント

ページリソースはいわばサービスです。それを利用するクライアント(=リソースクライアント)がページリソースをアクセスします。このようにサーバーサイドであってもリソースクライアント・リソースサービスは常に区別されます(関心の分離)2

$response = $resource
->get->uri('page://self/hello')->withQuery(['name' => 'Sunday'])->eager->request();

リソースをアクセスするのにはこのような専用の表記(DSL)をします。これは「リソースクライアント($resource)を使って、page://self/hello というページリソースを?name=queryというクエリー(問い合わせ)でeager(直ぐに)GETリクエストする」という意味になります。

普通のオブジェクトのメソッドコールと違って、クラス名を使わずURIを使っている点、メソッドコールが名前付引き数(順序でなく変数名で変数を指定している)で行われてる点に注意してみてください。PageリソースはWebサービスを提供しているようにリクエストを受け取とり、自己($this)をレスポンスとして返します。

$responseをvar_dumpしてみます。

object(helloWorld\Page\Hello)#51 (4) {
 ["uri"]=>
  string(17) "page://self/hello"
  ["code"]=>
  int(200)
  ["headers"]=>
  array(0) {
  }
  ["body"]=>
  string(12) "Hello Sunday"
}

ページリソースが返ってきました。HTTPレスポンスと同じようにcode, header, bodyを持っているのでheader関数とechoで出力するのは容易です。あるいはコンテンツネゴシーエションをして、リクエストヘッダーに応じてJSONやモバイル用コンテンツに出力することもできるでしょう。

リクエスト

eagerリクエストは即リクエスト実行です。リクエストの実行結果が取得できます。では、eagerでないリクエストは何が返ってくるのでしょうか?

$request = $resource->get->uri('page://self/hello')->withQuery(['name' => 'Sunday'])->request();
echo $request;

//get page://self/hello?name=Sunday

リクエストが返ってきます。このリクエストオブジェクトは文字列表現を持っているので、echoすることができます。リクエストオブジェクトは以下のように関数を実行するように記述すればその時にリクエストが実行されます。

$response =  $request();

つまり、リソースリクエストはeagerをつけると即実行、つけないといつでも実行可能なリクエストに必要な全ての情報を持っているリクエストオブジェクト、そのどちらかが得られます。 3

REST = Representational State Transfer

これまで見た来た様に、ページは自らの状態コードとコンテンツをセットして自分自身を構成します。4 リソースクライアントからのリクエストを受けてページはその構成された状態をreturn $this;と返します。RESTはRepresentational State Transferの略です。直訳すると(リソースの)表現状態の転送 。BEARのリソースもこの原則に従っています。

この記事での「あいさつページリソース」は「Hello Sunday !」という(リソース)表現状態(Representational State)になってリソースクライアントに転送(Transfer)されます。Representational State Transfer、つまり RESTです。

テスタビリティ

リソースはその利用がサーバーサイド内部でもクライアントとサービスに分かれてるので、テストコードではそのクライアントをそのまま記述できます。

ページの仕事はテンプレートのHTMLを構成することではなく、ページ自身を構成することなので、ページがどのような状態なのかページのHTMLを見るまでもなく、まずコードに入っています。次に(今回説明しませんでしたが)ページのヘッダーにはページのメタ情報が入っています。これもコード同様、どのように出力されるかとヘッダーの内容の実際とは関心が分離されます。5

これらは全てページコントローラーのテスト可能性に繋がります。

テスト時には全ての出力とPHPコンテキスト、webコンテキストをDBに保存して、デバックに役立てる事ができるかもしれません。入力と出力、プログラムのスタートアップと出力&終了はユーザードメイン(領域)にあり可能です。6

スクリプト

現在試験的にこの最も上位の層での処理をPHPスクリプト(includeしただけで実行される素のPHPスクリプト)で行っています。クラスベースの通常のPHPコーディングと違い、機能単位でスクリプトを用意して複数includeする事で全体を構成しようとしています。

例えばページリソースへのリクエストが終わった段階で、リソースリクエストをハンドルするハンドラスクリプトを用意してあれば、内部アプリケーションリソースURIに応じて特定リソースリクエストにACLを適用したり、実行をページ終了後に行う事ができます。(足跡DBの更新を画面表示のあとに行う等)このように、入力、ページリソースリクエスト、リクエスト実行、出力、などの大きな構造をユーザードメインのスクリプトを読み込むことで構成しています。

またスクリプトをリソースとURIと対応させ、他のフレームワークやCMS等と組み合わせる事を可能にします。
例えば、商品の残り個数がapp://self/goods/stock/quantity/?id=100というアプリケーションURIで利用可能だとして、WordPressのウィジェットなどから

残り個数は<?php include '/path/to/goods/stock/quantity/?id=100'; ?>です

等と呼べたらどうでしょうか。

リソースは一意につけられるURIというIDを持ち、そのリクエストには状態がありません。自らの表現へのリンクを持つ事ができ、上記のような最小限のリクエストを可能にします。副作用のないGETリクエストは何度でも同じ状態を返すはずでキャッシュも機能するでしょう。上記の最小限のクライアント利用を前提にするので、フロントコントローラーやルーターはBEAR.Sundayではオプションになります。

あるいはページコントローラーの無い、テンプレートとアプリケーションリソースだけがあるページはどうでしょうか。DrupalやWordPressのようなCMSの多くはコンテンツ・プルで情報が取得されます。コントローラーがテンプレートにコンテンツをpushするのではなくて、ビュートリガーで情報がPullされます。テンプレートを先に読み込み、テンプレートに出現したアプリケーションリソースがPullされます。 (詳しくはWebアプリケーションフレームワークを)

まとめ

モデル(アプリケーションリソース)を持たない単純なHelloWorldアプリを見てきました。リソースリクエスト専用問い合わせ言語(DSL)、ページコントローラーのビューへの無関心(ページは出力を構成しようとせず自らを構成しようとする)、ビューはページリソース状態の反映として扱われる、リソースリクエストは記録可能で遅延実行(レイジーエバリュエーション)可能などの特徴がありました。またそれらの実行フローはスクリプトで構成されアプリケーションドメインになっている。入力と出力はフレームワークが行うのではなく、フレームワークのライブラリを使うがユーザードメインで行う、つまり構成は変更できるという事を見てきました。

今回全然触れなかったものに、アノテーションベースのGuiceスタイルのDIコンテナ、メソッドインターセプターによるアスペクト指向プログラミング、リソースリンク、TraitとDIを使ったテンプレートエンジン選択、マルチアプリケーションリソース、ユーザースキーム、HATEOAS = Hypermedia As The Engine Of Application State(アプリケーション状態のエンジンとしてのハイパーメディア)、オブジェクトグラフキャッシュ等があります。これらは実装がある程度進んで来たもので、現時点でもある程度は紹介可能です。

HTTPを通信プロトコルとしてでなく、アプリケーションスタックとして内部、外部ともに使おうという試みでもあるのですが、今回の記事では一部コードの話で触れただけでした。これができて便利、あれを実装するのが一瞬でできる…という実装の話でなく、設計やコンセプトに興味を持ってもらったので今回の記事はそれに沿ったミニマムなものにしました。

再度お礼を言います。あの時、スクリーンの真ん前で熱心に見て、聞いて、質問してくださった皆さん、どうもありがとうございました。また別の機会でお会いできればと思います。


  1. アプリケーション状態を表したいが、このHTTPコードに合わない時はUnassignedのところで自分のコードを決め、アサインします。例えば210はログインしてる、211は有料会員の状態等とアプリケーションコードを決めても良いでしょう。 []
  2. MVCで言うとMVCの外側にクライアント(エディター)がいて、外側からコントローラーを操作しているようなものかもしれません。 []
  3. request()以外の全てのメソッドは$thisが帰って来ててデメテルの法則に従っています []
  4. ただ代入してるのだけに大げさな言い方に聞こえるかも知れませんが []
  5. 現在デバック用にセットされてるメモリ使用量や速度などヘッダー(ページ実行のメタ情報)は実際のprod環境では出力されないでしょう。 []
  6. 設定ファイルやコードでその処理を担うクラスを指定するのではなく、直接コーディングします。 []

PHPコーディング規約 – modernphp

PHP_CodeSniffer

PEARにPHP_CodeSnifferというコーディング規約チェッカーがあります。

PHP_CodeSniffer は PHP5 用のスクリプトで、PHP や JavaScript そして CSS のコードについて構文解析や “sniff (クンクンにおいを嗅ぐこと)” を行い、 コーディング規約に反するところを検出します。 開発者には不可欠であろうこのツールを使用することで、 あなたのコードをきれいで一貫性のあるものにできます。 また、開発者がおかしがちな間違いを防ぐ助けにもなります。

PEAR, Zend規約

デフォルトでPEAR, Zend等の規約が入ってるのですがこれがイマイチ使い勝手がよくありません。具体的にはPEARの規約はコメントのタグのチェックが中心です。1 Zendは規約があまり定義されてなく、これら2つの規約は肝心のコードをあまりチェックしてくれません。

Squiz規約

このライブラリを作成したSquiz Laboの規約が最も詳細にチェックしてくれるのですが、あまりに規約が細かすぎ&こだわり過ぎで&独自規約で山のようにエラーが出てしまいます。肝心なものが埋もれこれも使い勝手が良くありません。

modernphp規約

PHP_CodeSnifferは規約ルールセットを定義したXMLを用意する事で、コード規約をカスタマイズする事ができます。そこで定義済みの規約の中から現在のPHPコーディングで一般的だと思われる規約をピックアップして、使いやすいものを用意しようというのが今回のmodernphp規約です。自分の好みに寄らず、現在のPHPコーディングでより標準的なものはどういうものかという視点で調整しました。

これは中々難しい作業です。現在の有名ライブラリやフレームワークに共通したコーディングスタイルがあるのはあると思うのですが、すべてに通るようなものならせっかく大量に用意された規約のほとんどを使わない事になります。しかしユルユルにしたのでは規約の意味があまりありません。2

そこで大量の規約のオンオフがやりやすい形にして、そこから調整する方法はどうかと思いました。まずは全ての規約をオンにして、そこから排除する規約を最も細かい規約単位でオフにしていきます。

インストール

GitHub: phpcs-modernphpを直接、またはフォークして使います。

$ pear install PHP_CodeSniffer
$ cd /path/to/PEAR/PHP/CodeSniffer/Standards
$ git clone git://github.com/koriym/phpcs-modernphp.git modernphp
$ phpcs --config-set default_standard modernphp

※PEARディレクトリがわからないときはこれで表示されます。

$ pear config-show | grep php_dir

調整方法

-sオプションで使います。

$ phpcs -s /path/to/src --standard=modernphp

不要なものを削る時

例えば以下のエラーは「条件によっては読み込まないファイルはrequireではなくてincludeで読み込む」というエラーです。

 218 | ERROR | File is being conditionally included; use "include_once" instead
     |       | (PEAR.Files.IncludingFile.UseIncludeOnce)

これが不要ならrulseset.xmlを編集して以下のように不使用を指定します。

<rule ref="PEAR.Files.IncludingFile.UseIncludeOnce"><severity>0</severity></rule>

modernphpで削除されてるものを加える時

phpcs規約を指定して沢山出るエラーから目的のものを見つけ、ruleset.xmlに追加します。

$ phpcs -s /path/to/src --standard=phpcs

※これで出ない規約は自分で作成するしかありません。

XMLの設定方法はSauiz Laboのruleset.xml 解説ページが参考になります。

規約を公開する

PHPUnitの作者として有名なSebastian Bergmann氏は自分のコーディング規約をSebastian.規約としてGitHubで公開してます。

氏のように自分はこの規約にしたがってコーディングしてると宣言的に公開するのもまた面白いのではないでしょうか。


  1. PEARライブラリ用にかなり多くのphpdocタグを要求します。 []
  2. また主流はどちらか議論の別れるものもあります。例えばprivate / protecedの変数は_(アンダースコア)を接頭子として使うのがPHP4時代からPEAR規約として標準的でしたが、名前で型を表すのは?という議論もあり、多くの開発者がその規約を離れているような感じがします。 []

テストでPHP5.4の開発にコントリビュートしよう

現在PHPデベロッパチームはPHP5.4の正式リリースに向けて準備をしていますが、テストを行い結果を送信することで開発協力する事ができます。コーディングも英語も必要ありません。数分で完了します。

ダウンロードとテスト

PHPのソースをダウンロードしてテストを行います。

$ cd /tmp
$ wget http://snaps.php.net/php5.4-latest.tar.gz
$ tar xzvf php5.4-latest.tar.gz
$ cd php5.4-*
$ ./buildconf
$ ./configure
$ make
$ make test

これで数分かけて8000以上のテストが走ります。
テストが一部失敗すると以下のように出ます。

=====================================================================
FAILED TEST SUMMARY
---------------------------------------------------------------------
ZE2 A class constructor must keep the signature of all interfaces [tests/classes/ctor_in_interface_02.phpt]
SPL: DirectoryIterator test getGroup [ext/spl/tests/DirectoryIterator_getGroup_basic.phpt]
SPL: DirectoryIterator test getOwner [ext/spl/tests/DirectoryIterator_getOwner_basic.phpt]
Bug #39322 (proc_terminate() loosing process resource) [ext/standard/tests/general_functions/bug39322.phpt]
Bug #49936 (crash with ftp stream in php_stream_context_get_option()) [ext/standard/tests/streams/bug49936.phpt]
Bug #32001 (xml_parse*() goes into infinite loop when autodetection in effect), using UTF-* [ext/xml/tests/bug32001.phpt]
=====================================================================

You may have found a problem in PHP.
This report can be automatically sent to the PHP QA team at
http://qa.php.net/reports and http://news.php.net/php.qa.reports
This gives us a better understanding of PHP's behavior.
If you don't want to send the report immediately you can choose
option "s" to save it.  You can then email it to qa-reports@lists.php.net later.
Do you want to send this report now? [Yns]:

このレポートを送りますか?と質問されるのでYと答えメールアドレスを入力するとレポートを開発チームに送る事ができます。
自動送信に失敗する場合は表示されるメールアドレスに手動で送信します。

Thank you for helping to make PHP better.

レポートを送ると最後に出てくるメッセージです。

Posting to http://qa.php.net/buildtest-process.php

Thank you for helping to make PHP better.

送信結果はこのページに反映されるはずです。http://qa.php.net/reports/
お疲れさまでした。

※さらなるテスト協力はRamsusさん作成のインストラクションに詳細があります。


Ray.Di on Aura.Di

Aura.Di

Ray.DiはAura.Diを使用しています。AuraはPHP5.3用フレームワークで、Paul M.Jones.氏がリードのPHP5.2用フレームワークSolarPHPの現在のメジャーバージョンです。有名なフレームワークでは無いかもしれませんが、ライブラリファースト、コンパクトでクリーンなコード、100%テストカバレッジ等、リファレンスとすべき多くの点があるのではと思います。

Ray.Diは基本的にはアノテーションベースのDIコンテナですが、アノテーションを全く使わないAura.Diの上に構築されています。なのでどちらの方法でも依存性の注入を行う事ができます。前回の記事ではアノテーションを使った方法だけ紹介しましたが、この記事では両方の方法を紹介してそれぞれ比較したいと思います。

まずはそのどちらも使えるインジェクターの生成からです。

インジェクターの生成

Containerクラスのインスタンスと、インターフェイスとクラスを紐付けるモジュールの二つを引き数に取ります。ContainerクラスにはForge、ForgeにはConfig、ConfigにはAnnotationインスタンスが必要です。

$di = new Injector(new Container(new Forge(new Config(new Annotation))), new AppModule);

あるいは、

instance.php

require_once  '/path/to/Ray.Di/src.php';
return new Injector(new Container(new Forge(new Config(new Annotation))), new AppModule);

このようにincludeを使って

$di = include '/path/to/scripts/instance.php';

インスタンスをスクリプトから代入します。

クリーンな依存関係

使用される全てのクラスがインターフェイスを持ち、それぞれ必要とされるクラスのコンストラクタで受け取っています。固定化されたクラス関係は存在せずクラスの依存関係はクリーンで、ユーザー作成のコンポーネントとも入れ替え可能です。DIコンテナが扱うクラスだけでなく、DIコンテナそのものも実装(実クラス)ではなく、インターフェイスでつながれています。1

コンストラクタ・インジェクトション

Ray.Diはコンストラクターインジェクションとセッターインジェクション(メソッドを使ったインジェクション)をサポートします。2。3rdパーティのものや既存のライブラリ等、アノテーションが使えない場合の方法と使う方法を別にして紹介します。

ターゲットクラス

ターゲットになるクラスです。ListerクラスのコンストラクタにFindインターフェイスを実装したインスタンス(Finder)を渡す必要があります。

namespace MovieApp {
    class Lister {
        public $finder;
        public function __construct(Find $finder){
            $this->finder = $finder;
        }
    }
    class Finder implements Find {}
    interface Find{}
}

アノテーションを使わないコンストラクタ・インジェクション

イーガーセット

    $di = include __DIR__ . '/scripts/instance.php';
    $di->getContainer()->params['MovieApp\Lister'] = array(
       'finder' => new MovieApp\Finder
    );
    $lister = $di->getInstance('MovieApp\Lister');

params[クラス名]として、ネームドパラメーター3 で引き数を指定します。この準備は通常アプリケーションのブート時等に1度だけ行います。getInstance()時にはコンストラクタ引き数を指定していませんが、”予約”した方法で引き数が渡されインスタンスが生成されます。

レイジーセット

    $di = include __DIR__ . '/scripts/instance.php';
    $di->getContainer()->params['MovieApp\Lister'] = array(
        'finder' => $di->getContainer()->lazyNew('MovieApp\Finder')
    );
    $lister = $di->getInstance('MovieApp\Lister');

イーガーセットでは準備の段階で引き数に必要なインスタンスを生成しましたが、もしかしたら使わないかも、あるいは準備時にはまだインスタンスが確定できないものはlazyNewというメソッドを使ったレイジーセットが行えます。インスタンスの代わりにインスタンスの生成方法をセットしておいてgetInstance()時に遅延実行されコンストラクタ引き数として渡されます。引き数1つめにクラス名、2つ目に引き数をネームドパラメーターで指定します。

クラス同様、コンストラクタインジェクションの設定も親クラスから小クラスに継承されます。つまり、Finderクラスを継承した子クラスの取得時にも適用されます。またgetInstance()の第二引き数でインスタンス取得時に、設定した引き数を指定したパラメーターだけ上書きすることができます。4

アノテーションを使うコンストラクタ・インジェクション

ターゲットのメソッドに@Injectアノテーションでマークします。Ray.Diにインスタンスを代入しなければならない事が伝わります。

namespace MovieApp {
    class Lister {
        public $finder;
        /**
         * @Inject
         */

        public function __construct(Find $finder){
            $this->finder = $finder;
        }
    }
    class Finder implements Find {}
    interface Find{}
}

AbstractModuleを継承したモジュールのconfigureメソッド内でインターフェイスと実クラスを指定します。AbstractModuleにはインターフェイスとクラスを結ぶ様々なメソッドがあり、英語表現のようなDSL5 でインターフェイスとクラスを紐づけます。

    class Module extends \Ray\Di\AbstractModule
    {
        public function configure()
        {
            $this->bind('MovieApp\Find')->to('MovieApp\Finder')->in(Scope::SINGLETON);
        }
    }

前回の記事ではインスタンスを直接してしましたが、この例では実クラスを指定してin()でそのクラスはシングルトンスコープで利用されるように指定しています。二回目以降の注入には同じインスタンスが再利用されます。

    $di->setModule(new Module);
    $lister = $di->getInstance('MovieApp\Lister');

そのモジュールをセットしたインジェクターでインスタンスを取得します。

Conclusion

アノテーションを使用しないでクラス名やメソッド名を指定してそこの何を入れるかを指定する方法と、アノテーションを使ってインジェクトするポイントを指定しインターフェイスとクラスをワイアリングする方法と、依存オブジェクトの2つの指定の方法、Ray.Diはそのどちらも可能という事を見てきました。前者はXMLやYAMLファイルなどのスタティックな設定を持つことが多く、Symfomy2やFlow3、Ding等はこの方式です。何処で注入するかと場所に注目して指定する方法と、何が注入されるかに注目する指定する方法、の2つとも言えないでしょうか。6

* サンプル https://github.com/koriym/Ray.Di/tree/annotation/doc


  1. InjectorとAnnotation以外は全てAuraのコンポーネントです。Configだけ一部機能追加してますが他のクラスはAura.Diそのままです。 []
  2. 現在プロパティインジェクションは実装されていません []
  3. 引き数を順番ではなく変数名で指定 []
  4. $host, $id, $passを引き数に取るようなコンストラクタでgetInstance($class, array(‘host’ => $host);と指定すると$id, $passはデフォルトの値で$hostだけを指定できます。 []
  5. Guiceでこのように表現されてました []
  6. 個人的には前者はコンテナやコンパイルなど実装の都合から生まれた方法で、後者はインターフェイス指向をより意識した方法ではないかと思うのですがどうでしょうか []

Ray – Annotation based Dependency Injection system for PHP

Ray.Di

Ray.Di は DI (Dependency Injection: 依存性注入) のためのフレームワークです。Google Guiceにインスパイアされ、Aura.Diを利用したPHP用DIコンテナです。メソッドインターセプターによるアスペクト指向プログラミングをサポートします。

この記事は初学者向けのDIやAOPの解説は含みませんが、1サンプルを通じてなるべく分かりやすく全体構成を説明したいと思います。

ターゲットオブジェクト

インジェクト対象となるメソッドに@Injectとマークします。@PostConstuctはインスタンスコンストラクトされ後の初期化メソッドを表します。@Transactional, @Templateはユーザーが定義したアスペクト指向プログラミングのためのアノテーションで、@Aspectと共に用い、そのメソッドがインターセプトされる事を指定します。

/**
 * @Aspect
 */

class User
{
    private $db;
   
    /**
     * @Inject
     * @Named("pdo=pdo_user")
     */

    public function __construct(\PDO $pdo)
    {
        $this->db = $pdo;
    }

    /**
     * @PostConstruct
     */

    public function init()
    {
        // if not exist...
        $this->db->query("CREATE TABLE User (Id INTEGER PRIMARY KEY, Name TEXT, Age INTEGER)");
    }

    /**
     * @Transactional
     */

    public function createUser($name, $age)
    {
        $sth = $this->db->prepare("INSERT INTO User (Name, Age) VALUES (:name, :age)");
        $sth->execute(array(':name' => $name, ':age' => $age));
    }

    /**
     * @Template
     */

    public function readUsers()
    {
        $sth = $this->db->query("SELECT name, age FROM User");
        $result = $sth->fetchAll(\PDO::FETCH_ASSOC);
        return $result;
    }
}

モジュール

モジュールではインターフェイスと実クラスやインスタンス、ファクトリを紐づけるコードを記述します。ユーザー定義のアノテーションはインターセプターと紐づけます。インターセプターはネスト可能でこの例では@TransactionalとマークされたメソッドはTimerとTransactionの機能がネストされて適用されます。

class UserModule extends AbstractModule
{
    protected function configure()
    {
        $pdo = new \PDO('sqlite::memory:', null, null);
        $this->bind('PDO')->annotatedWith('pdo_user')->toInstance($pdo);
        $this->registerInterceptAnnotation('Transactional', array(new Timer, new Transaction));
        $this->registerInterceptAnnotation('Template', array(new Template));
    }
}

インターセプター

メソッド実行に割り込み、元メソッドの前後の処理をコーディングします。このタイマーインターセプターでは タイマーのスタートとストップの間に$invocation->proceed();として元のメソッドが実行されています。 array(new Timer, new Transaction)と指定することで、タイマースタート、トランザクションスタート、元メソッド実行、トランザクションコミット、タイマーストップと処理がネストされインターセプターに挟まれたその中心で元メソッドが実行されます。


@IT総合トップ > @IT CORE > Java Solution > Java EE 5マイグレーションプラクティス(1)より


Manjesh’s Blog Aspect Oriented Programming and Unity 2.0 より

タイマーインターセプター

/**
 * Timer interceptor
 */

class Timer implements MethodInterceptor
{
    public function invoke(MethodInvocation $invocation)
    {
        echo "Timer start\n";
        $mtime = microtime(true);
        $invocation->proceed();
        $time = microtime(true) - $mtime;
        echo "Timer stop:[" . sprintf('%01.7f', $time) . "] sec\n\n";
    }
}

トランザクションインターセプター

リフレクションを使い元オブジェクトのプライベートプロパティのPDOオブジェクトを操作してトランザクションを実現しています。

/**
 * Transaction interceptor
 */

class Transaction implements MethodInterceptor
{
    public function invoke(MethodInvocation $invocation)
    {
        $object = $invocation->getThis();
        $ref = new \ReflectionProperty($object, 'db');
        $ref->setAccessible(true);
        $db = $ref->getValue($object);
        $db->beginTransaction();
        try {
            echo "begin Transaction" . json_encode($invocation->getArguments()) . "\n";
            $invocation->proceed();
            $db->commit();
            echo "commit\n";
        } catch (\Exception $e) {
            $db->roleback();
        }
    }
}

テンプレートインターセプター

連想配列をフォーマットされた文字列に変換しています。

/**
* Template interceptor
*/

class Template implements MethodInterceptor
{
    public function invoke(MethodInvocation $invocation)
    {
        $view = '';
        $result = $invocation->proceed();
        foreach ($result as $row) {
            $view .= "Name:{$row['Name']}\tAge:{$row['Age']}\n";
        }
        return $view;
    }
}

インジェクター

インジェクターを生成し、モジュールをセットして対象のインスタンスを取得します。インスタンス取得時にオブジェクトグラフ(必要オブジェクトのリレーション)が解決され依存するオブジェクトが全て生成(またはレイジーロード可能なオブジェクトを取り出す機能のみを持ったオブジェクトプロバイダー)がセットされ対象インスタンスが生成されます。

モジュールは通常のwebアプリケーションならbootstrapで1回だけ作成します。@Aspectとマークされメソッドインターセプトされるオブジェクトは、Weaveオブジェクトというメソッドがインターセプトされ代理実行されるプロキシーオブジェクトに変わります。元のオブジェクトのメソッドを受付け、元のオブジェクトのように振る舞う代理オブジェクトです。

$injector = include 'path/to/scripts/instance.php';
$injector->setModule(new UserModule);
$user = $injector->getInstance('Ray\Di\Sample\User');
/* @var $user \Ray\Di\Sample\User */
$user->createUser('Koriym', rand(18,35));
$user->createUser('Bear', rand(18,35));
$user->createUser('Yoshi', rand(18,35));
$users = $user->readUsers();
var_export($users);

実行結果

Timer start
begin Transaction["Koriym",33]
commit
Timer stop:[0.0001919] sec

Timer start
begin Transaction["Bear",32]
commit
Timer stop:[0.0001190] sec

Timer start
begin Transaction["Yoshi",27]
commit
Timer stop:[0.0001149] sec

Name:Koriym Age:19
Name:Bear Age:28
Name:Yoshi Age:18

オリジナル実行

オリジナルのメソッドをそのまま実行した場合する場合のコードと結果です。ターゲットクラスに依存技術がなく、プレーンな形で実行とテストが可能です。

$pdo = new \PDO('sqlite::memory:', null, null);
$user = new \Ray\Di\Sample\User($pdo);
$user->init();
$user->createUser('Koriym', rand(18,35));
$user->createUser('Bear', rand(18,35));
$user->createUser('Yoshi', rand(18,35));
$users = $user->readUsers();
var_export($users);

array (
  0 =>
  array (
    'Name' => 'Koriym',
    'Age' => '33',
  ),
  1 =>
  array (
    'Name' => 'Bear',
    'Age' => '20',
  ),
  2 =>
  array (
    'Name' => 'Yoshi',
    'Age' => '27',
  ),
)

Conclusion

依存オブジェクトが注入される元のクラスには特定のベースクラスの継承や、DIコンテナ等特定の技術に対する依存がありません。利用するオブジェクトや値は全て外部から入力されます。インターフェイスやアノテーションを、クラスやインスタンスまたはファクトトリークラスと結びつけたモジュールを用いて、インジェクターが必要とするオブジェクトを注入 1 します。

アノテーションでマークされたメソッドはインターセプトされるメソッドと解釈され、代理オブジェクトによってそのメソッドが代理実行されます。各処理を横断的に共有する関心の実行に役立つと同時に、メソッド内の処理を本質的なものと付帯的なもの、それぞれドメインロジック(ビジネスルール)、アプリケーションロジック(認証やロギング)と分離する事にも役立ちます。オブジェクト指向プログラミングの大原則に関心事の分離があるとするとアスペクト指向プログラミングはそれを補完する横断的関心事の分離に他なりません。

この記事ではRayの基本的な使用法の紹介だけにとどめ、DIやAOPの効用や用語、概念の詳しい解説は行いませんでした。またパフォーマンスやこの技術が向いている問題領域、不向きな領域、アプリケーションでの可能性や、現在ある課題にも触れていません。プレビューリリースとして基本機能を簡単にご紹介しました。

DIに関するより良い議論

先日行われたZendConでZend FrameworkチームのエンジニアのRalph Schlenderさんがzf2のZend Diについてスライドを公開しています。zf2のDIだけでなく、特に前半DIについて語られています。素晴らしい内容で、共感する内容も多いです。紹介します。

Try it

ここで紹介したサンプルアプリはこのテストで簡単に実行することができます。ご協力頂ければ大変ありがたいです。現在は簡単な英文マニュアルがあるだけですがkoriym/Aura.Diで公開しています。


  1. 外部から代入 []

Steve Jobs 1955-2011

2011年10月5日 Steve Jobs氏死去。
謹んでご冥福をお祈りします。

Steve Jobs


16の時にApple IIcを使い始めて以来のApple製品ユーザーです。

Apple IIc

Macinthos SE/30

iMac DV Saige


PowerMac G4 Cube

iPod first

人々を引きつける彼のプレゼンテーションでも最も特別なのはやはりMacworld 2007 Keynoteでしょう。その冒頭でJobsは「世の中を変えてしまう製品というのがある。一度でも幸運なことだが、Appleは過去に2つやりとげた。1984年のMacintosh, 2001年のiPod …」とそれから初めて発表するiPhoneへの紹介に繋げます。

この2つの製品の登場は今も強い印象を持っています。ただし単なる熱狂ではなくて疑問と期待が入り交じった不思議なものでした。MacintoshはApple IIで成功した要素「カラー、拡張性、TVをモニターにできる、ゲームに向いた機能」の「全て」を持っていませんでした。

iPodが出現したときには128MのメモリのMP3プレーヤーに人気があり、市場に「ハードディスクを首からぶら下げて持ってる曲を全部持ち運びたい」という要求はありませんでした。iPodの日本初お披露目は(自分の記憶によれば)「ラフォーレ原宿」のロビーのところです。ガラスケースに入った発売前のiPodがうやうやしく回転してました。たまに見る人もいましたが、それがコンピューターメーカーの製品、ましてやすぐ数年後に音楽の聞き方を全く変えてしまう革新的な製品であると見てる人は全然いなかったと思います。

MacintoshもiPodも価格が高すぎるとも言われ、どちらも市場に登場した時には少なからず批判もありました。



今は分かります。
真にイノベイティブな製品は同時代の人に登場の時からすぐに熱狂的に支持されるものではないということを。

Keynoteの中でJobsは我々の世界の先駆者としてAllan Kayの言葉を引用します。

ソフトウェアに対して本当に真剣な人は、独自のハードウェアを作るべきだ。

iPhone登場30年前の言葉ですが、今のAppleそのものです。
そのAllan Kayが好んで使った言葉があります。

“Perspective is worth 80 IQ.”

“Knowledge is silver. Outlook is gold. IQ is a lead weight.”

物事を見る視点や見解の大切さを説いた言葉ですが、Steve Jobsは正に世界を人と違った視点で見てた人だと思います。人とは違う考えを持つことを恐れず、世界を変えられるとの信念を持つ大胆さ、そしてそれを実行できる能力を兼ね備えていた、世界はそういう惜しい人を無くしました。自分も今日は大きな喪失感と共に一日を終えました。

最後にJobsが制作に最も拘ったと言われるCM映像1 を紹介してこの記事を終えます。追放されたAppleに復帰したJobsがどん底のAppleの再生を願い制作したそうです。

Steve Jobs本人のナレーションによる「Think Diffrent」です。

クレージーな人達がいる。
反逆者,厄介者と呼ばれる人達。
四角い穴に、丸い杭を打ち込むように
物事をまるで違う目で見る人たち。

彼らは規制を嫌う。彼らは現状を肯定しない。

彼らの言葉に心をうたれる人がいる。
反対する人も、賞賛する人も、けなす人もいる。
しかし、彼らを無視することは、
誰にも出来ない。

なぜなら彼らは物事を変えたからだ。
彼らは人間を前進させた。

彼らはクレージーと言われるが、
私たちは彼らを天才と思う。

自分が世界を変えられること
本気で信じる人達こそが、
本当に世界を変えているのだから。


  1. http://jp.wsj.com/japanrealtime/2011/10/06/%EF%BD%97%EF%BD%93%EF%BD%8A%E6%97%A5%E6%9C%AC%E7%89%88%E7%B7%A8%E9%9B%86%E9%95%B7%E3%81%8C%E8%A6%8B%E3%81%9F%E3%82%B8%E3%83%A7%E3%83%96%E3%82%BA%E6%B0%8F%E3%81%AE%E5%AE%8C%E3%81%BA%E3%81%8D%E4%B8%BB/ []

The new era of PHP web development

カンファレンスの基調講演かよというような大げさなタイトルですが、参加したPHP勉強会@関東で空き時間があって、持っていったMacBook Airに入っていた以前つくった資料の断片がありその場で飛び入りを決め発表させてもらいました。

元々は自分が5.3+専用のフレームワークをつくるときに、何故作るのか、今求められるものとは何か、現在のweb開発、PHP、フレームワークの潮流とはどういうものなのか、等と自分のフレームワーク制作用に調べた時につくった資料の断片で公開の予定のないものでした。

自分なりに客観性を持って考察したのですが、やはりこういう観察や考察は多分に主観的なところとかあると思います。これと別スライドのCQRSパターンとMozilla laboのCANVASを使ったAceエディターが前のbespineから大分進化してて充分実用レベルです、デザイナーや開発者どうしでのコラボレーションに充分使えます。GitHubで使われてますが、開発で使うと使い勝手いいですよいう話、以上3つの話をいたしました。