BEAR Blog

Because everything is a resource

PHPNW 2013(2) - Presentation

| Comments

PHPNW 2013(1) からの続きです

“何のためにイギリスまで行って話をするのか”-この問いに対して高い目標を持っていました。

「世界レベルのプロのエンジニア/アーキテクトの人達をインスパイアさせたい」

単に自分のソフトウェアの紹介や、便利な使い方を紹介するだけで終わるつもりはありませんでした。 持ち時間は50分。終わりにQ&Aを考えると40分前後が実質のプレゼンテーションの時間です。自己紹介、DIは自分で、AOPをリチャードさん、そしてRESTを通訳、最後にまとめを自分がするというハイブリッドなプレゼンテーションにしました。

無名のフレームワークの話をどれだけの人が聞きに来るか、想像も付きませんでしたが立ち見は出ないまでもほぼ満席です。知った顔も見えます。(leedsphpでのセッションの人達がまた聞きに来てくれてました。) 多くのボランティアスタッフがphpnwカンファレンスの運営を支えてますが、撮影スタッフはプロです。会場の一番奥にいる2人組の撮影クルーのとなりの壁掛けデジタル時計が15:00:00を指したらプレゼンテーションスタートです。

撮影されたビデオはいまだに公開されていないので、発表ノートと共に全てのスライド77枚を紹介します。

Introduction

(after self introduction)

I was really surprised when BEAR.Sunday was chosen for this great conference session.

I am very happy be here as a speaker.

But, some of you guys may wonder (or may have doubts) about an unknown person talking about an unknown framework. 
But I’m not here to teach you how to use my framework. No. 
I’m here to share a new way of thinking, a new way of solving web problems.

How do we look at these problems. Yes, It’s about outlook.

Ok let’s start.


BEAR.Sunday offers no libraries of its own.

PHP namespaces, PSR, a new coding github culture, unit testing, a new trend of library oriented frameworks… these have all happened recently and push us to a more library oriented way of thinking.

So BEAR.Sunday chooses not to have it’s own components, It uses others from aura, symfony and zend etc.


No libraries, instead, BEAR.Sunday offers three object frameworks.


What is the framework, by the way ?


My friend told me like that.


Dependency Injection framework, Aspect Oriented Framework, and Hypermedia framework for object as a service. … these technology are centered but also widely used in BEAR.Sunday framework.

Let’s take a look one by one.

So which one attracts you ? let’s start DI.

DI Framework

DI … in many case, People said DI is good tool for testing. Well, it is true…but Is it really core value for DI pattern ?
 We will see some another benefit, mainly these two.



DIP, Dependency Inversion Principle.

“How many of you know this principle ?”

(around 70%)


Robert C. Martin says the following.

So I decided that we should take this seriously.


Let’s take look at the code.

BEAR.Sunday uses Ray.Di which is a subset of Google Guice for PHP.

It uses a binding DSL in PHP.


This class needs renderer as a dependency, We annotate it with an injection point.
 You can also annotate setter methods with @Inject.


You then bind the interface to an instance provider. Concrete class, factory or an instance.

This is binding an abstraction to a concretion.


Now the module knows about all of the bindings.

With this module, You can create an injector.


Then, We can pull an instance with bound dependencies using an interface. We do this with the injector that knows all bindings in the application.


You can change an object graph depending on context.

Its not uncommon to see the code like the above. The state is passed in the application logic. 
Then the behavior of the application is changed by the state. Even though we use objects, this is more like procedural programing.

Also concrete class names have been used. to have instantiate objects that are needed.

For better flexibility and simplicity. The code can be changed like below.
This code does not need to changed even if we use another renderer.

We should code a structure, not as a procedure.


In BEAR.Sunday there is a clear distinction between compilation and runtime.

Concrete class names should only appear at compile time.


Then at runtime it looks like this.

Never use concrete class names. Instead use an “Abstraction” or “Plug Consent” that I mentioned earlier. Which is an interface or an abstract class.

When type hinting a concrete class name should never be used.

This is not just for the sake of assertion or error checking, it is here to describe the applications design.


Best practice says you should have only one root object in your bootstrap.

This seems very different what we see in other PHP DI containers ?


It might sound crazy, but we follow this practice.


The role of application object in BEAR.Sunday is very simple. It holds the services that we use in the application script. That’s all.

This application class has no functionality or behavior. Also you will notice that the application holds no mode or any context. There is no global state like for example a globally defined DEBUG or ENVIRONMENT constant.

The context is used how to bind dependencies, not a how to behave in runtime as we saw. That kind of state information has permanently disappeared after injection.
We don’t need it.

The dependencies have already been injected.


Let’s take a look at a BEAR.Sunday application object graph.

You can access it via the development tools.


The AppModule knows all of bindings and their abstractions. The injection is then made to get the root object using these binding rules. The injector now can grab the application object.

Lets see how dependencies are resolved.


A Router, web response, resource client and dependency injector.

These are all the dependencies that are needed by the application object.

In the application script, we can configure the application with these services.


The Application script is a simple script which shows its own structure.

Don’t be surprised for goto statement or global variable. This is pre-”separation of concerns” 
It is a meeting point between the http web world and with PHP object oriented world.

This script tells whole top level application sequence

Feel free to edit it as you like. 

Ok let’s get back to application graph building…



The services in the application script may also need dependencies recursively.



Finally we can get one single object graph. Which is huge.
Even my 27 monitor can’t show all the objects at once.

That is why I made this graph visualizer.



This also another principle of BEAR.Sunday.

It has a unique Runtime DRY*. Don’t repeat the same procedure again and again.

the whole application object graph can be serialized and stored in memory. It is not recreated on each request. All dependency are injected and initialized. *

Super fast.

By this I mean that the whole application object graph can be serialized and stored in memory. It is not recreated on each request.

We can serialize whole application which all dependency are injected and initialized. 
This means a huge boost in performance. Super fast.


Have you got it ?

BEAR.Sunday’s application object is build in the correct way, with DI best practices and performance. 
DI is not only a convenient tool for testability*. That is just one part of the power of DI.

By following DIP completely it can lead us to proper application architecture. 
DI is not a magic wand which automatically upgrades our code.

But if you want to follow OOP principles and write clean code with ease, Its definitely worth it.

Runtime code can be simpler, faster, more flexibility and easy to read.

That is the 1st framework. let’s go to the 2nd !

AOP Framework


Who of you know about AOP?

Have used it?

This is a definition….


  • Have you seen code like in RED? Mixture of business & app logic?

  • It runs fine but….

  • Not good separation of concerns

  • Problems with testing, readability and refactoring.

  • Notice how clean this could be in green…


The Aspect Orientated Framework that BEAR.Sunday uses, implements AOP using what is called method interception.

Let’s look at a simple example.


  • Consumer and method stay exactly the same

  • We don’t need to change them

  • There is no base class

  • There is no special way of writing these classes or calling them

The magic I will show you later.

Upon execution the interceptor does not need to be registered. The interception is registered upon binding.


  • Lets Break up the concerns

  • Pull out the logging etc – this is not business logic, they are app logic

An aspect * cross-cuts a method * is readable * testable * completely re-usable and can be re-applied.


Imagine a Rock Concert

  • Band – single concern – business logic
  • Security barrier and guards are an aspect

This is how we use the interceptor in BEAR.Sunday. The interceptor is simple.

  • We invoke the source method as defined
  • Then we retrieve the source object
  • And arguments as needed.

Here is an example of how to use a transaction in AOP.

As you can see the invocation object has been injected using DI.

We can then act upon that wrapping it in a transaction, which rolls back when needed.

Note the $invocation->proceed() method.


A Simple cache interceptor.

  • You can add fancy rules too – this is simple
  • Is the cache there – yes? Just return it, no? Use invocation->proceed

Get the result and warm cache


Create bindings with annotations

  • This shows @db annotation binding
  • @api annotation – JSON would be this implementation.

  • Is MVC enough?
  • Sometimes stuck where to put things?

Much WEB FRAMEWORK functionality is CROSS CUTTING concerns.


An API will often need to change its processing order.


For example:

  • Need AUTHENTICATION when being accessed REMOTELY
  • NOT through the LOCAL app.

  • Some API’s might need Validation or LOGGING.

  • IMAGINE boss asks you to log each DELETE? EASY?


