PoEAA ch18 Gateway

PoEAAデザインパターン勉強メモ

出典: 


Gateway

20190521000324

An object that encapsulates access to an external system or resource.

  • OOシステムはオブジェクトではない外部リソースを取り扱わねばならないことがある

    • DBテーブル
    • CICSトランザクション
    • XMLデータ構造
  • 外部リソースはそれ専用のAPIをもつ

    • RDB: JDBC,SQL
    • XML: W3C, JDOM
  • そのまま使うのはよくない

    • プログラムを理解しづらくなる
    • 将来RDBをXMLに置換できなくなる
  • オブジェクトでラップしろ

How It Works

  • やることは至ってシンプルなラッピング
  • 用途を満たすシンプルなAPI(=メソッドとか)を定義し、外部リソースの操作にマッピングする
  • GatewayService Stubのよい適用場所でもある

    • 後述
  • Service Stubを適用しやすい設計にするのは重要なこと

    • テスト容易性
  • Gatewayはシンプルに保て

    • 一番大事な役割は…

      • 外部リソースのラッピング・クライアントコードの要求への適合
      • スタブの適用箇所の提供
    • これらを満足できる程度の最小のものであるべき
    • 複雑なロジックはクライアントコードに任せろ
  • コード自動生成を使うのは良いアイデア

      • リレーショナルメタデータからRDBゲートウェイ
      • XMLスキーマやDTDからXMLゲートウェイ
    • 生成されるGatewayは賢くない(dumb)が、うまくいく

      • 複雑な操作は他のオブジェクトに任せればいい
  • 2つ以上のオブジェクトでGatewayを作るのもよい

    • バックエンドとフロントエンド

      • バックエンド: ミニマルなラッパ
      • フロントエンド: バックエンドを叩き、シンプルなAPIを提供する

        • 【補】GoFのFacade Pattern
    • 外部サービスのラッピングと、クライアントコードの要求への適合が相応に複雑ならば良い
    • 単純なら分けるほどではない

When to Use It

  • 外部のもの感があり、インタフェースがぎこちない(OOPと合わない)ものがあればGateway適用を検討せよ

    • ぎこちなさをシステム全体に波及させるよりも、Gatewayで閉じ込める
    • Gatewayで包むデメリットはまずない
    • クライアントコード読みやすくなる
  • Gatewayを導入するとテストが容易になる

    • Service Stubsの明確な適用箇所
    • 外部リソースのインタフェースがGatewayで包むまでもなくOOPに適合していても、
      Service Stubの適用のためにGatewayで包むのは有用
  • Gatewayでを導入すると置換可能になる

    • 【補】クライアントコードをinterfaceに依存させれば、特定の実装には依存しなくなる
    • テスト用Gatewayへの置換も可能(後述)
![20190521000426](../../../imgs/20190521000426.png)
別の外部サービスに置換可能
  • Mapperという別の選択肢

    • 外部リソースとの結合を切り離す
    • Gatewayよりも複雑

      • クライアントと外部リソースを互いにignorantにするため
![20190521000451](../../../imgs/20190521000451.png)
Mapper
  • これって改めてデザインパターンとして挙げるほどのものか?

    • GoFのなにがしかと同じじゃないの?
    • 下記の理由につき区別した

      • Facadeとの違い

        • Facade

          • 複雑なAPIの単純化
          • 汎用
          • 異なるインタフェースが裏にあることを示唆
        • Gateway

          • 特定用途
          • 外部リソースのAPIへの単なるマッピングだったりする
          • 置換やテストを旨とする
      • Adapterとの違い

        • Adapter

          • 既存のインタフェースに寄せるやつ
        • Gateway

          • 既存のインタフェースは(普通)ない
          • Adapterパターンをとることもある

            • GatewayインタフェースがAdapterのインタフェース(Target)
            • 外部リソースの実装を包むのがAdapter
            • 外部リソースがAdaptee
          • この場合adapterはGatewayの実装の一部
      • Mediatorとの違い

        • Mediator

          • 各クラスはMediatorを知っている
        • Gateway

          • Gatewayに包まれる外部リソースはGatewayのことを知らない
      • 【疑問】Bridgeパターンとはどう違うの

        • 既存のインタフェースはないが、様々な実装ありきでインタフェースを作る点がそっくり
        • Bridgeパターンは「種類の継承ツリーと実装の継承ツリーとを分離する」ことを旨とするから違うのかな
        • Facade, Adapter, Mediatorよりは似てると思う

Example: A Gateway to a Proprietary Messaging Service (Java)

  • コード略(pp.468-472)
  • Gatewayのインタフェースについて

    • send('CNFRM', [1, 10, 'hoge'])

      • 汎用
    • sendConfirmation(1, 10, 'hoge')

      • 特定用途
    • 良し悪し

      • 汎用インタフェース

        • 引数の正当性が静的にわからない

          • typoでエラー出たりしそう
      • 特定用途インタフェース

        • 包んでいる外部リソースに追加変更があるたびにGatewayクラスに変更が生じる

          • 実装の単純なマッピングじゃないから
          • 自動生成じゃないから
    • 両方あるとよい
  • 戻り値から例外へのマッピング

    • exit 0: 正常終了
    • ほか: 異常終了
  • Gatewayのスタブ

    • テスト用protectedメソッドを生やしておく

      • 外部リソースの操作を単に包むだけのやつ

        • 特定用途のためのシグネチャとか持たない
        • 戻り値の例外へのマッピングもしない
    • 本メソッドをオーバライドして、外部サービスへのアクセスをモックする

      • 【補】サービス自体のスタブを作るわけではない
  • もう一つのテスト方法: Service Stub

    • 外部サービス自体のスタブを作る

      • 【補】JSON Serverとか
    • スタブの開発作業が困難でなければうまくいく
  • GatewayのスタブとServiceのスタブを併用するのもよい

    • Gatewayのスタブ: クライアントコードのテスト用
    • Serviceのスタブ: Gatewayのテスト用
  • Pluginパターンを併用することで、本物とスタブの選択をconfiguration timeまで遅延できる
![20190521000648](../../../imgs/20190521000648.png)
本物のGatewayを継承してテスト用Gatewayを作る(interface切ったほうが行儀いいと思う)
![20190521000703](../../../imgs/20190521000703.png)
Serivce Stub ... サービスのスタブでGatewayをテスト

英語

  • do the trick

    • うまくいく
  • ludicrous

    • ばかばかしい
  • laudable

    • 称賛に値する