BEAR Blog

Because everything is a resource.

Be the First One

| Comments

“have the courage to follow and show others how to follow.”

ソーシャルコーディングもそうではないかと考えました。

BEAR.Sunday Quick Tour

| Comments

簡単にBEAR.Sundayを体験できるチュートリアルを用意しました。それぞれのセクションの目安の時間も記してみました。良かったら手を動かしてお付き合いください。

準備

PHP 5.4がインストールされていればOKです。

1
2
3
$ php -v
PHP 5.4.11 (cli) (built: Jan 27 2013 22:00:35)
Copyright (c) 1997-2013 The PHP Group

もしPHP5.4がインストールされてなくてもOSXならこれだけでインストールできます。1

1
curl -s http://php-osx.liip.ch/install.sh | bash -s 5.4

BEAR.Sundayのインストール

5-? min

コンソールでインストールします。

1
curl -s http://install.bear-project.net/ | sh -s ./bear

または(curlが無い場合など)

1
2
$ php -r "eval('?>'.file_get_contents('https://getcomposer.org/installer'));"
$ php composer.phar create-project -s dev --dev bear/package ./bear

アプリケーションの作成

1 min

Helloアプリケーションを作成します。

1
2
$ cd bear
$ php bin/new_app.php Hello

コンソールでのアプリケーション実行

3 min

web.phpを使いconsoleでHTMLの出力が確認できます。GETメソッドで/(ルート)をアクセスするには以下のようにタイプします。

1
2
$ cd apps/Hello/public
$ php web.php get /

三番目の引き数でアプリケーションの実行コンテキスト(モード)を切り替える事ができます。

プロダクション

1
php web.php get / prod

1
2
3
4
5
6
7
8
9
10
11
12
13
200 OK
cache-control: ["no-cache"]
date: ["Mon, 04 Mar 2013 12:29:49 GMT"]
[BODY]
< !DOCTYPE html>
<html lang="ja">

<body>
<div class="container">
<h1>Hello BEAR.Sunday</h1>
</div>
</body>
</html>

API

1
php web.php get / api
1
2
3
4
5
6
7
8
9
10
11
12
13
200 OK
content-type: ["application\/hal+json; charset=UTF-8"]
cache-control: ["no-cache"]
date: ["Mon, 04 Mar 2013 12:31:17 GMT"]
[BODY]
{
    "greeting": "Hello BEAR.Sunday",
    "_links": {
        "self": {
            "href": "page://self/index"
        }
    }
}

利用できないメソッドには405(Method Not Allowed)が返って来ます。

1
php web.php delete /

1
2
3
4
5
6
7
8
9
10
11
12
405 Method Not Allowed
x-exception-class: ["BEAR\\Resource\\Exception\\MethodNotAllowed"]
x-exception-message: ["Hello\\Resource\\Page\\Index::onDelete()"]
x-exception-code-file-line: ["(405) \/Users\/akihito\/work\/bear\/vendor\/bear\/resource\/src\/BEAR\/Resource\/DevInvoker.php:59"]
x-exception-previous: ["-"]
x-exception-id: ["e500-b14ad"]
x-exception-id-file: ["\/Users\/akihito\/work\/bear\/apps\/Hello\/data\/log\/e500-b14ad.log"]
cache-control: ["no-cache"]
date: ["Mon, 04 Mar 2013 12:47:11 GMT"]
[BODY]
The requested method is not allowed for this URI.
KumaAir:public akihito$

404も試してみましょう。

Webでのアプリケーション実行 (5 min)

同じweb.phpを使ってBuilt-in Web serverを立ち上げます。ポート番号は自由です。

1
php -S localhost:8088 web.php

挨拶が表示されました。devモードではツールバーと共に表示されます。
スクリーンショット 2013-03-04 21.53.49

この挨拶にはpage://self/indexという名前(URI)がついています。このURIのついた情報は「リソース」と呼ばれます。

灰色のバックグランドで表示されてるのはこのリソースはキャッシュを利用しないことを表します2 URIの隣にツールバーが並び、情報の確認やコードの編集ができるようになっています。破線はそのリソースの表示範囲を表します。

オンライン編集

リソースのコードとビューテンプレートはwebブラウザ上で編集することができます。
スクリーンショット 2013-03-04 22.13.22

