FreeeUtilというFreee のAPIを操作するためのPHPライブラリを開発しています。現在は開発途中で徐々にいろいろなAPIを実行できるようにしていく予定です。そのライブラリを作る際に今回用いた実装作戦を紹介します。

Guzzleに依存

FreeeのAPIを実行するためにHTTP通信を行うライブラリ”Guzzle“を利用することにしました。Guzzleを利用して通信するので、普通に作るとこんな感じになるかなと思います。

この場合、クラスはGuzzleに依存することとなります。このメソッドで処理としては正しく動作するのですが困ったことに、テストするには必ずFreeeのAPIを実行しなければいけなくなります。

APIを実行せずにテストしたい

Guzzleではテスト用にモックハンドラーを設定することができます。モックを設定したGuzzleオブジェクトはAPI通信せずにモックに設定した結果を返すようになります。これを使えばAPI通信せずにテストができます。が、上記の実装だとクラスにGuzzleのCLientが密結合しているため、モックハンドラーを設定することができません。そこで、依存性の注入。いわゆるDIを活用します。

オブジェクト生成時にClientを注入する、コンストラクタインジェクションを利用して、依存するClientを外から注入します。これで、注入する前にモックハンドラーを設定すればAPI通信せずにテストができます。

Guzzleを意識させたくない

さて、コンストラクタインジェクションでGuzzleを外から注入し、テストがしやすくなりました。が、ここでちょっとした問題が発生します。このクラスを使うユーザ視点で見ると、ユーザは必ずGuzzleオブジェクトを用意しなければなりません。せっかくのライブラリ。依存をユーザ側に意識させたくありません。そこで今回はファクトリメソッドを用意しました。

これで、ユーザ側はGuzzleオブジェクトを意識せずにFreeeのAPIクライアントを取得できます。

APIごとにメソッド用意するのはしんどい

さて、これでGuzzleを外から注入しつつもユーザ側はそれを意識せずにFreeeのAPIクライアントを取得できるようになりました。が、APIごとにこのメソッドを用意するのはいささかしんどいです。そこでAPIクライアントごとにキーを用意し、そのキーで判断させるようにしました。そのまま作るとcreateメソッドが肥大してしまうのでResolverにしました。

FreeeAPIクラスにsupports()メソッドを用意し、そこで指定されたキーの場合にtrueを返すようにしました。ResolverクラスでFreeeApiクラスのリスト格納場所を用意し、resolve()メソッドでそれぞれのキーと一致するか調べ、一致した場合にクラス名を返します。(本来ならオブジェクトを返すのがベターですが、今回はクラス名にしました。)

FactoryのコンストラクタでResolverオブジェクトを作成して、FreeeApiクラスのリストをResolverに追加していきます。あとはcreate()メソッドでresolve()メソッドを実行してクラス名を取得し、それを利用してオブジェクトを生成します。

という感じで、個人的には今回ちゃんとしたクラス設計のもと、ライブラリを作成できています。ちょっとまだ納得いかない部分がありますが、そこは徐々に調整していけたらいいなと思います。

このような考え方を教えてくれたイベントがまもなく開催!

今回のような考え方で作るようになったのもひとえにPHPカンファレンスなどのPHPer系イベントに参加したのが要因だと考えています。個人で作るライブラリはもちろんのことお仕事にもカンファレンスで得た知識が大変役立っています。そんなPHPer系イベントであるPHPカンファレンス福岡 2019がまもなく開催です。そして引き続き、北海道沖縄東京とPHPerがたくさん集まるイベントが盛りだくさんです。ぜひぜひそちらに足を運んでいただけたらなと思います!

投稿者: Ippei Sumida

フリーランスデベロッパー。大阪を中心にWeb開発をしています。