In BEAR these cross-cutting concerns can be registered using

ANNOTATIONS, URI method names.

CROSS-CUTTING CONCERNS attached + detached DEPENDING on context.


  • Model interacted with differently depending on CONTEXT

  • Example FORMS

  • BEAR Sunday Forms are an ASPECTS

  • Can decouple validation


This is the magic

  • It is ugly
  • It is created for you
  • NOT weaver model, AOP Compiler model
  • For Type Safety – For Dependency Injection – Super fast!

INJECTION BY ASPECT

  • MASTER/SLAVE DB
  • master on WRITE
  • slave on READ

The CORE CONCERN is it uses a DB.

The CROSS CUTTING concern is the LOGIC that decides what DB.

  • Extremely testable.
  • Because CORE CONCERN LOGIC does not change.

To wrap UP

The AOP spec in BEAR.Sunday follows the AOP ALLIANCE standard which is common in the JAVA world.

LAYERING of aspects can be freely adjusted DEPENDING on the CONTEXT and environment.

It is TYPE SAFE meaning full dependency injection and seem-less integration with the BEAR compiling step. This is by no means slow!

At runtime necessary components can injected based on look up methods and arguments.

Hypermedia Framework


HyperMedia Framework 、それはオブジェクトをWebサービスのように扱うという試みです。


これがリソースオブジェクトです。URIがクラスにマップされます。

publicプロパティとリクエストインターフェイスがあり、リクエストはステートレスに行われます


リクエストには専用のクライアントが必要です。リクエストを受け取ったリソースは自分の値を決定します。

リソースはまた、他のリソースを必要とするかもしれません。

値がビューコンポーネントに渡され、レンダリングが行われるのではなく

ビューはそれぞれのリソースにインジェクトされ、__toStringメソッドとコンテキストによって出力されます。


HATEOASという言葉を聞いた事あるでしょうか。

アプリケーションのステートをハイパーメディアでドライブします。


@LinkアノテーションとURIテンプレートを使って、リソースをリンクします。


ハイパーメディアAPIはAPIとAPIを繋げ、本当の意味のRESTにします。

Webのように、リソース間の関係をクライアントではなくサービスが持つのです。


world wide webが成功した理由。

それをアプリケーションアーキテクチャの中心にします。


REST、つまりAPI開発を開発の中心にしているです。

かつてはDBはエンタープライズのコアバリューでした。FWや言語が変わってもDBがあれば良かったのです。

今APIがコアバリューです。

APIはハブです。複数のクライアントとストレージ、あるいは他のサービスと接続します。


アンクルBobのClean Architecture、この図を見た事あるでしょう。

(around 50%)


BEAR.Sundayのリソースは同じようにレイヤリングされています。RESTのネイチャーです。

アプリケーションスクリプトがページリソースにリクエストし、ページリソースはアプリケーションリソースをリクエストします。

webページの後ろに何が有るのが露出(expose)していないように、背後のリソースが隠れるのです。


実際のリソースをみてみましょう。

緑のラインがページリソース、それは赤いラインのアプリケーションリソースで構成されています。


開発画面ではURIとそのバウンダリー、そして開発ツールが表示されています。

リソースのロジックとビューはオンラインで編集可能です。


ページリソースはwebページの役割をし、HTTPのメソッドに対応したリクエストメソッドを持ちます。

パラメーターを見て下さい。フォームとPHPのメソッドは統合され同じパラメーターをもっています。 

手続きではなくて契約を表しているのです。


リソース中心、のBEAR.Sundayではこのような一覧表示は自然なことです。
 メソッドをクリックしたらフォームが表示されそれぞれのテストができるようになる…のは少しお待ちください。


アノテーションやDI、これらの言葉はパフォーマンスLoverにとって悪夢に聞こえないでしょうか?

実際は構成済み(configured by context)のオブジェクトが再利用されるので、これらのコストは0になるのです。

フレームワークとしての最大限の柔軟性を持ちながら、パフォーマンスは非常に良好です。


リソースの指定にはクラス名ではなくてURIを使います。

Facebookが開発したThriftを使えば、高速なJavaプログラムを同じURIでコールする事ができます。


プログラムは変わりやすいところと変わりにくいところがあります。 我々はそれぞれハードスポット、ソフトスポットと呼んでいます。

システム毎に決まる変更点はハードスポット、一旦構成されればリクエストの度には変わりません。 例えばDBのIDや利用するテンプレートエンジンの種類です。

アスペクトはソフトスポットを取り扱います。例えばメソッドによって接続DBを変えます。

What is BEAR.Sunday ?

BEAR.Sundayは接続フレームワークです。 
DIはオブジェクトとオブジェクトを依存性によって接続します。アプリケーションはオブジェクトグラフとして表されます。

同じインターフェイスしかし違う実装でオブジェクトを繋ぐ事で、HTML表現の普通のアプリなのか、それともモバイルアプリケーションのためのAPIアプリケーションなのかを決定するのです。

AOPはドメインロジックとアプリケーションロジックをつなぎます。メソッドインターセプションは驚くべき簡単な仕組みで、本質的関心と横断的関心を繋ぎます。

AOPプログラミングに行ったん慣れてしまうと、一体以前はどこにログやトランザクション、認証やバリデーションを置く事ができたのか不思議に思うでしょう。

REST – Hypermediaは情報と情報、リソースとリソースを接続します。リソースは意味によって繋がれ、そのリンクはサービスサイドで変更可能です。

情報に真の意味での価値を与えるのはその繋がりです。APIをハブに、RESTを中心にしたロングタームのアーキテクチャをするのです。


BEAR.SUndayはアブストラクションフレームワークです。

抽象化のためのテクノロジーを最大限使用しています。

実装を直接表すのではなく、抽象化された意図(intention)を表します。

アノテーションでアプリケーションロジックを、ハイパーリンクでリソースとリソースの関係を表すのです。手続きではなく、関係性を記述するのです。

コンテキストと束縛によって、その意図に実装(implementation)が与えられます。

@Transactionalとアノテートしたメソッドにはトランザクションコードがラップされ、URIには全く別の言語の別のメソッドをマップする事が原理的に可能なのです。


We had a lot of technical talks.

3 frameworks in one session ? You must be tired.

Lets take a break with this beautiful English garden.

It is full of flowers, trees, fountains. It seems to offer everything. 
Each garden has its own style but fundamentally has a similar design.

They certainly seem joyful and certainly contain many great features and are welcoming.

Visitors can enjoy the garden as the gardener intended them to. 

For me, many frameworks look like this English garden.

Now, Look at a Zen garden.

No water, No trees or flowers.

There is nothing here that’s common in western gardens.

But you will notice after some time, it offers nothing but perfect harmony.

This garden has only abstraction. Your imagination and your mind can reflect on this garden (when it’s ready.)

Minimalism. Look at this garden, what can I remove? Nothing, it’s impossible!
 The opposite way of thinking is more common. You add more elements and functions until you can’t add anymore, then you will think. “oh now it is complete.” 
When I built this framework, I thought:  ‘How can I reduce the rules or code base? without loosing any functionality by design’

To provide the best tools, I decided not to try and develop them myself. It’s impossible. A lot smarter people can make better tools.

Instead, I decided to provide the maximum freedom you can then choose the best tools with proper constraints.

Freedom doesn’t meant, You can chose anything for any part. You can’t wear jeans under a kimono. 

You need harmony, you need good constraints.

BEAR.Sunday wants to be your zen garden, zen framework.

I hope your imagination, your creativity can be maximized through this connecting framework, a harmony framework.

Lastly, don’t put ’d’ after ‘n’, That’s another framework. Thank you very much.


Do-mo, Arigato.

力を尽くし臨んだプレゼンテーションは、次の人が「ちょっとやりにくい」と言ってくれたぐらい大きな拍手で終了しました。

(続く)

PHPNW 2013 (1)

| Comments

2014年、あけましておめでとうございます。 年が変わってしまいましたが、2013年のBEAR.Sundayにとって最大のイベントphpnw13に参加した事を記事にします。

20 June; CFP (Call for Paper)