保存にはショートカットキーも使えます。(⌘W / Ctl+W)

シンタックスエラー

2 min

ClassのCを誤って消してしまいました。シンタックスエラーになりますがエラーある状態でアプリケーションを実行するとエラーメッセージの表示されたエディターが表示されます。

スクリーンショット 2013-03-04 22.27.37

その場で修正して、「保存」「再読み込み」ですぐに復帰します。ケアレスミスによる思考の中断を最小限にします。

クエリーを読む

5 min

HTTPのGETメソッドではonGetメソッドがアクセスされます。

1
public function onGet($name = 'BEAR.Sunday')

このメソッドは

$_GET

と同様に機能します。$_GET[‘name’]を$nameとして受け取っています。

?name=YourName

としてアクセスしてみたり、以下のようにyearクエリーも受け取ってみましょう

1
2
3
4
5
    public function onGet($name = 'BEAR.Sunday', $year=2013)
    {
        $this['greeting'] = 'Hello ' . $name . ", It's {$year}";
        return $this;
    }

スクリーンショット 2013-03-04 22.43.18

メソッドは$_GETクエリーと同じく名前で指定されるので(名前付き引き数=named parameter)通常のPHPの引き数のように引き数の順番では変数名で指定されます。(順番は関係ありません)$_GETのクエリーは取得するのではなく、PHPのメソッドと融合して与えられている事にも注目してください。

テンプレート

1 min

リソースクラスファイルの拡張子をtplあるいはtwigに変えたものがそのリソースの表現に用いられるビューテンプレートになります。

スクリーンショット 2013-03-04 22.55.42

/dev/ツール

3 min

URLに/dev/と入力するとデバックツールが表示されます

スクリーンショット 2013-03-04 22.58.27

リソース一覧

/dev/resource/ ではリソースを一覧したり新規のリソースをつくることができます。

スクリーンショット 2013-03-04 22.59.31

つくったばかりのHelloアプリケーションはpage://self/indexというページリソースが1つ。利用可能なメソッドはGETだけという事が分かります。リソース(モデル)は、アプリケーションの核心です。アプリケーション管理者はそのアプリケーションにいくつ、どんなリソースがあるかをこのリソース画面で知る事ができます。

What’s next ?

1 week

Web+DB Press記事のリソースを作ってみるのはどうでしょうか。“はじめて”シリーズはソフトウエアやインターネット技術の概念を同時に学ぶ事ができます。ブログチュートリアルは既存のFWとの実装の比較になります。apps/SandboxアプリケーションはDB/ページングなど実用的なサンプルも含みます。特にRESTに興味のある方は定番となってるREST BucksをBEAR.Sundayで実装したHATEOAS実装もあります。

  1. 詳しくは php-osx.liip.ch を []
  2. 緑/赤=Read/Write []

WEB+DB PRESS Vol.73

| Comments

BEAR.SundayでRESTfulなシステム開発

WEB+DB PRESSの大人気連載「巨人の肩からPHP 先人たちに学ぶモダンプログラミング」の連載5回目にBEAR.Sundayをとりあげて頂きました。

734505566 RESTやRESTとBEAR.Sundayの関わりに触れてから、実際のリソースやリソース実装がどのようなコードになるかを紹介してもらっています。限られたページの中でよくまとまっていると思います。執筆編集の方々、ありがとうございます。

サンプルを雑誌に掲載されているようにSandboxアプリケーションでお試ししてもらっても全然問題ないのですが、雑誌掲載後にアプリケーションのスケルトンコードをcomposer create-projectで作成する機能がつきました。apps/ディレクトリで以下のようにアプリケーションディレクトリ名を指定してインストールします。

php composer.phar create-project -s dev --dev bear/skeleton ./MyApp

MyAppはアプリケーション名です。インストール直後にcomposerのpost-install-scriptが実行され「フォルダ名として指定したアプリケーション名」がコード中のnamespaceなどにも適用されます。アプリケーション固有のコマンド群を持つ代わりに汎用のcomposer create-projectを使用しています。

スクリーンキャストも用意しました。ご覧ください。

BEAR.Sundayの総合パッケージであるBEAR.PackageのインストールしてからMyAppというアプリケーションを作成してます。作成した後にコンソールでHTMLの確認、built in web serverでそのwebサイトを確認しています。

