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系イベントに参加したのが要因だと考えています。個人で作るライブラリはもちろんのことお仕事にもカンファレンスで得た知識が大変役立っています。2019がまもなく開催です。PHPerがたくさん集まるイベントが盛りだくさんです。Sumidaフリーランスデベロッパー。大阪を中心にWeb開発をしています。#3『ひらパーに行ってブログを書く会』開催しました。Unplat検索する。