phpnw(PHP North West)カンファレンスはイギリスのマンチェスターで2008年から毎年開催されている欧州でも有数の規模のPHPカンファレンスです。 スピーカーとして参加する為にはCFPが必要で、単に「自分の興味ある技術的な話をします」ではなく“why we should accept your talk” (なぜ主催者達が自分の応募を採用するのか)という事を伝えなければなりません。 以下のようにタイトルを3つ考えました。

  • API driven development for API driven World
  • Think differently, REST centric approach solve REST problem effectively.
  • A resource orientated framework using the DI /AOP/REST Triangle

採用されたのは3つ目です。そのタイトルに沿った詳細な紹介文を通訳兼共同発表者のリチャード(@mackstar)さんに用意してもらって応募しました。

Many web developers have a REST or API part of their app when offering it as a service. In this session I will show you how in making REST a central part of your design you can have a huge amount of consistency at the core of how you code. REST gives us much of the power we need in development and is not just for API’s. This session will completely change the way you think about REST. BEAR.Sunday is a REST-centric framework that makes you think totally different about how to go about architecting web-apps and platforms to the maximum potential with elegance.

03 July; 採用

採用の返事が来たのは7月4日。夏期休暇でスイスを友人とレンタカーでドライブをしてた時に連絡がありました。

We were delighted to hear from you and we would love to extend an invitation for you to give your talk “A resource orientated framework using the DI /AOP/REST Triangle” at our conference.

採用された事に驚きました。そして今スイスにいるのにまた三ヶ月後にイギリスに返るのかとも思いましたが、友人は「行くしか無い、他の選択肢はない」とはっきり言い切ります。 英語のプレゼンも、舞台の大きさも、完全に自分のキャパシティを超えてましたが腹を決め渡英するとの連絡をしました。

採用のプロセスは厳しくキュレーターが4人全ての人の採点が10点中の9か10が必要です。200以上の応募があり採用率は15%以下。 技術レベルは三段階の最上位での応募でした。「基本的にみんなフレームワーク選択の話にあまり興味はない」との事で応募はかなり無謀だったのですが、一緒に発表をするリチャードさんのクレジットもあり採用されました。 3つのトラックが同時進行して、ホールは大中小の大きさがあります。選ばれたのは定員100人程度の真ん中の大きさのホールでした。

28 Sep; @leedsphp ユーザーグループとBBC

どうせ渡英して話すならと地元のleedsphpユーザーグループのmeetupとリチャードさんが働くBBCでもセッションを持つ事になりました。いわば大舞台のphpnwのカンファレンスの練習です。 日本の勉強会のようなものですが、流石イギリスというか、雰囲気のある場所です。

手元の書類が見えにくいぐらい照明を落としたところで最初のスピーチをしました。 機材トラブルもあり、スピーチそのものできはあまり良くなかったのですがかなりの熱を持って聞いてもらう事ができました。

通常は(日本と違って)トークが終わると基本すぐに解散らしいのですが、終わった後もみなさんといつまでも色々な事を話ました。「こういう反応は今まで見た事がない」反応だったそうです。 興味を持って質問を積極的にしてくれた方はSymfonyを使っている人が多くSensio Labsの方もいました。元々Symfonyユーザーは多いのでしょうが、日本のSymfonyユーザー会の人達の縁ある事もありなにか不思議な感じです。

次はBBCです。ここでのセッションが一番緊張しました。

BBCでの経験は驚きの連続です。世界最高のメディア企業でのWebプロダクト制作、その現場です。 とにかくかっこよくて、詳しい事が書けないのは残念です。一日始業から終わりまでインターンのように過ごす機会にも恵まれその現場の空気やワークフローの実際に立ち会う事ができました。 シニアアーキテクトのマシューさんとのランチの機会も頂きました。「軽いおしゃべり」という予定だったのですが、ほとんどの時間はBEAR.Sundayについての質問とその答えというやり取りになりました。 質問が非常にシャープで的確です。「そのアーキテクチャのポイントを、ノンテクニカルな人に3分で伝えるとしたらどう話す?」等、こちらが試されるような質問の連続です。 真剣な質問に真剣に答えます。手応えのあるやりとりは満足のできるものでした。

とても緊張してプレゼンテーションを行いました。イギリスのバーの二階でやったleedsphpユーザーグループの時と違って、就業中に時間をさいて集まってくれたBBCのWebエンジニアの方々はとても真剣です。 しかし内容を高く評価してもらいphpnwでの発表が少し安心できるものになりました。またアーキテクチャにとても関心が高い事の確信も得られました。 (BBC Future Media SportsのSenior Technical Architectのマシュー・クラークさんとリチャードさんの三人とBCの食堂でランチ。)

phpnw13

02 Oct; Hackason

カンファレンスの前日金曜は昼間はチュートリアル、夜はハッカソンがあります。ハッカソンと言っても日本のものと違って何かを個人で制作して発表するとかではありません。 例えば「PHP-Excel」とか並んでいるテーブルにプレートがあるので、自分の協力したいオープンソースのテーブルに加わりコーディングしたりおしゃべりをしたりするのです。終わる時に特に発表もありません。 カンファレンスの前日のソーシャルな時間とも思えました。@leedsphpで知り合った人達にも会え、色々話す事ができました。

05 Oct; 発表の日

セッションは土曜日から始まります。オープニングキーノートはLorna MitchellさんとIvo Janschさんの 0x0F Ways to be a Better Developer (より良いディベロッパーになる0x0Fの方法)。

会場は2つに別れていて、二人のスピーカーを映像で繋げそれぞれ交互に変わりながらプレゼンテーションを行うといった凝った仕掛けです。キーノートのテーマがPHPの進化や特定技術ではなくて「より良い開発者になる」というのは印象的でした。 例えば“Get Out of Your Comfort Zone” 「普段の安全で良く知った自分のフィールドから飛び出し、リスクをとって”Enjoy the unknown”しましょう」という事ですが、 「今回マンチェスターで自作のフレームワークのプレゼンテーションを行うのは充分Get Outしてますしてます。the unknownを楽しんでます!」と頷きながら聞いてました。

自分達の発表の練習や最後の準備もしなければなりませんが、聞きたいセッションも沢山あります。プレンゼンテーションの内容は非常に充実していて、スピーカーも普段もネットで目にするような有名な人ばかりです。

phpnw13 Schedule http://conference.phpnw.org.uk/phpnw13/schedule/

「speaker shadowです」1人のスタッフが現れました。どうもスピーカーの世話をする人の事をspeaker shadowというようです。かっこいい言い方するんだなあとか思いながら、装備するワイヤレスマイクや接続するMacの手順などの打ち合わせをします。

スピーカーに対するケアがとても手厚いのです。phpnwは有料カンファレンスで、チケットは£135.00(現在12/31のレートで23,430円)します。 スピーカーに報酬はありませんが、滞在中の食事や宿泊費は全て賄われます。ホテルの部屋にはエッセンシャルキットと言って、ミネラルウォーターや洗面道具のキットのwelcomeセットのようなものが部屋に用意されています。 スピーカーだけにトレーナーやギフトもありました。食事は例えば、スピーカーディナーはコース料理なのですがそのメニューは事前にwebで注文しておく事ができ、例えばベジタリアンの人などへの配慮もあります。 スピーカー同士の交流が図られるという事が大事です。食事の度に顔を合わせて一緒に話したりするので自然と交流が持て色々な話が聞けます。

いよいよ、時間が近づいてきました。 前のセッションはDrupal。世界のPHP開発者の誰もが知るプロダクトでスピーカーはその開発者、立ち見がでるくらい満員です。

その次が自分達の番、誰も知らないフレームワークの発表です。

(続く)

BEAR.Sunday England Tour 2013

| Comments


無名の個人が作った無名のフレームワークをこれだけの規模のカンファレンスで発表するというのを聞いた事がありません。そもそも「誰も新しいフレームワークに興味が無い」というこで、新しいどころか世界の誰もが知っているフレームワークが200を超えるCfPの中で落選してる事も知りました。

そこでこういう言葉でセッションを始めることにしました。紹介します。

It’s an honor to be here as a speaker.
But, some of you guys may wonder (or may have doubts) about an unknown person talking about an unknown framework.