PHP ソフトウェアメトリック

| Comments

ソフトウェアメトリック

ソフトウェア測定法(ソフトウェアそくていほう)またはソフトウェアメトリック(英: Software metric )とは、ソフトウェアやその仕様の属性の尺度である。
定量的手法の威力は他の分野で証明されていたことから、計算機科学の分野でも同様の手法をソフトウェア開発に持ち込もうとする努力が続けられてきた。Tom DeMarco は「測定できないものは制御できない」と記している。

Wikipedia ソフトウエア測定法

ソフトウェア工学の祖の一人であるトム・デマルコは名著『品質と生産性を重視したソフトウェア開発プロジェクト技法』をこの有名な一文「測定できないものは制御できない」で始めました。1987年のことです。

phpdepend

ソフトウエア品質を客観的・機械的に計ろうとするPHPのメトリクスツールにphpdependがあります。
http://pdepend.org/

本体の紹介の中でこのように述べてます。

PHP_Depend can be used in an automated build environment and the generated reports are always objective, it just measures the quality facts of a given source base.

PHP_Depend scales with growing source bases, where human code reviews will fail at some day.

PHP_Depend allows you to indentify suspect parts in a software system that should be part of a code review, without looking into the source.

PHP_Depend also supports some fancy metrics that will become very useful, when you have reached certain level of metrics knowledge.

このツールを使いソースコードを解析すると2つの画像(svg)ファイルが得られます。Abstraction Instability ChartOverview Pyramidの2つです。

Abstraction Instability Chart

report-a-i-chart Abstraction Instability Chartは横軸にA – abstraction(抽象化)、縦軸に I – Instabilityのグラフです。このAを理解するためにまず二つの数字を理解する必要があります。CaとCeです。

Ca – Afferent Couplings:
このパッケージに依存した他のパッケージがいくつあるかという数字です。高い数値は仕様変更が他に影響を与えるパッケージが多いということを表します。

Ce – Efferent Couplings:
このパッケージが依存するパッケージはいくつあるかという数字です。高い数値は他のパッケージの影響を受けやすいということを表します。

CaCeIllustration この2つの数字を使って次のIが求められます。

I -Instability – パッケージの不安定性を表します。Iは0~1をとり値が大きいほど不安定なパッケージとされ、この数値は(Ce / (Ce + Ca)) として求められます。

横軸のAは抽象度を表します。

A – Abstractness = 抽象象クラス数(AC) / 具象クラス(CC) + 抽象クラス数(AC)

Main Sequence

グラフに(0,1)と(1,0)を結ぶ直線をひきます。これがMain Sequenceと言われるラインでAとIのバランスの理想的な関係を表します。この線からの距離が大きいと「抽象度が高いがあまり利用されていない」「抽象度が低いが他からの依存が強い」など「抽象度と依存度の関係」が不適切という事を表します。

そのパッケージのサイズが丸の大きさで表されるので、重要なパッケージに注目することができます。

各フレームワークのA/Iチャート

実際に取ってみました。ソースはhttps://github.com/koriym/php-framework-metricです。※画像はSVGファイルなので単独で表示させ拡大するとパッケージ名の文字も読めます。

symfony

symfony-jdepend

zf2

zf2-jdepend

cakephp

cakephp-jdepend

CodeIgniter

CodeIgniter-jdepend

fuel

fuel-jdepend

laravel

laravel-jdepend

Slim

Slim-jdepend

yii

yii-jdepend

Silex

Silex-jdepend

BEAR.Sunday

bear-jdepend

Overview Pyramid

bear-pyramid
この”ピラミッッド図”の見方ですが、まず3つの部分に分かれてる事を理解します。

logger.overview-pyramid-0.serendipityThumb 次にNOPやCALLなどまるでアセンブラのニーモニックのような謎の略語を理解します。

Size and Complexity(サイズと複雑度)

NOP パッケージの数
NOC クラスの数
NOM メソッドの数
LOC コードの行数

Coupling(結合度)

CYCLO 循環的複雑度
CALL メソッドあたりの呼び出し数
FOUT ファン・アウト (ある特定のメソッドが呼び出す他のメソッドの数)

