よく使うJavaライブラリで味わうデザインパターン - Facadeパターン

普段よく使うJavaライブラリにも、GoFのデザインパターンが隠されています。日々の作業が忙しく見逃しがちですが、たまにはじっくり一種の芸術ともいえる美しい設計を味わってみましょう。


## 今回の芸術

```java
import org.apache.http.client.fluent.Request;
import java.io.IOException;
...

String html = null;
try {
    html = Request.Get("http://www.qualysite.co.jp/")
        .connectTimeout(1000)
        .socketTimeout(1000)
        .execute()
        .returnContent()
        .asString();
} catch (IOException e) {
  ...
}
```

引数で指定したURLのソース（HTML）を取得するシーンですが、あらためて鑑賞してみると、直感的に伝わってくるインターフェイスの美しさにうっとりしてしまいます。


## 鑑賞のポイント

流れるようなインターフェイスに目が行きがちですが、設計者に言わせると「あんなの飾りです。偉い人にはそれがわからんのですよ[^1]」という答えが返ってきそうです。ここでの鑑賞ポイントは、何かとステップが多いHTTPの接続ルーティーンを、わかりやすく、シンプルにまとめた機能美です。以下で一緒に味わっていきましょう。


## Facadeパターンを使わない場合

冒頭のコードは、Javaで最も有名だと思われるHTTPクライアント[Apache HttpComponents HttpClient](https://hc.apache.org/)の使用例です。このライブラリには、2013年にリリースされたバージョン4.3で、冒頭のようなインターフェイスが追加されました。

それ以前は、同じ結果を得るのに以下のような、ステップが多いコードを記述する必要がありました。

```java
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
...

String html = null;

CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet("http://www.qualysite.co.jp/");

// Requestの設定
RequestConfig requestConfig = RequestConfig.custom()
    .setSocketTimeout(1000)
    .setConnectTimeout(1000)
    .build();
httpGet.setConfig(requestConfig);

CloseableHttpResponse response = null;
try {
  response = httpClient.execute(httpGet);

  // Content取得(EntityオブジェクトがContentを保持している)
  HttpEntity entity = response.getEntity();

  // Contentからソース取得
  html = EntityUtils.toString(entity, StandardCharsets.UTF_8);

  // Entity消費
  EntityUtils.consume(entity);
} catch(IOException e) {
  ...
} finally {
  try {
    if (response != null) {
      // Responseクローズ
      response.close();
    }
  } catch (IOException e) {
    ...
  }
}
```

このようなコードでは、コーディングに手間がかかることは表面的な問題です。本当の問題は、コードを記述するときにミスが起きやすいことです。HTTP接続を開始してから終了するまで、**いくつものステップを順番に踏まないといけない**ことと、**必ず実行しなければいけないステップがどれなのかわかりにくい**ことは、ミスの原因になります。

具体的には、

```java
// Entity消費
EntityUtils.consume(entity); // 内部ではInputStreamを閉じている
```

や、

```java
// Responseクローズ
response.close(); // 内部ではHTTPコネクションを閉じている
```

は、ビルド時にも実行時にもエラーにならないので、内部の作りを理解していないと簡単に書き忘れてしまうでしょう。「Entityは消費（consume）しないといけない」とか、「Responseは閉じないといけない」というのは一般的ではありません。この書き忘れは、リソースリークを引き起こします。

また、`CloseableHttpClient`はCloseableインターフェイスを実装しているため、`httpClient.close();`という記述もできるのですが、このようにHttpClientをcloseするメソッドは呼ばなくても大丈夫なのでしょうか？　[公式のサンプルソース](https://hc.apache.org/httpcomponents-client-4.5.x/quickstart.html)では呼ばれていないので不要かと思いますが、不安になってしまいます。

低レベルでたくさんの機能を提供していて、数々のライブラリで使われているHttpClientですが、必然性がないケースでこのコードをそのまま使うのは美しいとは言えませんよね。


## Facadeパターンを使った場合

冒頭のコードはFacadeパターンが使われています。コメント付きでもう一度見てみましょう。

```java
import org.apache.http.client.fluent.Request;
import java.io.IOException;
...

String html = null;
try {
  html = Request.Get("http://www.qualysite.co.jp/")
    .connectTimeout(1000) // Requestの設定
    .socketTimeout(1000)  // Requestの設定
    .execute()
    .returnContent()      // Content取得 -> Reponseクローズ -> Entity消費
    .asString();          // Contentからソース取得
} catch (IOException e) {
  ...
}
```

注目すべきは、`Response#returnContent`メソッドです。このメソッドひとつで、Content取得 -> Reponseクローズ -> Entity消費という、複数のオブジェクトを使う処理で**必ず実行しなければいけないステップ**を、**順序通り**、**まとめて**処理できます。

このメソッドでは3つの処理を行っていますが、メソッドの名前が`returnContent`なのもポイントです。クラスの設計者は、ReponseクローズとEntity消費の処理をクラスの利用者に意識させたくなかったのでしょう。メソッドに含まれていないからです。ただ、さらに想像すると、`getContent`ではなく`returnContent`としているところが、「単にContentオブジェクトの参照を返すだけではないんだよ」という隠れたメッセージも見えてくるような気がします。

Facade（ファサード）は、「建物の正面」という意味です。Facadeパターンの目的は、利用者に建物の正面しか見せないようにすること、つまり複数のクラスのごちゃごちゃしたインターフェイスをまとめて、最小限だけ見せることです。どうりでインターフェイスがエレガントだと思っていましたが、それは、設計者によって計られた美しさだったのです。


## Facadeパターンへの専門家のコメント

多くの専門家からも、Facadeパターンを評価するコメントが寄せられています。（太字での強調は私がやりました。）

結城浩さん

> あるプログラマが「ああ、このクラスを呼ぶ前にはこっちを呼ぶんだよ。こっちのメソッドの呼び出し前には、このクラスに登録しておく必要があるんだぜ」といった話を「得意げ」に語るときには、Facade役を導入する必要があることを示唆しています。
> [『Java言語で学ぶデザインパターン入門』](https://www.amazon.co.jp/増補改訂版Java言語で学ぶデザインパターン入門-結城-浩/dp/4797327030/) より

lang_and_engineさん

>  **複数のクラスを呼び出す際**，呼び出す順番を思い出さなくてすむように，定石として１メソッド内に集約しておく。そのメソッドは，いわば複数のクラスの利用手順書になる。
> [GoFの23のデザインパターンを，Javaで活用するための一覧表](http://language-and-engineering.hatenablog.jp/entry/20120330/p1) より


## 最後に
わざわざ美術館に行かなくても、たった1行のコードを眺めるだけで知的な愉しみを味わうことができるのは、プログラマーの醍醐味でしょう。

Facadeパターンの芸術性に共感してくださったエンジニアの方は、ぜひ当社（[クオリサイトテクノロジーズ株式会社](http://www.qualysite.co.jp/)）の採用担当までご連絡ください！


## 関連記事
#### インスタンスを作る
- [よく使うJavaライブラリで味わうデザインパターン - Factoryパターン](http://qiita.com/takuya-s/items/7ffebaee2a9db4310460)
- [よく使うJavaライブラリで味わうデザインパターン - Builderパターン](http://qiita.com/takuya-s/items/3c3415962a7568c637ed)
- [よく使うJavaライブラリで味わうデザインパターン - Abstract Factoryパターン](http://qiita.com/takuya-s/items/6b26410d8eb47a9410e4)

#### インターフェイスをシンプルにする
- よく使うJavaライブラリで味わうデザインパターン - Facadeパターン
- [よく使うJavaライブラリで味わうデザインパターン - Adapterパターン](http://qiita.com/takuya-s/items/45176b2bfc9fe07a9ce7)

#### 他のクラスに任せる
- [よく使うJavaライブラリで味わうデザインパターン - Template Methodパターン](http://qiita.com/takuya-s/items/8898e9bae34acada6480)
- [よく使うJavaライブラリで味わうデザインパターン - Strategyパターン](http://qiita.com/takuya-s/items/473699b5cb2d5329eed3)


## 参考URL
- [HttpClient Quick Start - Apache Software Foundation](https://hc.apache.org/httpcomponents-client-4.5.x/quickstart.html)
- [HttpClient Fluent API - Apache Software Foundation](https://hc.apache.org/httpcomponents-client-ga/tutorial/html/fluent.html)


[^1]: 機動戦士ガンダムに出てくる名言のひとつ。ジオングに脚がないことをシャアに尋ねられた整備兵は「あんなの飾りです。偉い人にはそれが分からんのですよ」と返した。（[ジオング](ttps://ja.wikipedia.org/wiki/ジオング) - Wikipedia）