But I’m not here to teach you how to use my framework. No .

I’m here to share this new way of thinking, a new way of solving the web problem.
How do we look at the problem.

Yes, It’s about outlook.

Ok let’s start.

こういう機会を得られたのはリチャードさんという素晴らしい開発者のこれまでのコミュニティに対するコントリビュートがあり、彼のアクションに周りの信認があるからだと思ってます。そのリチャードさんにphpmatsuriというイベントで出会う事ができ交流を持てた事も縁です。

機会や縁に感謝しつつ、挑戦の旅に出かけます。

PEAR

| Comments

What is PEAR ?

公式サイトのトップページに、PEARとはなにかがこのように説明されています。

What is PEAR ?

PEAR is a framework and distribution system for reusable PHP components.

PEARはフレームワークであり、再利用可能なPHPコンポーネントのディストリビューションシステムです。

PEARの持つ2つの側面。フレームワークディストリビューションシステムと簡潔に説明されています。

PEARの誤解

PEARは一般にいくつか誤解されてるようです。

グローバル

PEARはグローバル専用でなく、「ひとつのプロジェクトにおける依存関係を管理」に利用することは可能です。特殊なHackなどではなく、標準で用意された方法です。

.pearrcをconfig-createで作って、オプションで指定するだけです。

1
2
3
$ pear config-create /path/to/pear .pearrc
$ pear -c /path/to/pear/.pearrc install PEAR
$ pear -c /path/to/pear/.pearrc install PEAR Cache_Lite

BEAR.Saturdayでもユーザー環境へのインストールを紹介していて、実際多くのプロジェクトがプロジェクト単位で構築されて駆動しています。

チャンネル

作成したパッケージをwebでサービスするために、パッケージ登録のための投票を受ける必要はありません。それは公式のチャネル pear.php.netでの話です。公式に載せていない、独自のチェンネルでサービスをしているパッケージも沢山あります。BEAR.Satuday http://pear.bear-project.net/ もその一つです。

どちらも改善の余地はあるものだったのでしょうが、機能的には可能でした。またPEARの大きな特徴として後方互換性の完全な維持がありました。

BCブレイク

PEARは後方互換性を破らないという厳しいルールがありました。BEAR.Saturdayは沢山の依存PEARパッケージがあり、数えきれないほどPEAR upgradeしましたが問題が出た記憶がほとんどありません。 バージョンが.1あがったら互換性でエラーだらけになるような事は決してありませんでした。

依存管理で正確なバージョンを特定しなくても、最新バージョンを入れれば機能しました。しかしこれは、そこまで厳格でないパッケージの依存を扱う時に困った事になります。composer.lockのような機構はありませんでした。PEARのような高い品質を持ったライブラリ同士でなければ問題になってしまいます。

PEARはフレームワーク

PEARはコード作成に関する標準スタイルや共通のエラーメカニズム、バージョニング、ディストリビューションをも含んだ包括的なフレームワークです。Internet ArchiveによるとPEARに初出は2001年です。こんなに速い時期からこんなフレームワークが提供できたのはPHPコミュニティの誇れる歴史です。

後に続く非PEARのアプリケーションフレームワークやライブラリは、この偉大な先輩にリスペクトを持ったものと、全く持たないものがありました。コーディング規約やフォルダ構造を見れば分かります。1 例えばPEARのフォルダ構造はPseudo-namespace(PHP5.3以前のなんちゃって名前空間)に従ったもので一貫性がありauto loaderが簡単に実装できましたが、独自のフォルダ構造をもちクラスファイルの読み込みに大変なコストがかかるものもありました。2

ただ、その高すぎる理想と、GitHubを中心とした新しいコーディング文化、PHP5.3以降のライブラリ群の依存要求、Pyrus移行の失敗、など様々な要因によってPHPの依存管理の主役の座をComposerに明け渡す事になります。

しかしPEARは当時のPHPの最良を提供しようとした、意欲的で完成度の高い包括的なエコシステムです。今のPSRやコーディングにも多くの影響を与えています。単に古く間違ったプラクティスとして忘れてしまおうという考えには賛同できません。主役の座は受け渡しましたが、今でもいくつものライブラリは有用だしディストリビューションシステムとしても健全で機能します。公式サイトでホストされてるライブラリは複数のレビュアーが承認した質の高いコードで、コードリーディングのテキストとしても有用です。

PEARはPHPコミュニティの誇れるべき財産だと考えます。

  1. BEARは前者です []
  2. 何のための逸脱なのか分かりません []

Ray.Tutorial – First DI Framework

| Comments

初めてのDIフレームワーク

準備

  1. PHP5.4+で動作します。mysqlで予めテーブルを作成しておきます。 2 フォルダをつくります。
1
2
$ mkdir ray.tutorial
$ cd ray.tutorial

まずは手動でインジェクションするコードソースを入力して実行します。

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
<?php
class Todo
{
    /**
     * @var PDO
     */
    private $pdo;

    /**
     * @param PDO $pdo
     */
    public function __construct(PDO $pdo)
    {
        $this->pdo = $pdo;
    }

    /**
     * @param string $todo things to do
     */
    public function add($todo)
    {
        $stmt = $this->pdo->prepare('INSERT INTO TODO (todo) VALUES (:todo)');
        $stmt->bindParam(':todo', $todo);
        $stmt->execute();
    }
}
$pdo = new PDO('mysql:dbname=test;host=localhost');
$todo = new Todo($pdo);
$todo->add('Get laundry');

実行してみます。

1
$ php manual-di.php

データベースにtodoが入力されたか、コンソールかツール等で確認します。1 確認できましたか?OK? では、次にcomposerのプロジェクトを作ってこのクラスをDI化してみましょう。

composerでRay.Di依存の空プロジェクトを作る

まずはcomposerをダウンロードします。

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

composerを使ってRay.Diを使うプロジェクトを作ります。

1
$ php composer.phar init

すると色々質問されるので、ray/diのバージョン* (最新の安定板)をインストールするように答えます。

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
  Welcome to the Composer config generator
This command will guide you through creating your composer.json config.
Package name (<vendor>/<name>) [akihito/ray.tutorial]:
Description []:
Author [Akihito Koriyama <akihito .koriyama@gmail.com>]:
Minimum Stability []:
License []:
Define your dependencies.
Would you like to define your dependencies (require) interactively [yes]?
Search for a package []: ray/di
Found 15 packages matching ray/di
   [0] ray/di
   [1] ray/aop
   [2] jms/di-extra-bundle
   [3] aura/di
   [4] orno/di
   [5] league/di
   [6] mnapoli/php-di
   [7] zendframework/zend-di
   [8] mnapoli/php-di-zf1
   [9] ocramius/ocra-di-compiler
  [10] lcobucci/di-builder
  [11] aimfeld/di-wrapper
  [12] kdyby/autowired
  [13] seiffert/console-extra-bundle
  [14] vojtech-dobes/extensions-list
Enter package # to add, or the complete package name if it is not listed []: 0
Enter the version constraint to require []: *
Search for a package []:
Would you like to define your dev dependencies (require-dev) interactively [yes]?
Search for a package []:
{
    "name": "akihito/ray.tutorial",
    "require": {
        "ray/di": "*"
    },
    "authors": [
        {
            "name": "Akihito Koriyama",
            "email": "akihito.koriyama@gmail.com"
        }
    ]
}
Do you confirm generation [yes]?
</akihito></name></vendor>

入力の必要な質問はこれだけでした。

1
2
3
Search for a package []: ray/di
Enter package # to add, or the complete package name if it is not listed []: 0
Enter the version constraint to require []: *

すると最後に表示されたcomposer.jsonが出来上がりますが、まだray/diはインストールされていません。installコマンドでインストールします。

1
$ php composer.phar install

initコマンドで作成したcomposer.jsonに従ってRay.Diとその依存ファイルとダウンロードされ、現在の依存の状態が記録されたcomposer.lockファイル、それにautoloaderを含むcomposerのファイル群もインストールされました。

1
2
3
4
5
6
7
8
9
10
$ tree -L 2
├── composer.json
├── composer.lock
├── composer.phar
└── vendor
    ├── aura
    ├── autoload.php
    ├── composer
    ├── doctrine
    └── ray

