1

Result私は、特定の基本情報、特に一意のIDをすべて提供する汎用タイプのsをポンプできるWebサービスAPIを使用しています。その一意のIDは、送信者によって定義される傾向がありますが、必須UUIDではありません。送信者は常に同じ人物であるとは限りません(ただし、IDはシステム全体で一意です)。

基本的に、APIはこれに沿ったものになります(Javaで記述されていますが、言語は無関係である必要があります)。ここでは、基本インターフェースのみが共通の詳細を表します。

interface Result
{
    String getId();
}

class Result1 implements Result
{
    public String getId() { return uniqueValueForInstance; }
    public OtherType1 getField1() { /* ... */ }
    public OtherType2 getField2() { /* ... */ }
}

class Result2 implements Result
{
    public String getId() { return uniqueValueForInstance; }
    public OtherType3 getField3() { /* ... */ }
}

Resultそれぞれのタイプが完全に異なる種類の情報を表す場合があることに注意することが重要です。他のsと相関できないものもあればResult、同じタイプであるかどうかに関係なく、相関できるものもあります(たとえば、Result1と相関できる可能性があるためResult2、その逆もありますが、ResultX異なる情報)。

現在、これらのいくつかを受け取り、可能な場合はそれらを相互に関連付けるシステムを実装しています。これにより、相互に関連付けられたもののコンテナであるResult別のオブジェクトが生成されます。Result

class ContainerResult implements Result
{
    public String getId() { return uniqueValueForInstance; }
    public Collection<Result> getResults() { return containedResultsList; }
    public OtherType4 getField4() { /* ... */ }
}

class IdContainerResult implements Result
{
    public String getId() { return uniqueValueForInstance; }
    public Collection<String> getIds() { return containedIdsList; }
    public OtherType4 getField4() { /* ... */ }
}

これらは2つのコンテナーであり、異なるユースケースを示します。最初の、ContainerResultは、相関関係のある詳細と実際の完全な相関関係のあるデータを誰かが受け取ることを可能にします。2番目の、IdContainerResultは、関連付けられたIDのみを送信することにより、帯域幅を優先して完全なリストを犠牲にします。相関を行うシステムは必ずしもクライアントと同じである必要はなく、クライアントはResultそれらのIDが表すを受け取ることができます。これは、IDを受け取るだけでシステム上で相関を示すことができるようにすることを目的としています。

さて、私の問題は一部の人には自明ではないかもしれませんし、他の人には自明かもしれません:の一部としてIDのみを送信する場合IdContainerResult、クライアントResultは、単一のIDストア?各実装によって実際に表されるデータのタイプは、Result相関できない場合に分離されるのに役立ちます。つまり、ほとんどの場合、メモリやストレージに負担をかけずに単一のIDストアを使用することはほとんどありません。

私たちが思いついた現在のソリューションでは、新しいタイプのIDを作成する必要があります。TypedIdこれを、と呼びます。これは、それぞれのXML名前空間とXML名をのIDと組み合わせたものResultですResult

そのソリューションに関する私の主な問題は、IDが任意のクライアントのシステムに適切に関連付けられるように、検出時に更新されるタイプの可変コレクションを維持するか、すべてのタイプの事前知識が必要になることです。残念ながら、私はより良い解決策を思い付くことができませんが、現在の解決策は間違っていると感じています。

Result特にWSDLの制限を念頭に置いて、ジェネリックを元のタイプに関連付けて、よりクリーンな方法で解決したいという同様の状況に直面したことはありますか?

4

1 に答える 1

1

