アプリケーションはオブジェクトグラフ

## HelloWorld

[第1日目](http://qiita.com/koriym/items/3f060df9b5c854a42a9b)で試した`MyvVendor\HelloWorld`アプリは最小構成のアプリケーションです。

![bearsunday_2014_adv_2.png](https://qiita-image-store.s3.amazonaws.com/0/3940/c00f64de-ed81-4b33-9831-d880e0f14959.png)

実行可能なBEAR.Sundayアプリケーションの最小構成です。PHPファイルが４つあります。

 * Index.php　ページリソース
 * AppModule アプリケーションモジュール

 * www/index.php アプリケーションスクリプト
 * App.php アプリケーションクラス

`リソース`はMVCフレームワークでいうと`モデル`に近いものですが、`ページリソース`はwebのページに対応します。`アプリケーションモジュール`がDIとAOPの設定を持ちオブジェクトの構成を決定します。

アプリケーションの実行に必要なサービスオブジェクトは`アプリケーションオブジェクト`が保持しているのでスクリプトはそのサービスを使いアプリケーションを実行します。

## アプリケーションスクリプト

アプリケーションの実行手順が記述してあります。

```php
<?php

use BEAR\Resource\Request;
use BEAR\Sunday\Extension\Application\AbstractApp;
use BEAR\Sunday\Extension\Application\AppInterface;
use MyVendor\HelloWorld\AppModule;
use Ray\Di\Injector;

require dirname(__DIR__) . '/vendor/autoload.php';

$app = (new Injector(new AppModule))->getInstance(AppInterface::class);
/** @var $app AbstractApp */

$request = $app->router->match($GLOBALS);
try {
    // resource request
    $page = $app->resource
        ->{$request->method}
        ->uri($request->path)
        ->withQuery($request->query)
        ->request();
    /** @var $page Request */

    // representation transfer
    $page()->transfer($app->responder);

} catch (\Exception $e) {
    $code = $e->getCode() ?: 500;
    http_response_code($code);
    echo $code;
    error_log($e);
}
```

順に見ていきましょう。５つのステップがあります。

#### 1.オートローダーの登録

```php
require dirname(__DIR__) . '/vendor/autoload.php';
```
`composer`のオートロードを利用します。

#### 2.アプリケーションインスタンスの生成

```php
$app = (new Injector(new AppModule))->getInstance(AppInterface::class);
```

アプリケーションは１つの変数に格納されています。`BEAR.Sunday`アプリケーションは全体を通して`DI`が利用されるので、実クラス名がほとんど登場しません。全ての依存の束縛を知るのが`AppModule`です。インジェクターはそれを利用しアプリケーションクラスからアプリケーションのインスタンスを生成します。

アプリケーションクラス名ですらもここに登場しないのに注目してください。`AppInterface`に束縛されたアプリケーションクラスが使用されます。

基本的なアプリケーションクラスはこのようなものです。

```php
<?php
namespace BEAR\Sunday\Extension\Application;

use BEAR\Resource\ResourceInterface;
use BEAR\Sunday\Extension\Router\RouterInterface;
use BEAR\Sunday\Extension\Transfer\TransferInterface;

class AbstractApp implements AppInterface
{
    /**
     * @var RouterInterface
     */
    public $router;

    /**
     * @var TransferInterface
     */
    public $responder;

    /**
     * @var ResourceInterface
     */
    public $resource;

    /**
     * @param RouterInterface   $router
     * @param TransferInterface $responder
     * @param ResourceInterface $resource
     */
    public function __construct(
        RouterInterface $router,
        TransferInterface $responder,
        ResourceInterface $resource
    ) {
        $this->router = $router;
        $this->responder = $responder;
        $this->resource = $resource;
    }
}
```

アプリケーションの振舞いはスクリプトで記述するので、このクラスでは記述されてなく単にスクリプトで使用するサービスオブジェクトを３つ保持しているだけです。

クラスは単純ですが、実際に生成されるインスタンスは複雑です。

http://bearsunday.github.io/readme/print_o/app.html
http://bearsunday.github.io/readme/print_o/app_array.html （詳細）

BEAR.Sundayは適切なDIを使ったオブジェクト指向のアプリケーションでもあります。

> オブジェクト指向のアプリケーションは相互に関係のある複雑なオブジェクト網を含んでいます。オブジェクトはあるオブジェクトから所有されているか、他のオブジェクト（またはそのリファレンス）を含んでいるか、そのどちらかでお互いに接続されています。このオブジェクト網をオブジェクトグラフと呼びます。

上記のリンクのオブジェクトグラフの中から検索して`MyVendor\HelloWorld\App`を探してみてください。３つのオブジェクトに依存しているルートオブジェクトが見つかるでしょう。それが`AppInterface`に束縛されていたアプリケーションクラスのインスタンスです。

明日はその３つのサービスオブジェクトを使ってアプリケーションを実行するところに続きます。