Ray.Diを使ったコードを入力してsrc/フォルダを作ってその下に配置します。 src/todo3-ray-di.php

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
<?php
use Doctrine\Common\Annotations\AnnotationRegistry;
use Ray\Di\AbstractModule;
use Ray\Di\Injector;
use Ray\Di\Di\Inject;
use Ray\Di\Di\Named;
$loader = require dirname(__DIR__) . '/vendor/autoload.php';
AnnotationRegistry::registerLoader([$loader, 'loadClass']);
class Todo
{
    private $pdo;
    /**
     * @Inject
     */

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

    /**
     * @param $todo
     */
    public function add($todo)
    {
        $stmt = $this->pdo->prepare('INSERT INTO TODO (todo) VALUES (:todo)');
        $stmt->bindParam(':todo', $todo);
        $stmt->execute();
    }
}
class Module extends AbstractModule
{
    public function configure()
    {
        $pdo = new PDO('mysql:dbname=test;host=localhost');
        $this->bind('PDO')->toInstance($pdo);
    }
}
$injector = Injector::create([new Module]);
$todo = $injector->getInstance('Todo');
/** @var $todo Todo */
$todo->add('Walking in Ray');

これがRay.Diを使ってDIを行っているコードです。変わった部分をそれぞれ見て行きます。

オートローダー

1
2
$loader = require dirname(__DIR__) . '/vendor/autoload.php';
AnnotationRegistry::registerLoader([$loader, 'loadClass']);

composerを使うと依存ファイルのオートローディングの設定が含まれた、vendor/autoload.phpというオートローダーのファイルが自動で生成されます。 Ray.DiのアノテーションはDoctrineのアノテーションを使っています。アノテーションの読み込みにはオートローダーの登録が必要で、いくつかの方法がありますがここではcomposerのオートローダーをそのまま使っています。

アノテーション

