1

APIのXML応答を構築するライブラリを構築しようとしています。私の問題を説明するために、ここに2つのサンプルAPI応答があります。1つ目はメニューを表示するためのもので、2つ目はテキストを表示するためのものです。

<CiscoIPPhoneMenu>
  <Title>Title text goes here</Title>
  <Prompt>Prompt text goes here</Prompt>
  <MenuItem>
   <Name>The name of each menu item</Name>
   <URL>The URL associated with the menu item</URL>
  </MenuItem>
  <SoftKeyItem>
   <Name>Name of soft key</Name>
   <URL>URL or URI of soft key</URL>
   <Position>Position information of the soft key</Position>
  </SoftKeyItem>
</CiscoIPPhoneMenu>

..。

<CiscoIPPhoneText>
  <Title>Title text goes here</Title>
  <Prompt>The prompt text goes here</Prompt>
  <Text>The text to be displayed as the message body goes here</Text>
  <SoftKeyItem>
   <Name>Name of soft key</Name>
   <URL>URL or URI of soft key</URL>
   <Position>Position information of the soft key</Position>
  <SoftKeyItem>
</CiscoIPPhoneText>

さて、私のモジュールのアウトラインは次のようになります。

class CiscoIPPhone(object): 
    def __init__(self, title=None, prompt=None):
        self.title = title
        self.prompt = prompt

class MenuItem(object):
    def __init__(self, name, url):
        self.name = name
        self.url = url

class CiscoIPPhoneMenu(CiscoIPPhone):
    def __init__(self, *args, **kwargs):
        super(CiscoIPPhoneMenu, self).__init__(*args, **kwargs)
        self.items = []

    def add_menu(self, name, url):
        self.items.append(MenuItem(name, url))

注:読みやすくするために、これらのクラスが処理する検証とサニタイズを削除しました。

だから私の質問は:

  1. 私は実際にこれらのオブジェクトのシリアル化された表現を出力していますが、これは間違っているか悪い習慣と見なされていますか?
  2. この種のAPIインターフェースクラスを説明するデザインパターンはありますか?
  3. 似たようなことをするエレガントに書かれた(Pythonic)Pythonライブラリはありますか?(私は、Djangoのモデルシリアル化の簡略版、またはDjango-Tastypieのように考えています)。
4

1 に答える 1

1

残念ながら、Python 側についてコメントすることはできません。

個人的には、このデザインは非常に受け入れやすいと思います。

これらのメッセージがシリアライズおよびデシリアライズされる場所が 1 つあります。これらのクラスを使用するドメイン コードは、クラスを作成し、必要なデータを入力して、それ (またはシリアル化された表現) を別のコンポーネントに渡します。実際のシリアル化が発生すると、クラス自体がすべての必須データが設定されているかどうかを確認します。

クラスはテストに適しています。メッセージを作成し、いくつかの値を入力し、XML でシリアル化されたバージョンを確認するだけです。テストは、期待値と実際の出力の両方をスキーマチェックします。これらのテストは、プロトコル全体の仕様です。

この設計は、流暢な APIに適しています。

new CiscoIPPhoneMenu()
    .withTitle("Title text goes here")
    .withPrompt("Prompt text goes here")
    ...

参照目的で、Martin Reddy はC++ の API 設計で、プロトコルまたはファイル形式について、シリアル化された表現との間で変換する 1 つのコンポーネントを持つことを述べています。これがまさにこれらのクラスの目的だと思います。

シリアル化された表現が変更された場合 (XML 形式からバイナリ形式など)、形式を受け入れる 2 番目の ctor を提供するか、その変化を予期してSerializationFormat列挙型を導入するなどして、簡単に表現を切り替えることができます。

XML スキーマ ComplexType を受け取り、それに対応する Python クラスを生成する Python モジュールを簡単に想像できます。Altova XML Spy を使用して C# でこれらのクラスを生成しようとしたことがあります。ただし、これにはランタイム DLL の参照が含まれており、このためだけに別の DLL を使用するとオーバーヘッドが大きすぎるように思われました。これは基本的に、XML スキーマ ComplexType が外部 DSL で定義され、シリアライゼーション形式がバイナリ形式であるprotobufの動作方法です。

于 2012-05-08T20:54:54.237 に答える