Laravelのファサードが全然わからなかったので自分なりに色々と調べた事

# はじめに
Laravelを使い始めて１年ぐらいが経ちました。とはいえ仕事の50%はWordPress案件で、Laravelは5%ぐらいしか使えていません。
堂々と「Laravelで開発やってるよ！」と言えないレベルで、Laravelの大きなポイントの一つであるファサードの事を全然理解していなかったので色々調べました。
これからLaravelを学ぶ人たちのためになれば幸いです。

# ファサードがわからない
Laravelを始めて触ってから１年以上経っていますが、今までファサードのこと分かっていませんでした。
知り合いなどから「Laravel使ってんの？やっぱファサード便利だよね」とか言われても利便性などをわかっていませんでした。
そんなファサードのことを知らない素人だったんですが、なんとか小さいシステムは組めていましたし、なんとかなってきました。
ですがが最近、ちょっと大きめの案件でユニットテストを書こうとした時に壁に当たりました。
ユニットテストを通す際にはモックを行いまずが、その際のモックの通し方がわからず困りました。
検索に検索を重ねてようやくファサードのことがわかり、ユニットテストを書くことができました。

# 意味
「ファサード」（英: facade）
あまり聞きなれない言葉ですがフランス語、イタリア語からの借用語で、「建物の表面」、とりわけ「正面」という意味で使われます。
語源はラテン語のfacies（英: face）（直面する、顔）が転じたものです。
[facade - Wiktionary](https://en.wiktionary.org/wiki/facade)

ファサードは元々は建築用語だったそうです。
> ファサード保存
> 歴史的建築物の保存方法として、ファサード保存が選択されることがある。これは、建築物の正面部分（時には正面の一部）だけを保存する方法で、都市における再開発と歴史的建造物の保存を両立させるための苦肉の策である。
<img width="206" alt="Screen Shot 2017-03-20 at 15.41.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/47327/682c4952-f396-3890-ac33-1f994abd8dc6.png">

[ファサード - Wikipedia](https://ja.wikipedia.org/wiki/ファサード)

この「建築物の正面部分だけを保存する方法で、都市における再開発と歴史的建造物の保存」というのはプログラミングで言うところの「リファクタリングと過去のコードの保存」に繋がる意味だと思います。

Laravelのファサードとは、建築用語での「建築物 の 正面部分」という意味が、プログラミングでの「ライブラリ（建築物）の呼び出し部分（正面部分）」という意味になるわけですね。

実際に使い方を見ていきましょう。

# 使われているファサード
実際にファサードを見てみます。

```php
use Illuminate\Support\Facades\Cache;

Route::get('/cache', function () {
    return Cache::get('key');
});
```
> https://laravel.com/docs/5.4/facades

上記のコードでは`Cache::get('key')`の部分がファサードになります。
名前から見るに`Cache::get('key');`は`key`という名前でキャッシュされた値を取得する、とわかります。
ですが実際にこの`Cache::get('key')`というのがどういった機構でキャッシュを提供しているかというのは明らかにしません。
もしかすると[memcached](http://php.net/manual/ja/book.memcache.php)かもしれませんし、[Redis](https://redis.io/)かもしれません。はたまた[APC](http://php.net/manual/ja/book.apc.php)を使っているかもしれません。
そういったバックエンド側をプログラマに明らかにしないままに機能を提供する、それが「ファサード」です。

バックエンド側を明らかにしたコードはどうなるでしょうか？
例としてmemcacheとAPCでのキャッシュ取得のコードを見てみます。

```php
$memcache_obj = new Memcache;
$memcache_obj->connect('memcache_host', 11211);
$var = $memcache_obj->get('some_key');
```
> http://php.net/manual/ja/memcache.get.php

```php
$bar = 'BAR';
apc_store('foo', $bar);
var_dump(apc_fetch('foo'));
```
> http://php.net/manual/ja/function.apc-fetch.php

memcacheではオブジェクト指向のコードが、一方のAPCでは関数のコードになっています。
memcacheでは[`get`](http://php.net/manual/ja/memcache.get.php)、APCでは[`fetch`](http://php.net/manual/ja/function.apc-fetch.php)という名前が付いています。それぞれの関数名を覚えていないと大変ですね。
またもしプロジェクトの途中で「memcacheからAPCへ変更」といったことが起こった場合には置換だけでは動きません。

そういった違いを吸収してくれるのがファサードです。

# デザインパターンとファサード
元々「ファサード」という言葉はGoFのデザインパターンで紹介されていました。

> Facadeクラスはあくまでサブシステム内部に仕事を投げるだけで複雑な実装は持たない。
> 多様な機能の塊であるサブシステムから、サブシステムを利用するユーザーの用途に合わせた窓口(インターフェース)を提供するだけである。
> <img width="546" alt="Screen Shot 2017-03-20 at 15.45.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/47327/a6fd7350-e650-9097-9ca5-f31f4fad6928.png">
> [Facadeパターン - Wikipedia](https://ja.wikipedia.org/wiki/Facade_パターン)

> サブシステム内に存在する複数のインタフェースに1つの統一インタフェースを与える。
> [Facade - Strategic Choice](http://d.hatena.ne.jp/asakichy/20090314/1237030727)


# 用意されたファサード
Laravelでは標準で37種類のファサードが提供されています。
その中から使う機会のありそうなファサードについて列挙します。

| Facade | 使い方 |
|:---:|:----|
| Cache | キャッシュを提供する。`config/cache.php`で設定可能。 |
| Config | config/app.phpの値を取得したりする。 |
| DB | クエリビルダなどを提供。ファサードじゃない書き方もよくあるようです。 |
| File | ファイル操作。 |
| Log | ログの書き出しなど。storage/logsなどに書き出せるのでデバッグなどで重宝します。syslogも可能。 |
| Request | $_REQUEST周りの処理。Laravel5からはInputファサードの代わりにこちらを使った方が良いそうです。 |
| Response | ブラウザへの返答の制御。ヘッダー関連の処理全般、CORSなどが制御できます。 |
| Route | ルーティングをするならコレ。Laravelで最初に目にするファサードかも。 |
| Storage | ファイルの保存など。 |
> [Facade Class Reference - Laravel](https://laravel.com/docs/5.4/facades#facade-class-reference)


Laravelを使ってまず最初に使うのは`Route`ファサードでしょうか。


Laravelを始めた頃は「こうやって書くのがお作法なんだな」ぐらいにしか思っていなくて、ファサードということを意識してなかったですね

# テスト、モック、ファサード
ここまでファサードの利点は「バックエンド側を意識せずコードを書くことができる」と述べてきました。
例えば`Cache`ファサードであればmemcacheかAPCか意識せず、それぞれのメソッド名を知らなくとも使うことができるし、切り替えも容易ということでした。
この「バックエンドを意識しない」ファサードが（ユニット）テストで非常に強力な存在になります。

# DI
コードのテストを書くことは素晴らしいですが、大変なこともあります。
その一つが依存性注入です。
テスト側から見たコードの深いところ、ての及ばないライブラリでの動作をモックする場合には引数にモックしたい値を渡す依存性注入が必要になります。
`A()` => `B()` => `C()` と順に関数を呼ぶプログラムで具体的に見てみます。

```php:依存したメソッド呼び出しの例
Class Hoge{
  public static function A() { return self::B(); }
  public static function B() { return self::C(); }
  public static function C() { $fuga = new Fuga('hoge'); return $fuga->toString() ; }
}

echo Hoge::A(); // 'hoge'
```

この`Hoge::A()`メソッドをテストする場合に`Fuga`クラスに依存しています。
この依存している`Fuga`クラスのインスタンス`$fuga`をモックしたい場合、依存性を注入する必要があります。
引数での依存性を行います。


```php:DIを使った例
Class Hoge {
  public static function A(Fuga $fuga) { return self::B($fuga); }
  public static function B(Fuga $fuga) { return self::C($fuga); }
  public static function C(Fuga $fuga) { return $fuga->toString() ; }
}

$fuga = new Fuga('injection!');
echo Hoge::A($fuga); // injection!
```

これで`Hoge::C();`は外側で定義されたFugaのインスタンスで実行することができるようになりました。
ですが大変です。
これを簡単にするのがファサードを使ったモックです。


```php:ファサード（っぽいもの）を使った例
Class Hoge {
  public static function A() { return self::B(); }
  public static function B() { return self::C(); }
  public static function C() { Fuga::toString('hoge'); }
}

Fuga::shouldReceive('toString')->andReturn('injection!');
echo Hoge::A(); // injection!
```

上記の例では `Fuga`クラスの静的メソッド、`shouldReceive()`を呼び出し、その後で`andReturn()`を呼んでいます。
こうすることで `Fuga::toString('hoge');`の戻り値が`andReturn()`の引数である`injection!`に置き換わっています。

こうすることで、呼び出しの外側から依存された内部の動作を変更することができます。
テストでは非常に便利ですね！

# 実際のモック
上記の例では仮想のFugaというクラスを使ってLaravelとは無関係の操作を行っていました。
Laravelで実際にファサードをモックさせて動かしてみます。
通常の作成では`test/*`などに置くコードですが、動作テストコードとして認識しやすいようweb.phpファイルだけで完結させています。

まずはモックをせず`Cache`を使うコードです。

```php:web.php
Route::get('/cache_test1', function() {
  Cache::put('key', 'cached value', 300);
  echo Cache::get('key'); // cached value と表示される
});
```
echo文のところで`cached value`と表示されるコードです。

このキャッシュをモックを使って呼び出します。

```php:web.php
Route::get('/cache_test2', function() {
  Cache::put('key', 'cached value', 300);

  Cache::shouldReceive('get')
    ->andReturn('mocked value');
  echo Cache::get('key'); // mocked value と表示される
});
```

これで`Cache::get('key')`がモックされました。
`Cache::shouldReceive('get')->andReturn('mocked value');`と書くことで`get`メソッドの戻り値が`mocked value`となります。

このモックはどこからでも定義することができるので、ユニットテスト内部を簡単にモックすることができます。便利ですね！


# ファサードのオプション
これでファサードをモックして呼び出すことができました。
Laravelのファサードのモックは[Mockery](http://docs.mockery.io/en/latest/)というライブラリを使っています。
サンプルコードの例をコメントで追ってみます。

```php:web.php
Route::get('/cache_test3', function() {
  Cache::shouldReceive('get') // getメソッドをモックする
    ->with('key') // 引数がkeyのとき
    ->once() // 一度だけ呼び出されます
    ->andReturn('value') // 戻り値です

  echo Cache::get('key');  // ここで value と表示される。
});
```

このように、Mockeryでは期待値条件（Expectation Declarations）と呼ばれるメソッドをメソッドチェインで列挙します。
この期待値条件を定義することでモックの動作を決めていきます。

LaravelのMockeryでは決まった多いですが、Mockeryの期待値条件の書き方について抜粋します。

最初に書かれる期待値条件はShouldReceiveです。呼び出し方にいくつかの種類があります。

| ShouldReceive | 使い方 |
|:---|:----|
| shouldReceive(method_name) | メソッド名を文字列で与えます |
| shouldReceive(method1, method2, ...) | 複数のメソッド名に合致させます。 |
| shouldReceive(array('method1'=>1, 'method2'=>2, ...)) | メソッド名と戻り値までを配列で定義します。|

withで引数を定義します。

| with | 使い方 |
|:---|:----|
| with(arg1, arg2, ...) | 引数を提示します。可変長引数です。|
| withArgs(array(arg1, arg2, ...)) | 可変長引数ではなく配列で与えることもできます。|
| withNoArgs() | 引数なしのみが合致します。 |
| withAnyArgs() | デフォルトの動作で、どんな引数でも合致します。 |

回数の制御です。指定した回数分だけモックします。

| 回数 | 使い方 |
|:---|:----|
| once() | 一度だけです。 |
| twice() | 二回までです。 |
| times(n) | n回までです。 | 
| atLeast() | times(n)と組み合わせて、最低何回は呼ばれる、と定義します。 |
| between(min, max) | 回数制限の範囲です。 |


戻り値の制御です。

| return | 使い方 |
|:---|:----|
| andReturn(value) | 戻り値。オブジェクトもいけます。 |
| andReturn(value1, value2, ...) | 複数回数呼ばれる場合の定義 |
| andReturnValues(array) | こちらも複数回呼ばれる場合に定義します |
| andReturnNull() | NULLを返します |
| andThrow(Exception) | 例外を返します。|
| andThrow(exception_name, message) | 例外を返す場合の別の書き方です。 |
| andSet(name, value1) | 値を返す代わりにモックオブジェクトのpublic変数にセットを行います |

[Expectation Declarations](http://docs.mockery.io/en/latest/reference/expectations.html)
[Mockeryのドキュメントを翻訳された方](https://kore1server.com/202/Mockery+0.8.0+日本語ドキュメント)

Mockeryだけでも色々な使い方ができそうですね。
`shouldReceive()->with()->andReturn()`という書き方が多いかなと思います。
配列を使った複数の戻り値を順に定義する使い方も便利ですので、覚えておくと良いかなと思います。

```php:web.php(複数回呼び出しのモックサンプル)
Route::get('/cache_test4', function() {
	$returns  = [
		'1st mocked value',
		'2nd mocked value',
		'3rd mocked value',
	];
	Cache::shouldReceive('get')
		->times(count($returns))
		->andReturnValues($returns);
	echo Cache::get('key'); // 1st mocked value と表示される
	echo Cache::get('key'); // 2nd mocked value と表示される
	echo Cache::get('key'); // 3rd mocked value と表示される
	// echo Cache::get('key'); // ここはエラー
});
```

# OSI基本参照モデルとDI、ファサード
ちょっと他の話を。
現在僕はプログラマとしてコーディングしていますが、元々プログラミングはあまり得意ではなく（今でも！）、ネットワークエンジニアになりたいと思っていました。
ネットワークエンジニアになるための勉強をしていた時期があり、ネットワーク分野に似ている印象を受けました。
それはネットワーク分野の「OSI基本参照モデル」です。
> <img width="419" alt="Screen Shot 2017-03-20 at 15.55.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/47327/766dab2a-c0b8-6d99-b96f-a7f525c5ad9c.png">
> [OSI参照モデル](https://ja.wikipedia.org/wiki/OSI%E5%8F%82%E7%85%A7%E3%83%A2%E3%83%87%E3%83%AB)

「OSI基本参照モデル」とはネットワーク通信のプロトコルスタックを定めたものです。
それぞれのレイヤ（層）でどんな通信を行うかという取り決め（プロトコル）を定めています。
現在のインターネット通信ではTCP/IPプロトコルスイートが（ほぼ）標準になっていますが、本来はそれぞれのレイヤで具体的なプロトコルを定めて良いものです。
この抽象化された「OSI基本参照モデル」のレイヤ定義は、Laravelのファサードに似ているなぁ、という印象を受けました。
とは言え、抽象化と具現化というのはプログラミングではよく出てくる概念なので、ファサードとOSI基本参照モデルに限った話ではないかもしれないですね。


# 自作ファサード
ここまで使ってきたファサード（サービスプロバイダ）は自作することもできます。

ファサードの作り方は以下の通りになります。

> 1. クラスを作成
> 2. サービスプロバイダーを作成
> 3. サービスプロバイダーの設定
> 4. ファサードクラスを作成
> 5. ファサードを使ってみる
> 6. ファサードエリアスの設定
>
>  [ファーサードの作成 - ララ帳](https://laravel10.wordpress.com/2015/04/27/%E3%83%95%E3%82%A1%E3%82%B5%E3%83%BC%E3%83%89/)


コード自体は単純なのですが、ファサードの自作を行うには手順が多く大変そうです。
またファサードは非常に便利で融通がきくため、設計を誤ると後の実装に響きそうです。

僕もHTTP通信のライブラリでファサードを使いたい機会がありました。
自作も検討しましたが検索したところファサード（サービスプロバイダ）が公開されていました。そういった公開されたファサードを使うというのが便利かもしれません。
> [laravel-guzzle-provider ](http://packalyst.com/packages/package/kozz/laravel-guzzle-provider)

ファサードに慣れてきたら自作を検討したいですね。

# まとめ
以上、ファサードについて自分なりにまとめてみました。
当初は聞き慣れない言葉だったので使い方も概念もわからなかったですが、単語を調べることでかなり理解が進んだ気がします。
また実際にモックできるようになるとテストを書きやすくなり、テストが楽しくなりました。モックがキマると気分爽快ですね :)

# お礼
今回の記事を書くにあたって、@naname さんにファサードのことを教えてもらい、記事の監査してもらいました。ありがとうございました😃

# 参考サイト
[Laravel コードで見るファサードクラスの仕組み](http://www.1x1.jp/blog/2014/03/laravel-facade-class.html)
[Laravel 5.4 ファサード](https://readouble.com/laravel/5.4/ja/facades.html)
[Laravel ファサードを利用しないメリット](http://ytake.hateblo.jp/entry/2015/12/16/011812)
[LaravelのDIの挙動を勘違いしていてドハマリした件](http://qiita.com/ak-ymst/items/00e7d3cee16ba6d3e710#%E3%81%A9%E3%81%86%E3%81%99%E3%82%8C%E3%81%B0%E3%81%84%E3%81%84%E3%81%AE%E3%81%8B-%E3%81%9D%E3%81%AE2-%E3%83%95%E3%82%A1%E3%82%B5%E3%83%BC%E3%83%89%E3%82%92%E4%BD%BF%E3%81%86)
[laravel5.2 自作Facadeを作る](http://blog.booklook.jp/program/laravel5-2-%E8%87%AA%E4%BD%9Cfacade%E3%82%92%E4%BD%9C%E3%82%8B/)