Inheritance(継承)

ANDC 直接の子孫の平均数
AHH 継承ツリーの平均の深さ

それらの値がピラミッドの中央に表示され、上段/下段の割合の数字が端に表示されます。

logger.overview-pyramid-3 数字には色が付けられ基準となる値の範囲に入ってない事を知らせてくれます。
これも同様に各フレームワークのチャートを用意しました。

Symfony

symfony-pyramid

zf2

zf2-pyramid

cakephp

cakephp-pyramid

CodeIgniter

CodeIgniter-pyramid

fuel

fuel-pyramid

Silex

Silex-pyramid

laravel

laravel-pyramid

Yii

yii-pyramid

Slim

Slim-pyramid

BEAR.Sunday

bear-pyramid

ソフトウエア品質はツールによって測定できるか

これには様々な議論があることも紹介します。この議論もとても興味深いものです。

今回各フレームワークのチャート図を作ってみました。それぞれのフレームワークの傾向が出て面白いとも思うのですが1、特に自分や自分のチームの開発しているソフトウエアに適用してその傾向や特徴を探る事も大事かと思います。ミニマムブートストラップを探るHelloWorldベンチマークと同様です。

参考URL

  1. 特にsymfony/zf2/cakephpのLOCが圧巻です []

BEAR.Sunday 0.6.0

| Comments

BEAR.Sunday 0.6.0をリリースしました。

インストールが簡単に

$ curl -s https://getcomposer.org/installer | php $ php composer.phar create-project -s dev --dev bear/package bear

従来git cloneした後にcomposer installしてたインストールをcomposer.phar create-projectに対応してインストールをより簡単にしました。これで”./bear”フォルダにBEAR.Packageがインストールされます。-s dev –devと似たようなオプションが並びますが前の”dev”はstability、後者の”dev”はcomposer.jsonで指定する”require-dev”パッケージ依存をインストールするという意味です。composer scriptにも対応し、インストール後にディレクトリの書き込み権限も設定します。

フレームワークの拡張を明確に

DIP(依存関係逆転)原則に忠実なBEAR.Sundayではフレームワーク機能の拡張性や変更に関して最大限の自由がありますが、それらを機能単位で明確にするためにExtentionインターフェイス/フォルダという仕組みを導入しました。

BEAR.SundayのExtensionフォルダ下にはフレームワークが提供する機能のインターフェイスが格納されています。

スクリーンショット 2013-01-26 22.14.05

このインターフェイスを実装したものがBEAR.PackageのProvideフォルダです。

スクリーンショット 2013-01-26 22.15.58

対応するProvideフォルダのクラスではExtensionで指定されたインターフェイスの実装をします。この実装を利用するためには用意されているモジュールをインストールします。

例えば現在TemplateEngineに用意されているのはデフォルトでSmartyですがAppModule.phpでTwigModuleをインストールしてTwigを利用する事ができます。1

スクリーンショット 2013-01-26 22.21.05

PSR compliance

これまでもPSR0/1/2の対応は行って来ましたが、PSR3のログインターフェイスに合わせてインターフェイスsuffixの議論があってそれに習いこれまでの「単数のメソッドのインターフェイスは–able系で複数のメソッドのものは”Interface” suffixにする」をすべて”Interface” suffixに変更しました。

これは初期のzf2のコード規約に習ったものだったのですが、zf2自身も方針を変更しています。またTraitも原則”Trait” suffixにし、パッケージのベースの例外インターフェイスも

1
interface Exception

から

1
interface ExceptionInterface
に変更しました。これもzf2と同じです。

例外は”Inject”suffixのついたインジェクト用のセッターメソッドTraitで、これは従来通り”Inject”suffixを使用します。

1.0に向けて

今回の変更は大掛かりなBCブレイクを伴う最期の変更にしたいと思っています。調整を経て1.0に繋げれる予定です。

Meetup #1

2/16にBEAR.Sundayのmeetup #1を予定しています。これは現在マニュアルの英訳をしてもらってるリチャードさん@mackstarの来日に合わせて行うものです。

BEAR.Sunday meetup #1
http://www.zusaar.com/event/505010

今回も技術的にエキサイティングで楽しいものになればと思っています。
BEAR.Sunday meetup#1でお会いしましょう!

  1. このTwigモジュール実装はまだ実験的なものです。 []