これが私の提案です:

  1. 「クライアントが最終的に結果を一致させる方法を知っている」ようにしたいと考えています。そのため、「RequestType」と呼ばれる追加の識別子フィールド (文字列) を応答に含めます。

  2. 「発見されたときに更新されるタイプの変更可能なコレクションを維持すること、またはすべてのタイプの事前知識を維持して、クライアントのシステムで ID を適切に関連付けること」を避けたいと考えています。明らかに、各クライアント要求呼び出しは、結果がどの処理領域に関連するかを認識しています。そのため、クライアントに「RequestType」文字列をリクエストの一部として渡すことができます。RequestType が異なるタイプのクライアント要求ごとに一意の文字列である限り、サービスはナレッジをハードコーディングせずにそれを処理して関連付けることができます。

  3. 以下は、リクエストおよびレスポンス メッセージの Java クラスの例の 1 つです (つまり、実際のサービス エンドポイントではありません)。

    interface Request {
        String getId();
        String getRequestType();
        // anything else ...
    }
    
    interface Result {
        String getId();
        String getRequestType();
    }
    
    class Result1 implements Result {
        public String getId() { return uniqueValueForInstance; }
        public OtherType1 getField1() { /* ... */ }
        public OtherType2 getField2() { /* ... */ }
    }
    
    class Result2 implements Result {
        public String getId() { return uniqueValueForInstance; }
        public OtherType3 getField3() { /* ... */ }
    }
    
  4. これが落とし穴です。上記の (2) と (3) では、完全に動的な解は得られません。サービスが、それぞれの異なる要求に関連する柔軟なレコード構造を返すことができるようにしたいと考えています。次のオプションがあります。

    4A) XSD では、単一の厳密に型指定されたバリアント レコード タイプとして Result を宣言し、WSDL では、単一のサービス エンドポイントと単一の操作から結果を返します。XSD は、バリアント レコード構造を宣言するときに、識別子要素の値をハードコーディングする必要があります。

    4B) XSD では、可能なクライアント要求ごとに、複数の厳密に型指定された一意の型 Result1、Result2 などを宣言します。WSDL では、これらのそれぞれを返すために複数の一意の名前の操作があります。これらの操作は、1 つまたは複数のサービス エンドポイント、さらには複数の WSDL にわたって行うことができます。これにより、リクエスト タイプを特定のフィールド自体としてハード コーディングすることは回避されますが、実際にはクライアントに依存しない一般的なソリューションではありません。これは、各結果タイプと各操作に一意の名前を作成することで、各リクエスト タイプを区別するよう明示的にハード コーディングしているためです。 . したがって、明らかなダイナミズムは蜃気楼です。

    4C) XSD では、バリアントではないが、必要なすべての可能な結果を​​処理できる、一般的に名前が付けられたフィールドが多数ある柔軟な汎用データ構造を定義します。フィールドの例としては、「stringField1」、「stringField2」、「integerField1」、「dateField1058」などがあります。つまり、非常に弱い型付けを使用し、各フィールドに含まれるデータを魔法のように知るという負担をクライアントに課します。このオプションは非常に一般的かもしれませんが、通常はひどいやり方だと考えられています。それは洗練されておらず、かなり読みにくく、エラーが発生しやすく、とにかく制限/仮定が組み込まれています.十分な汎用フィールドが含まれていることをどのようにして知ることができますか? あなたの場合、(4A) がおそらく最良の選択肢です。

    4D) 柔軟な XSD スキーマ設計戦術を使用する - 型の代用性と「任意の」要素の使用。http://www.xfront.com/ExtensibleContentModels.htmlを参照してください。

    4E) 高レベルの型を作成する独自のファクトリ クラス メソッドに対して @Produces @SomeQualifier アノテーションを使用します。これは、特定の Bean タイプと修飾子を構築するために常にこのメソッドを使用するように CDI に指示します。ファクトリ メソッドには、呼び出しごとにどの特定の低レベル型を構築するかを決定するための凝ったロジックを含めることができます。@SomeQualifier には、タイプの選択に関するガイダンスを提供する追加のパラメーターを含めることができます。これにより、修飾子の数が 1 つに減る可能性があります。

    (4D) を使用すると、変化する要件に非常に効果的に対処できる柔軟なサービス エンドポイント設計が得られます。ただし、サービスの実装では、リクエストごとにどの結果フィールドを返すかを決定する柔軟な動作を実装する必要があります。実際、さまざまなデータ構造に対する論理的な要件がある場合、コードは個別のリクエストごとにこれらのデータ構造を処理する方法を知っている必要があるため、特定の形式の RequestType / 一意の操作名に依存する必要があります。(結果データに対する各クライアントのニーズに適応することなく) 完全に動的な処理を行うという目標は、あまりにも野心的です。

于 2013-03-11T00:59:53.147 に答える