ミッション

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

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

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

何故DIを使わないか?

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

問題:面倒、難しい

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

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

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

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

易しい依存の利用

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

// トレイトで
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. 問題は表面化してません。 []