Advent Day 12: Debug Print

| Comments

デバック表示 p($var);

BEAR.Sundayは前バージョンからの伝統(?)のデバック出力p();があります。
表示はxdebugのvar_dump()と同じですが加えて、変数名とp()した場所が表示されます。

1
p($a);

webでp()すると
スクリーンショット 2012-12-17 23.31.50

コンソールでp()すると

スクリーンショット 2012-12-17 23.34.23

引き数なしでp()すると(void)と表示されます。

スクリーンショット 2012-12-18 0.26.19
その場所を通ったかどうかの確認になります。

表示されたファイル名はクリックしてweb上で編集できデバック表示したp()を消したり表示内容を変更したりできます。
スクリーンショット 2012-12-18 0.37.16

デバック表示

「変数内容を画面上で確認」IDE+Debuggerでもっと洗練された内容確認の仕方やTDDを実践したあとでも、この原始的なやり方を手放す事ができません。

一方、デバック情報を画面に表示するときの問題「どれがどの表示を表してるのか分からなくなった」「どこでかいたのか分からない」「エディタに戻ってまた消すのが面倒」…それらの解決とコーディング作業の中断を0.1秒単位で削りたいという考えからこのp()を作りました。

前回バージョンのSaturdayで好まれた機能です。Sundayでは表示変更とコンソール表示のサポートを追加しました。その他は以前のものと編集できたところも含めて同じです。

Advent Day 11: DI: Why Not ?

| Comments

ミッション

BEAR.Sundayは非常に現実的なミッションがあって、スキルが多様なチームで最大限のパフォーマンス(制作、運用)を出す事が求められます。難しい要求なのですが、これはゴールであって前提でもあります。

もっと平たく言うと、スキルの高い人だけが使える”難しい”ものにできません。
またどんな奇麗な設計でも実運用でパフォーマンスが出ないと導入できません。

このミッションとDIがどのように関係してるのかを考察します。

何故DIを使わないか?

DIの利点や理解を促進する記事は多いですが、ここではまず何故DIを使わないかを考察してみます。その理由を解決すれば良いと単純に考えてみます。

問題:面倒、難しい

「面倒」と「難しい」は全く違う問題なのですが、これを一緒に解決します。つまり前回までの記事で「生成」と「利用」に分離されたDIのパターンでは面倒&難しいという問題はほぼ全て「生成」、つまりコンパイルに集中しています。コードや実行時間だけでなく、まず作成者を区別することを考えてみます。

アプリケーション・アーキテクト

ライブラリを選択し、抽象と束縛し、必要なアダプターを記述します。これらはよりスキルのいる仕事でもありますがより再利用性の高い仕事でもあります。ここをアプリケーションアーキテクトが担当します。あるいはアプリケーションを横断するパッケージ、そのまたさらにBEAR.Sundayフレームワーク開発者1が担当します。アプリケーションを記述するアプリケーションエンジニアは基本は用意されたパッケージを利用する事に集中し、コンパイルタイムで行われる仕事は原則しません。

つまり現在のBEAR.PackageであればSQLを記述し、テンプレートを用意し、用意されたサービスオブジェクトとアノテーションに束縛された@Cacheアドバイスなどを利用しアプリケーションを記述します。特定ドメインにフォーカスしてビジネスロジックとその表現に関わることにコーディングを集中させます。

易しい依存の利用

一旦アプリケーション・アーキテクトがまとめ上げた制約は再利用が可能です。BEAR.SundayのDIはオブジェクトを利用するのに最低限の記述しか必要としません。

1
2
3
4
5
6
7
8
9
10
11
// トレイトで
use LogInject;
use TmpDirInject;
// メソッドで
/**
 * @Inject
 */
public function setLog(LogInterface $log)
{
    $this->log = $log;
}

特定の抽象に束縛済みの依存があるなら再利用可能です。同じ依存がある新しいクラスを書くときにコンパイルに関わる記述の必要はありません。use文か、インターフェイスに@Injectアノテーションを打つと依存を受け取ることができます。

依存を利用するだけなら、特定のDependency Injector機構やその設定ファイルのフォーマットを理解する必要はありません。利用コードだけで依存を受け取れます。

