ゲートウェイ(Gateway)パターン(PofEAA)

参考書籍一覧(Amazon アソシエイトリンク)

外部システムまたはリソースへのアクセスをカプセル化するオブジェクト。

エンタープライズアプリケーションアーキテクチャパターン 第18章 ベースパターン 18.1 ゲートウェイ

FacadeパターンAdapterパターンに近いパターンではあるが、主な責務は外部リソースへのアクセスとそれをラップするインターフェースを構築することである。

マイクロサービスで他サービスへの通信手段として構築するのが、典型的な適用例だろう。

require 'open-uri'
require 'json'

class AnotherServiceGateway
  SERVICE_URL = '...'.freeze

  def find_user(id)
    get("/users/#{id}")
  end

  def get(path)
    JSON.parse(get_request(path))
  end

  def get_request(path)
    open(SERVICE_URL + path)
  end
end

上記はREST APIサービスのケースだが、メッセージベースのサービスでも同様に実装すれば良い。

サービススタブ(ServiceStub)パターンと組み合わせることで、テストを容易に実行できるようになる。どのように実際のクラスとサービススタブを入れ替えるかは色々なやり方があると思うが、RailsでRspecを用いているケースの参考例を示しておく。

# spec/rails_helper.rb
# 最終行に以下を追加
Dir[Rails.root.join('spec/spec_helpers/stubs/*.rb')]

# spec/spec_helpers/stubs/another_service_gateway.rb
# オープンクラスで上書き
class AnotherServiceGateway
  def self.get_request_return=(value)
    @get_request_return = value
  end

  def self.get_request_return
    @get_request_return
  end

  # 差し替えの値が指定されていなければ元の挙動にする
  # 元の挙動をするか切り替えるフラグを用意しても良い
  alias_method :super_get_request, :get_request
  def get_request(path)
    value = self.class.get_request_return
    return super_get_request(path) if value.nil?

    value.to_json
  end
end

# 適当なspecファイルの中
Rspec.describe '...' do
  before { AnotherServiceGatewayStub.get_result_return = {id: 1, name: '山田太郎' } }
end