1
2
3
4
5
    /**
     * @Inject
     */
    public function __construct(PDO $pdo)
    {

依存を受け取るメソッドには@Injectとアノテート(注釈)されています。Ray.Diはこのアノテーションを目印にして依存が必要なメソッドを割り出します。2 アノテーションはクラスで、名前解決のためuse文が必要です。3

1
use Ray\Di\Di\Inject;

モジュール

モジュールでは依存を必要とする場所に依存をどう渡すかを記述します。

1
2
3
4
5
6
7
8
class Module extends AbstractModule
{
    public function configure()
    {
        $pdo = new PDO('mysql:dbname=test;host=localhost');
        $this->bind('PDO')->toInstance($pdo);
    }
}

AbstractModuleを継承したクラスのconfigure()というメソッド内で、bind()メソッドを使って依存を束縛(バインド=結びつけます)します。ここではPDOクラスを必要とするインジェクションポイントに作成した$pdoインスタンスを束縛しています。 これによってアノテーションの節で説明したように@injectとアノテートされPDOクラスのタイプヒントを持つ引き数には$pdoインスタンスが渡されるようになります。

インジェクター

モジュールを使って作成したインジェクターは、どの依存が求められれば何を渡せばいいかを知っています。そのインジェクターを使って’Todo’クラスを取得するとインジェクターは必要とされる依存をモジュールで決めたルールで渡し、依存解決(dependency resolution)が行われます。

1
2
$injector = Injector::create([new Module]);
$todo = $injector->getInstance('Todo');

ついに出来ました!!!! $todoオブジェクト!!! 依存の問題を解決(外部の変数を外側から渡す)を自動化するために、様々な事が必要になりました。 依存が必要な箇所にアノテーションが必要です。そのアノテーションクラスのオートローディング登録も必要で、モジュールでも依存の束縛の記述、束縛を使ったインジェクターの作成をしてようやく依存解決をするインジェクターが作成されました。 1つの問題を解決するためにこれだけの事をしたのです。4DIフレームワークはRayだけではありません。他のDIフレームワークも同じような、あるいはこれ以上の準備の手順の複雑さを持っています。

オーバーエンジニアリング?

オーバーエンジニアリング(作り込みのし過ぎ、過剰技術)でしょうか? まず、他の技術同様に、説明のための単純な例で実利を感じる事は往々にして難しい事は頭に入れておく必要があります。例えば、HelloWorldのサンプルでフレームワークのメリットを実感する事はなかなか難しいでしょう。 DIフレームワークの使用がオーバーエンジアリングか、クラス名のハードコーディングがアンダーエンジニアリングなのか、その辺りの判断を直感で出すのはひとまず置いといて、Ray DIフレームワークの使い方の実例をもう少し見て行きましょう。 …続く

  1. あるいはSELECTをするメソッドを追加してください! []
  2. コンストラクタ以外でも依存を受け取る事ができます。@Injectとアノテートしてメソッド名は何でもかまいません []
  3. Doctrineアノテーションの仕様です []
  4. NateさんのLithiumのスライド A Framework for People who Hate Frameworks – Lithium もご覧下さい []

Ray.Tutorial – Introduction

| Comments

Introduction

BEAR.SundayのDIとAOP(Ray.Di)を理解するためのチュートリアルです。

最初に題材としてTodoクラスを作りました。$todo文字列を受け取ってデータベースに格納するだけのクラスです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
class Todo
{
    /**
     * @param $todo
     */
    public function add($todo)
    {
        $pdo = new PDO('mysql:dbname=test;host=localhost');
        $stmt = $pdo->prepare('INSERT INTO TODO (todo) VALUES (:todo)');
        $stmt->bindParam(':todo', $todo);
        $stmt->execute();
    }
}
$todo = new Todo;
$todo->add('Pay bills');

システムの可変点

このプログラムはちゃんと動きますが、再利用性はどうでしょうか?
データベースの接続情報がプログラムに直接記述、ハードコーディングされてあるのは問題です。

他の部分は運用環境に変更があっても変わりませんが、DBの接続情報は変わります。
このようにプログラムには変更の可能性が高い場所とそうでも無い場所があります。

定数を使う

初期のシステムではこのようなシステムで変更部分のある情報を定数を使う事で解決していました。プログラムの初期化(bootstrap)ではdefineが並んだファイルを読み込みます。

1
define('PDO_DSN', 'mysql:dbname=test;host=localhost');

利用部分ではその情報を使います。

1
$pdo = new PDO(PDO_DSN);

ハードコーディングされていた箇所は取り除かれ、コードはよりクリーンになりました!

定数ファイルをみると、そのシステムでの変更部分が集約されていて変更可能な箇所を一覧することもできます。可変点は集約され、DBの接続情報に変更があっても利用コード全体を調べる必要がなくなりました。

しかしdefineはスカラー値(float、string、boolean)しか定義できません。また グローバル定数なのでシステムのどの部分からもアクセスができます。

Configureクラスを使う

設定値をより柔軟に取り扱うためにConfigureクラスの導入を考えてみます。

Configureクラスは設定値の入れ物(コンテナ)を用意します。bootstrapでプログラムに必要な設定情報を設定ファイル(ini/yaml/php配列)を読み込んだりコードで直接代入したりして準備しておきます。

1
2
$connection = Configure::read('pdo');
$pdo = new PDO($connection['dsn'], $connection['user'], $connection['password']);

利用するときにはそのConfigureクラスとセットに使ったキーを使ってその値を取り出します。これで設定に配列も扱えるようになりました。設定の代入も多様な方法で行えます。

しかし一方で、このアプリケーションは依然としてコード中のどこからでも同一の値にアクセスできるグローバルスコープの設定値を持っています。”コントローラだろうがモデルだろうがビューだろうがアプリケーション内のおおよそ全ての場所”から利用可能です。

グローバル変数$_GLOBALSを使う

1
2
$connection = $_GLOBAL['MYAPP']['pdo'];
$pdo = new PDO($connection['dsn'], $connection['user'], $connection['password']);

グローバル変数に抵抗がありますか? グローバルスコープでどこからも参照できる変数という意味では、グローバル変数もConfigureクラスもあまり変わりません。実際CakePHPではこのような注意書きがあります。

何でも保存でき、コード内のあらゆる場所で使用できるので、CakePHPのMVCパターンを崩してしまう誘惑には注意しましょう。

グローバルスコープの変数、特にごく単純なものなら$_GLOBALSを使うのは自然です。ただ競合しないようにpresudo-namespace(prefixを使ったなんちゃって名前空間)を使うのがいいと思います。PEARでも使用例がいくつもあります。

しかし、defineもグローバル変数もConfigure専用クラスもグローバルスコープでどこでも参照できる点には代わりがありません。

BEARでは

前のバージョンのBEAR.Satudayではグローバルdefineが2つ(時間とアプリケーションパス)ありましたがBEAR.Sundayではありません。またConfigureクラスのようなどのクラスからも参照できるグローバルスコープの設定値専用の変数コンテナはありません。

インスタンスの管理を考える

次にインスタンスの管理を考えてみます。本来PDOオブジェクトはメソッド内で毎回newして新しいインスタンスを作る必要はありません。一度生成すればそのオブジェクトを再利用したいところです。

そこで、メソッドの生成・管理をメソッドに任せる事にします。「シングルトン」です。

1
2
3
4
5
6
7
8
9
    private $instance;

    public static function getInstance()
    {
        if (is_null(self::$instance)) {
            self::$instance = new self;
        }
        return self::$instance;
    }

このようメソッドを各クラスに持って以下のように取得します。

1
$pdo = Db::getInstance();

newでインスタンス生成が行われるのは一度だけで、次回以降は生成済みのインスタンスが渡されるだけです。

しかし、このようなシングルトンのコードはテストに向かない保守性の低いコードになってしまいます。コード中のどこからでも同一のインスタンスにアクセスするグローバルスコープのオブジェクトになっているからです。

オブジェクトの生成・管理がまとまった仕事であるなら、専用のクラスを持つのは自然な話です。1
例えばその専用クラスは以下のように使われます。

1
2
3
4
5
// Global registry
$pdo = ServiceContainer::get('pdo');
...
// Contextual dependency lookup (CDL)
$pdo = $this->app['pdo'];

bootstrapでは何らかの方法でオブジェクトの生成の準備を完了させておき、取り出し’キー’と共にオブジェクトが取り出せる準備をしておきます。

利用する方は、これがシングルトンで渡されるかどうかを指定しません。またコンストラクタに初期値も渡しません。利用側ではオブジェクトをどう生成するかに関心を持たずに単に取り出し用のキー名指定するだけで利用できます。

pros

ここでは利用だけに注目しましょう。オブジェクトの生成方法ががどんなに複雑になっても、インスタンスの管理方法が変わっても、取得の方法に変化がありません。これを利用するクラスは保守性の高いコードになりやすいでしょう。

cons

一方、このコードだけを見ても$pdo変数は何のオブジェクトで何ができるのが分かりません。ServiceContainer::getのphpdocの@returnを見ても分かりません。ServiceContainerクラスの働きを理解して、何がどう’pdo’にセットされているか、コードかドキュメントから知る必要があります。Todoクラスの実行にはServiceContainerクラスが必要になりました。ユニットテストの時もServiceContainerクラスが必要です。クラス間の依存を減らす為に一つ依存が増えました。

依存性の注入

これまで、オブジェクトをどうやって作り、どうやって管理するか、というオブジェクトの生成と管理の視点でコードを見て来ました。様々なやり方を検討してきましが、いずれの方法も オブジェクトを生成するか、または他のクラスを使って取得していました。(Dependency Lookup) これから見るのは依存性の注入と呼ばれるパターンで、依存オブジェクトの取得は完全に受け身になります。

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
<?php
class Todo
{
    /**
     * @var PDO
     */
    private $pdo;

    /**
     * @param PDO $pdo
     */
    public function __construct(PDO $pdo)
    {
        $this->pdo = $pdo;
    }

    /**
     * @param string $todo things to do
     */
    public function add($todo)
    {
        $stmt = $this->pdo->prepare('INSERT INTO TODO (todo) VALUES (:todo)');
        $stmt->bindParam(':todo', $todo);
        $stmt->execute();
    }
}
$pdo = new PDO('mysql:dbname=test;host=localhost');
$todo = new Todo($pdo);
$todo->add('Get laundry');

内部で必要なオブジェクトをハードコードして生成/取得するのではなくて、クラスの外から依存が代入されています。DBオブジェクトがDBの接続情報文字列を可変点と考えたように、DBオブジェクト利用クラスにとってDBオブジェクトが可変点と考えます。

これが依存性の注入(dependency injection=DI)です。

「利用するインスタンスを外部から渡す」- DIの本質的なところはこれだけです!

ファウラーの「Inversion of Control コンテナと Dependency Injection パターン」を読んだ人はえ?っと思うのではないでしょうか。2

それを揶揄した記事もあります。

“Dependency Injection” is a 25-dollar term for a 5-cent concept.
Dependency injection means giving an object its instance variables. Really. That’s it.

依存性の注入はwikiではこのように説明されています。

依存性の注入(いぞんせいのちゅうにゅう、英: dependency injection)とは、コンポーネント間の依存関係をプログラムのソースコードから排除し、外部の設定ファイルなどで注入できるようにするソフトウェアパターンである。

依存性の注入を利用したプログラムを作成する場合、コンポーネント間の関係はインターフェースを用いて記述し、具体的なコンポーネントを指定しない。具体的にどのコンポーネントを利用するかは別のコンポーネントや外部ファイル等を利用することで、コンポーネント間の依存関係を薄くすることができる。

このwikiの説明はパターンの説明というよりもその実際の説明により過ぎてるように思います。英語版はもっと明快です。

Dependency injection is a software design pattern that allows the removal of hard-coded dependencies and makes it possible to change them, whether at run-time or compile-time.1

依存性の注入とはランタイムやコンパイルタイムでハードコードされた依存を取り除き変更可能にするためのソフトウエアデザインパターンの一つ

上記のサンプルは設定ファイルもインターフェイスも出て来ませんが、DIを適用したコードです。英語版wikiの説明のようハードコードされた依存は取り除かれ、変更可能になっています。

再びシングルトン

同じオブジェクトを再利用するシングルトンもやってみましょう。

1
2
3
4
$pdo = new PDO('mysql:dbname=test;host=localhost');
$todo1 = new Todo($pdo);
$todo2 = new Todo($pdo);
...

同じオブジェクトを渡す事で、それぞれ別の利用クラスが同じ依存インスタンス($pdo)を使っています。依存クラスは利用クラスの外側で集中して管理されていて、PDOインスタンスの生成は一度だけです!

問題を違う場所に移しただけ?

…と、ここまで見て、確かにTodoクラスから依存が取り除かれコードはすっきりしました。テストもより簡単になったでしょう。

その代わり依存のややここしいところはオブジェクトの生成部分に依然あるし、設定値もハードコーディングされています。オブジェクトの利用から問題を取り除いた代わりに、オブジェクトの生成の部分が問題になったように見えないでしょうか。つまり依存の問題を解決したというより問題をある場所から違う場所に移しただけのように見えないでしょうか。

これらをRay.Di DI frameworkではどういう風に解決してるか、次回から見て行きます。

…続く

  1. BEAR.Saturdayでは BEAR::Dependency []
  2. かつての自分です []

BEAR.Sunday Meetup #2

| Comments

BEAR.Sunday meetup #2 2013-07-28 3.06.12 IMG_8334
>
  Meetup
</h2>

Meetup

BEAR.Sunday meetup#2を開催しました。

学習より交流、啓蒙というよりアイデアの交換、勉強会というよりmeetup、そういう風に今回はよりmeetupらしくしようとドリンクタイムと全員LTから始めました。場所は秘密基地の雰囲気ただようHubTokyoラウンジスペース。

LTの順番もリストされたものではなくて、関連がありそうだったりその場の雰囲気だったりで手を上げ「じゃ次やりますー」と前に出て3分という短い時間で自分の考えや視点を中心に話します。役に立つ話である必要はないし、結論でさえ不要です。

普段プライベートに持っている個人の考えや問いかけがパブリックになって、刺激を受けるというのは面白いです。

土曜日らしいゆっくりした雰囲気で始まったmeetupは、セッションを時々挟みながら、しかしあくまでフリータイム中心に進みます。

Resource Oriented X

サプライズでLithiumのリードデベロッパーで来日中のnateさんが遊びに来てくれ、公演までして行ってくれました。BEAR.Sundayはリソース指向のフレームワークですが、このnateさんの公演内容はリソース指向のアプリケーション(with Lithium & AunguraJS)です。

最新技術の最新アプリケーションに圧倒されつつ、「リソース指向」のシンクロニシティにエキサイトしました。

Arigato

遠く大阪や岐阜から訪れてくれた人も「来たかいがあった」と満足して帰られたのではないでしょうか。Nateさんのサプライズもあったし会場も雰囲気も食事も全部良かった。良いmeetupになったと思ってます。緩く始まりドンドン濃くなっていって、最後にドーンとRichardさんとNateさんの花火のようなプレゼンテーションに達成感すら感じました。meetup最後の@haltさんのtweet「すごい密度で疲れたああああ!」..同意です。 小さな集まりですが、質の高い時間を共有できるように私たちスタッフは力を尽くしました。@kuma_nana @zingooo @zukimochi ありがとうありがとう。 トークをしてくれた 神宮君、Richardさん、Nateさん、それにLT&参加してくれた全ての人、スポンサード頂いたHubTokyoWebster、LT「Tech for Social Good 」の明石君にも感謝です。

TEDxTokyo 2013

| Comments

TED / TEDxとは?

TEDx(テデックス)は、TEDの精神である「広める価値のあるアイデア」を共有するために世界各地で生まれているコミュニティー。TEDxTokyo(テデックス・トーキョー)は、世界で2番目、米国以外では最初のTEDxとして、近年のTEDxムーブメントを先導してきました。

5/11にTEDxTokyoに参加しました。

今回の参加

TEDは以前からのファンで日本語が用意されていない頃から見ていました。そのTEDの精神を持ったTEDxの参加への興味は自然の事でしたが直接のきっかけは、初期の頃からボランティアとして参加していた@remore (沢田さん)1 にTEDxTokyoの事や参加のためのプロセスを伺った事でした。

年7500ドル参加に別に2500ドルが必要な本家のTED*と違ってTEDxTokyoの参加に費用負担はありませんが、キュレーションが行われ参加には招待を受ける必要があります。締め切り間近の3/25にParticipant Application Formから申し込んで、幸運な事に直後に招待のメールを受け取ることができました。

「本家TEDと同じく、全セッションおよびセッション間のインタラクティブな休憩時間すべてに参加することを前提にデザインされています」という事でセッションの全てとイーブニングセッションに参加すると確認の返信をして参加が決定しました。

参加決定して助言も頂きました。

説明するまでもないかもしれませんが、TEDxTokyoは単なるプレゼンテーションイベントでもNetworkingイベントでもなく、ある一つのコミュニティです。参加者もスピーカーも、ファウンダーも、ボランティアスタッフも、idea-centeredでinspiringな空間が生まれるようにイベントを設計していきます。どうか当日は話を聞くだけでなく、他の方とのアイデアの交換や会話も含めて楽しんできてください^^

オーガナイザーのトッドさんやパトリックさんの話も知り、ますます盛り上がります。

http://www.shibuyabunka.com/keyperson/?id=109

http://www.1101.com/patrick/index.html

Discovery

僕はよく旅行に出かけます。旅の楽しみは色々ありますが、自分にとって最大の楽しみは「発見」です。その発見の中でも、エキサイティングなのは背景や価値観の違う人達と同じ時間、同じ空間を共有、交流する事で得られる発見です。モノやコトを違う角度で見て、違う解釈をする、しかし同時代に生きる同じヒトとの交流で得られる発見です。

前日に再度 @remoreさんから再度アドバイスを受けます

TEDxではどのような交流があって、どんな発見があるのか。初めての一人旅前日のような高揚感とワクワク感で当日を向かえました

TEDx Talks

当日は13時間の長丁場です。

スケジュール
08:00 受付開始 (軽い朝食と交流会)
08:40 ご着席
09:00 セッション1
10:30 休憩
11:15 セッション2
12:45 ご昼食
14:15 セッション3
16:00 休憩
16:30 セッション4
18:30 ディナーレセプション「TEDxTokyo祭り」開始
21:30 ディナーレセプション「TEDxTokyo祭り」終了

全てのセッションはオンラインで中継されました。現在はほとんど全てのトークやパフォーマンスをTEDxチャンネルで視聴する事ができます。

中でも特に印象に残ったものを紹介します。

愛あるデザインの為に: 田子 學

自分のしてる事を常に問いかけ続ける姿勢に感銘しました。田子さんは最後にこう結びます。「シンプルに見返して、そして信念を見つける事、それを一つ一つ繋げて行く事」

星に届いた夢: 大平 貴之

メガスターは前からいつも一度見て見たいと思っていたのですが、制作者ご本人のユーモアに溢れたセッションを先に聞く事になりました。小さな頃の思いを抱き続けそれを形にして世に問い世界的な評価を手にした事はすごい事です。しかし本人の優しい語り口から、身近な話のように感じ自分自身の経験を重ねて聞いていました。

クモの糸で変わる世界: 関山 和秀

本当に驚きました。「初めはみんな不可能だと言いました」言うでしょう、言うと思います!しかしそれをやりとげ、自ら作った糸を右手で掲げ「私たちはそう思わない」…本当にかっこ良かったです。

社会の役に立たない建築家: 坂 茂

スピーカーの方が登場される前に、オーガナイザーであり進行であるパトリックさんがスピーカーの方を紹介するのですが、最も高揚して紹介されてると感じられたのが最後のスピーカーの坂さんでした。

“権力者の誇示のための建築ではなく、社会のための紙建築”の話です。世界的に高名な建築家2 が「社会の役に立たない建築家」と題し「地震が人々を殺してるんではないのです、地震によって倒壊した建物が人々を殺してる」のですと話します。自身の取り組みを静かな熱意とユーモアで紹介します。

ほかにも人間国宝の室瀬和美さんの漆の話会田誠さんの”テキトー”佐藤卓さんの「あ」モーメント、発見のあるものばかりでした。

TEDx パフォーマンス

江戸古典奇術『手妻』: 藤山 晃太郎

パフォーマンスも全て素晴らしかったのですが、朝一番に出演した手妻師の藤山晃太郎さんの操る蝶が見事でした。江戸時代にマジシャンが居たなんて初めて知りました。それを知った事も良かったです。

YouTubeでは見る事ができませんが、舞踏家の工藤丈輝さんのパフォーマンスも強く心に残りました。

1+1=11

今回のテーマです。1+1=2は日常の世界、1+1=10はコンピューターの世界(二進数)、1+1=11は単純加算ができず、人(one)が並び合い、向かい合い化学反応を起こすTEDxの世界。今回のテーマをこのように解釈しました。

感銘を受けたスピーカーの方に共通してたのは、常に自身や自身の行ってる事に問いかけ続ける姿勢を持っている事でした。語り口は静かですが情熱を持ち、自分のなすべき事に真摯に対峙してる方々の話です。「信念を見つける事、それを一つ一つ繋げて行く事」それを実践している人の話です。「伝える価値のあるアイデア」の元にある「伝える価値のある経験」を共有できた事が素晴らしかった。

多くの方の思いと情熱で作られているTEDxTokyoに参加できて良かったです。

これを何かの形で繋げていかねばなりません。

「単なる1-day eventでは」… 一日が終わり、熱狂が良い感じで引いて来た頃に参加前に聞いた言葉を思い出しました。

% img http://placekitten.com/890/280 %}

  1. PHPのイベントphpmatsuriで知り合いました []
  2. 最近話題になった成蹊大学情報図書館のも坂さんの作品ですね []

Timeアノテーション

| Comments

PHPメンターズのブログで時計オブジェクト(ドメインクロック)を導入してテスト容易性と意図性を高めるという記事が掲載されました。

この記事のように、現在時刻をアプリケーションでどう扱うかをBEAR.SundayのSandboxアプリケーションで見てみます。

@Timeアノテーション

現在時刻文字列を扱いたいクラスにはpublicのtimeプロパティを追加しメソッドにBEAR\Sunday\Annotation\Timeアノテーションを注記(アノテート)します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
use BEAR\Sunday\Annotation\Time;
    /**
     * Current time string
     *
     * @string
     */
    public $time;
    /**
     * @Time
     */
    public function onPut($id, $title, $body)
    {
        $this->time; // 2013-04-03 19:37:40
    }

するとこのメソッドがコールされたタイミングでtimeプロパティに現在時刻が代入されるようになます。メソッド内ではそのプロパティを利用するだけです。

テストコードでは以下のようにpublicプロパティに値を代入します。1 テストは容易に行う事ができます。

1
2
 $user = new User;
 $user->time = "2013-04-03 19:37:40";

DI ? AOP ?

働きとしてはプロパティに依存が代入されるプロパティ・インジェクションなのですが2 、BEAR.SundayではこれをRay.Aopで行っています。メソッドに束縛されたインターセプターが現在時刻をインジェクション(外部から代入)しています。

TimeStamper

BEAR\Package\Module\Database\Dbal\DbalModuleモジュールでDoctrin DBALモジュールを利用するためにDIとAOPの設定を行っていますが、このモジュール内で@Timeとアノテートされたメソッドと現在時刻を代入するインターセプターが束縛されています。

1
2
3
4
5
$this->bindInterceptor(
    $this->matcher->any(), // どのクラスでも
    $this->matcher->annotatedWith('BEAR\Sunday\Annotation\Time'), //@Timeとアノテートされてるメソッドに
    [new TimeStamper] // TimeStamperを束縛
);

TimeStamperは元メソッドのtimeプロパティに現在時刻をセットするだけの単純なインターセプターです。

1
2
3
4
5
6
public function invoke(MethodInvocation $invocation)
{
    $object = $invocation->getThis(); // 元オブジェクト
    $object->time = date("Y-m-d H:i:s", time());  // 現在時刻代入
    return $invocation->proceed(); // 元メソッド実行して返す
}

おわりに

この記事では現在のSandboxアプリケーションで行っている現在時刻文字列を取り扱いましたがこれを\DateTimeにすれば時計オブジェクト(ドメインクロック)を導入してテスト容易性と意図性を高める記事の中のドメインクロックと同じになると思います。

現在時刻を必要とするメソッドに@Timeと注記しその依存を利用する事でテスト容易性(testability)とコードの意図性(intentionality)が実現されています。

また時刻を用意するという関心を1つのメソッドに集約することでフォーマットの一括変更が可能になるのと同時に、その適用を任意に束縛して決定しているのでアプリケーションコンテキストやメソッド・クラス名に応じて変更する柔軟性も確保しています。

  1. セッターメソッドを用意してもいいでしょう []
  2. Ray.Diではプロパティ・インジェクションをサポートしていません []

Ray 1.0.0

| Comments

1.0.0

Ray.Di / Ray.Aopのバージョン1.0.0をリリースしました。

これまでも何度か紹介しましたがRay.Diはオブジェクトとオブジェクトの関係の問題を解決するDIフレームワーク、Ray.Aopはアスペクト指向プログラミングフレームワークでGoogleのDIフレームワークGuiceのPHPクローンです。

first commit

最初に作り始めたのはRay.Aopです。これが最初のコミットです。まだPHP5.4はなく、PHP5.3でコードしていました。
https://github.com/koriym/Ray.Aop/tree/2ab2dff8204622fdfaeae0bd608e88010b98b99f

最初に作ろうとしたのはこういうものでした。

サービス(呼び出される方)

1
2
3
4
5
6
7
class Mock
{
    public function getDouble($a)
    {
        return $a * 2;
    }
}

コンシュマー(呼び出す方)

1
echo $mock->getDouble(3); //6

これらの呼び出しコード、呼ばれるメソッドを変更をすることなく帰ってくる値を本来の値の10倍(60)にしすることを考えます。実現するためにはメソッドの実行呼び出しコードと呼ばれるメソッドの間に、「10倍にする」という処理を差し込まなければなりません。

1
2
3
4
5
6
7
8
class tenTimes implements MethodInterceptor
{
    public function invoke(MethodInvocation $invocation)
    {
        $result = $invocation->proceed();
        return $result * 10;
    }
}

特定のメソッドをコールしたときのコールバックを設定する機能などがあれば簡単なのですが、そういう機能はありません。なのでオブジェクトを作成するときにその「横断的処理」を織り込んだオブジェクトを生成する必要があります。具体的にはgetDouble(2)でコールされたららその結果を10倍にする横断的処理が透過的に呼ばれるようなオブジェクトをつくります。

最初はどうやって記述したらよいかさっぱり分からなかったのですが、AOPアラインスのインターフェイスやメソッドリフレクション、マジックメソッドの組み合わせでなんとか(というよりもしかしたら)出来るのではと考えました。

最初のコミットでのコードはこういうものでした。

1
$mock = new Weaver(new Mock, $interceptors);

元のオブジェクト(new Mock)に「10倍に」という処理を横断的処理($interceptors)を織り込んたもの(Weaver)を元のオブジェクト同様に扱います

1
echo $mock->getDouble(3); //60

できました!

オブジェクトに横断的処理を”織り込む”事により、呼び出し側も呼び出される側も無変更で振る舞いを変更することができました。webフレームワークの機能の多くはこれらの横断的処理です。呼ぶ側も呼ばれる側にも無変更で、動的に横断的処理を着脱できると事に大きな可能性を感じました。

失敗

最初のコミットのRay.Aop、これは大失敗というのがすぐに分かります。

1
$mock = new Weaver(new Mock, $interceptors);

このコードではメソッドの指定がなく、Mockが持つ全てのメソッドに「10倍」という横断的処理がくっついて(束縛されて)ました。数字以外を返すメソッドではそもそもエラーになります。これでは使い物になりません。

可能性

しかし同時に、この失敗でやっとAOPの本当の力に気がつくことができました。つまり無指定で全てのメソッドに横断的処理が束縛されるということは、指定した特定メソッドに同時に横断的処理を束縛できるということです。delete*で始まるメソッドには全てログを、admin/で始まるパスでは認証チェックを、などといった横断的処理の束縛がアプリケーション実行コンテキストによって指定条件を決めることができます。1

Ray.Di

AOPがメソッドの呼び出しと呼ばれるメソッドとの関係を規定するものだとすれば、DIはオブエクトとオブジェクトの関係を規定するものです。BEAR.Saturdayの開発/運用経験を通じてオブジェクト間の関係性をオブジェクト自身が解決しないことの有用性は大きく認識してたので、DIフレームワークの導入というのは最優先事項でした。BEAR.SaturdayのDIで多いに参考にしてたのはSolarだったのですが2 今回最も良い設計/実装と思えたのはGoogleのDIフレームワークGuiceでした。それを普通に移植するのではなく、Solarの後継のAura、そのAura.Diをforkして、拡張することにしました。

こんなものが移植できるのか3 甚だ疑問で難しいのではないかと思ったのですが、AOPと共に機能するアノテーションベースで依存ポイントを指定し抽象と具象の接続指定でオブジェクトを構成するその設計と指向は、チャレンジに充分すぎるほどのものではないかと感じながら移植を開始しました。

実装、パフォーマンス、デバック等困難な事も多かったのですが、現在のBEAR.Sundayでかなりヘビーに使えていて今回1.0として長くつけてたbetaを外しました。これでcomposer.jsonで@devや@beta指定する必要がなくなります。

Thx

@madapaja さん @akkie さんには有用なアドバイスをもらい、GitHubもPRもしてもらいました。特に@madapaja さんはブログ記事かいてもらったり、スライドで発表してもらったりしました。また@jingu君にはRoboGuiceとの比較を教えてもらって、Guiceを使った事もない自分には大変助かりました。@hidenorigotoさんにはWeb+DBで「たとえばSymfonyのDIコンポーネントと比較すると、DIの構成と利用の分離の点で一歩進んでます」との賛辞で紹介していただきました。@vectorxenonさんにはCakePHPでの利用してもらいました。

みなさん、ありがとうございます。これからもよろしくお願いします。

  1. 現在BEAR.Sundayのsandoxアプリでは、”テスト”ではスタブデータを、”開発”では全てのin/outを記録するようになっています。 []
  2. 他のPHPフレームワークではほとんどDIが使われていませんでした []
  3. 当時とても大きいものだと誤解してました []