仕事の80%はメンテナンス

三ヶ月で開発されたサービスが数年単位でメンテナンスされます。担当は代わり、プログラマーは内部外部問わず交代します。そしてメンテナンスの仕事の多くは生成ではなく、利用コードの変更です。

全ての仕事を一人で担当する場合でも、再利用性の高いコンパイルに関連するコードと利用コードが分かれている事はメリットになります。ずっと手を入れてない(忘れてる)コードを触る時でもまずは利用コードの理解だけに集中できます。

問題:パフォーマンス

オブジェクトグラフの再利用する設計でパフォーマンス上の問題はあまりありません。逆により高いパフォーマンスが望める場合が多いと思います。

どうでしょうか?

話をフェアにするためにBEAR.SundayのDIがうまく解決できない問題も述べます。アノテーションベースのDIシステムに共通の問題なのですが、「ロボットの足問題」と呼ばれる問題があります。これは同じような依存の少しだけ違う依存をどうやって束縛するかという問題で解決できるのはできるのですが、記述は冗長です。もっとうまい解決があるべきだと考えます。2

「難しい、面倒、遅い」これらのそれなりの解答になってるでしょうか。また他にどういう問題があるでしょうか?あれば解決法を考えましょう。dependentがクリーンなDIは、インジェクトの仕組みをより良いものに丸ごとアップデートできる可能性があります。

アノテーションベースのRay.Diの現在のBEAR.Sundayクラスも設定ファイルベースのAura.Diに変更することは原理的に可能です。depedentに注入機構の依存がないためです。

  1. つまり自分なのですが []
  2. 問題は表面化してません。 []

Advent Day 10: DI > SL ?

| Comments

依存するから?

また違った面からDIを考察してみます。SLとの比較です。
SLをアンチパターンとするときに良く言われるのが、「コンテナに依存するから」と説明されますがこれを考えてみます。

依存した事自体が問題なのでしょうか?(0 dependencyでなくなった)
それとも依存しているコンテナの性質に依存している問題なのでしょうか?

new, SL and DI

1
2
3
4
5
6
7
class Conventional
{
    public function __construct()
    {
        $this->foo = new Foo;
    }
}
1
2
3
4
5
6
7
class Di
{
    public function __construct(FooInterfeace $foo)
    {
        $this->foo = $foo;
    }
}
1
2
3
4
5
6
7
class Sl
{
    public function __construct(Container $container)
    {
        $this->foo = $container->get('foo');
    }
}

オブジェクトを取得する3つのコードです。

Conventionalクラスではnewで生成して取得しています。依存はハードコードされていて$fooはFooのインスタンスです。

Diではインターフェイスを通じて依存を受け取っています。DIP原則に従って抽象に依存しています。$fooはFooInterfaceを実装した何かのクラスです。

Slでは”foo”というサービスオブジェクトを取得しています。ロケーターはこのクラスに記述してあった依存を隠してしまいました。このfooサービスはどういうもので何でしょうか?どうすれば分かるでしょうか?これを知るAPIはありません。コンテナ機構を理解して、コンテナにセットしているコードを見て、あるいは設定ファイルから?ドキュメントから?

これをうまく説明するには前の2つの方法に比べて、何かの規約や機構が必要です。人が容易に理解できるようになってもコードはこれを検出しません。IDE等でコード補完を受けるためには注釈が必要でしょう。

またこのクラスはコンテナに依存するようになったことで、独立したパッケージとしてリリースするには何らかの依存解決ツール(composer)を前提にする必要があります。

more info

このエントリーはこのビデオを参考に起こしています。

Decoupled Library Packages for PHP 5.4 – Paul Jones

また大抵のデザインパターン・パラダイムは、XX is evil, XX is anti paternで検索すると色々でてきます1

Service Locator is an Anti-Pattern

CodeAsDocumentation

この記事はSLが駄目という記事ではなくて、SLは「コンテナに依存するから駄目なのだ」という意見のどの部分が駄目なのかを考察することで、依存性を自己記述的なCodeAsDocumentationとして表すDIの性質を明らかにしようとしました。

  1. ^^; []

Advent Day 9: Compile and Runtime

| Comments

決定論

もしもある瞬間における全ての物質の力学的状態と力を知ることができ、かつもしもそれらのデータを解析できるだけの能力の知性が存在するとすれば、この知性にとっては、不確実なことは何もなくなり、その目には未来も(過去同様に)全て見えているであろう。

— 『確率の解析的理論』1812年

「ラプラスの悪魔」です。

ラプラスの悪魔のような、こんなデバックツールできないでしょうか?

もしもある瞬間における全てのオブジェクトの状態と機能を知ることができ、かつもしもそれらのデータを解析できるだけの優れたアナライザーがあるとすれば、このアナライザーにとっては、不確実なことは何もなくなり、その目には全ての潜在的なバグが全て見えるであろう。

…夢でしょうか^^; しかしデバックに苦しむのは「状態の不確実性」からという事は多くないでしょうか?例外でいえばLogicExceptionの原因追及は、RunteimExceptionの例外の原因追及よりずっと簡単です。オブジェクトが”モード”やHTTPが状態(セッション)をもつと問題解決はずっと複雑になります。状態=不確実性=evil !

この記事ではオブジェクトの不確実性を低減する技術としてのDIを見て見ます。

再び生成と利用分離原則

DIでは生成と利用を分離しますが、分離するのはコードだけではありません。その時間(タイミング)も分離されます。「生成」が終わってから「利用」になるためです。BEAR.Sundayではオブジェクトの生成時に依存の注入だけでなく、アスペクトの織り込みも行われます。これがオブジェクトをつくるコンパイル。その時間がコンパイルタイムです。

生成・使用分離の原則 DI 関心の分離で[具象コード]と[抽象コード]の分離を示したようにするとこういう風になります。

生成と使用のタイミングが分離されていないパターン

< -– boot終了 -–>
< -– runtime開始 -–>
[生成]
[使用]
[生成]
[使用]
[使用]
[生成]
[使用]

生成と使用のタイミングが分離されているパターン(DI)
[生成]
[生成]
[生成]
< -– boot終了 -–>
< -– runtime開始 -–>
[使用]
[使用]
[使用]
[使用]

オブジェクトグラフの決定

DI以外のパターン、例えばfactory()メソッドとの比較は分かりやすいでしょう。コードの途中で現れたnew演算子やfactory()メソッドは“on demand”でオブジェクトの取得を行います。

対してService Locaterを使ったパターンではどうでしょうか。オブジェクトやあるいはオブジェクトの生成方法はboot時に各コンテナに格納されるので生成と使用のタイミングの分離はDIと同じです。

しかしオブジェクト間の関係性=オブジェクトグラフの決定のタイミングが違います。SLではオブジェクトをコンテナから取り出しプロパティに格納あるいは直接利用します。その時点でdependentとdependencyの関係性が決定されます。つまりメソッド内の実装でその関係性が決定されます

対してDIではメソッドシグネチャーとその束縛の集合がオブジェクトグラフを決定します。リクエストを受けたboot時にどのオブジェクトグラフが生成されるかが最大限、決定されています。

その応用

BEAR.Sundayではその特性を利用してオブジェクト生成の再利用を行っています。莫大なオブジェクトグラフコンストラクションコストは再利用され運用ではほぼ0になります。10万を超えるファンクションコールは1/100の1000程度になります。これは抽象化レイヤーが最少のFWとほぼ同等です。

この設計パターンはパフォーマンスの寄与と、より少ないコード実行を可能にしています。

Advent Day 8: Packagist

| Comments

Packagist登録

BEAR.PackageをPackagistに登録しました。
composerのcreate-projectでインストールできるようになりました。

composerインストール

1
$ wget http://getcomposer.org/composer.phar

または

1
$ curl -s https://getcomposer.org/installer | php

composerでBEAR.Sunday sandboxアプリケーションインストールします。

1
$ php composer.phar create-project -s dev bear/package /tmp/mysunday

BEAR.Packageとその依存のBEAR.Sundayが指定したバージョンでインストールされます。1 その後PHP5.4のbuilt-in web serverを立ち上げます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
$ composer.phar create-project -s dev bear/package /tmp/mysunday
Installing bear/package (dev-master bbc42caf8ed71e56c4f72f7270db012dc4b40d39)
  - Installing bear/package (dev-master master)
    Cloning master
Created project in /tmp/mysunday
Loading composer repositories with package information
Installing dependencies from lock file
  - Installing aura/installer-default (1.0.0)
  - Installing aura/web (1.0.0)
  - Installing aura/signal (1.0.0)
  - Installing aura/router (1.0.0)
  - Installing aura/di (1.0.1)
  - Installing doctrine/common (2.3.x-dev bb0aebb)
    Cloning bb0aebbf234db52df476a2b473d434745b34221c
  - Installing ray/aop (dev-master 3edfe6b)
    Cloning 3edfe6ba6b52e8d3190da62c14479ff7cce2377f
  - Installing ray/di (dev-master 1.0.0-beta3)
    Cloning 1.0.0-beta3
  - Installing zendframework/zend-stdlib (2.0.5)
  - Installing zendframework/zend-log (2.0.5)
  - Installing nocarrier/hal (dev-master cc46654)
    Cloning cc466546c6ca5df3e806cd91258cdf194518a12f
  - Installing twitter/bootstrap (master master)
    Cloning master
  - Installing firephp/firephp-core (dev-master c26d972)
    Cloning c26d972dcb28fd483fa193512091df7b3c85e450
  - Installing symfony/http-foundation (2.0.x-dev 4de1a1f)
    Cloning 4de1a1f9a81a58bd6f24607894f76fd7017d45e7
  - Installing symfony/console (2.0.x-dev v2.0.19)
    Cloning v2.0.19
  - Installing smarty/smarty (v3.1.12)
    Checking out /tags/v3.1.12/@4664
  - Installing pagerfanta/pagerfanta (dev-master 12f71d9)
    Cloning 12f71d99457b018fb80746f84514dd5b495c5789
  - Installing symfony/event-dispatcher (dev-master eb290a4)
    Cloning eb290a447c0af5bea0d3de5d95d498afd8c82f89
  - Installing guzzle/guzzle (v2.7.2)
  - Installing facebook/xhprof (0.9.2)
  - Installing doctrine/dbal (2.3.x-dev f63af19)
    Cloning f63af1948a609a96b8ea1c1302c7cdf2f9f51468
  - Installing printo/printo (dev-master abd0d6b)
    Cloning abd0d6b68d00dc98a71124215780b57ec3ede268
  - Installing vdump/vdump (0.1.0)
  - Installing bear/resource (dev-master 3ca644b)
    Cloning 3ca644bc29de4257ec9165ce1c9745150dc231dd
  - Installing bear/sunday (dev-master a9b6fdd)
    Cloning a9b6fdd7cd34b9e7d2075a7c95e066547bcf59ac
zendframework/zend-stdlib suggests installing pecl-weakref (Implementation of weak references for Stdlib\CallbackHandler)
zendframework/zend-log suggests installing zendframework/zend-db (Zend\Db component)
zendframework/zend-log suggests installing zendframework/zend-escaper (Zend\Escaper component, for use in the XML formatter)
zendframework/zend-log suggests installing zendframework/zend-mail (Zend\Mail component)
zendframework/zend-log suggests installing zendframework/zend-validator (Zend\Validator component)
pagerfanta/pagerfanta suggests installing doctrine/orm (2.*)
pagerfanta/pagerfanta suggests installing doctrine/mongodb-odm (2.*)
pagerfanta/pagerfanta suggests installing solarium/solarium (2.*)
symfony/event-dispatcher suggests installing symfony/dependency-injection (2.2.*)
symfony/event-dispatcher suggests installing symfony/http-kernel (2.2.*)
Generating autoload files
Do you want to remove the existing VCS (.git, .svn..) history? [Y,n]? Y
$ chmod -R 777 /tmp/mysunday/apps/Sandbox/data/
$ chmod -R 777 /tmp/mysunday/apps/Helloworld/data/
$ cd /tmp/mysunday/apps/Sandbox/public/
$ php -S localhost:8088 web.php
PHP 5.4.9 Development Server started at Wed Dec 12 13:11:37 2012
Listening on http://localhost:8088
Document root is /private/tmp/mysunday/apps/Sandbox/public
Press Ctrl-C to quit.
  1. インストールスクリプトはまだ用意できていないのでパーミッションの設定が現在必要です []