1

サーバー上にあるEmployeeクラスがあり、それを Web サービスで公開して、クライアントが使用できるようにしたいと考えています。

これが私のクラスです:

public class Employee
{
    public CountryCode { get; private set;} 
    public EmployeeType {get; set;}

    public bool IsTaxable
    {
       get
       {
           return (CountryCode != Codes.CaymanIslands 
                  && Status != EmployeeType.Contract);
       }
    }

    public void Employee(EmployeeType type, CountryCode code)
    {
        EmployeeType = type;
        CountryCode = code;
    } 

    private void Employee() {}
}

プライベート コンストラクターとプライベート セッターは、このクラスが厳密に型指定され、DRY 原則に準拠し、有効な状態でのみインスタンス化できるようにするのに役立ちます。

たとえば、IsTaxableがコンストラクターで設定されていないことを確認しますが、他のクラス プロパティに基づいて動的に評価されます。このように、EmployeeTypeが変更された場合、 IsTaxableの結果はこの変更を反映します。この単純な例を使用して、このオブジェクトがロジックに富んでいるという事実を強調します。

このEmployeeクラスがサーバー上にあり、クライアント上でアクセスしたいとしましょう。私は WebService を構築し (.NET では WCF を使用します)、クラスを公開し、すぐに使用できるツールを使用して接続し、クライアントでネットワークを介してこのクラスを使用できるようにします。

問題は、そうすると、このカプセル化されたロジックのほとんどが失われることです。受信側では、クライアントはプライベート セッター、非表示のコンストラクター、IsTaxable プロパティのロジックなどを含むこのリッチ クラスを確認できません。代わりに、クライアント側では、次のような軽量クラスが表示されます。

public class Employee
{
    public CountryCode { get; private set;} 
    public EmployeeType {get; }
    public bool IsTaxable {get; }
}

クライアントが次のようなことを行うことで、無効な状態でクラスをインスタンス化できるようになりました。

Employee e = new Employee();
e.EmployeeType = EmployeeType.Contractor;
e.IsTaxable = true;

リッチ オブジェクトの喪失は、サービス指向の生活の単なる事実であり、私たちが共に生きなければならないものなのでしょうか?

このようなサービス転送オブジェクトは、情報を送信する目的のみで弱いデータ転送エンティティと見なされ、読み取り専用である必要がありますか。

クライアント側では、(必要に応じて) これらをよりリッチなオブジェクトにラップする必要がありますか?

ロジックがそのままのリッチ オブジェクトをネットワーク経由で渡す方法はありますか、それとも本当に必要ですか?

そのようなシナリオに対処するための確立されたパターンはありますか?

4

2 に答える 2

3

設計パターンを検討する前に、最初に検討する必要があるのは、実際にロジックを実行したい場所と、「悪意のある」クライアントがネットワーク経由で受信しているデータを変更した場合に実際に何が起こるかです。

ほとんどのクライアント/サーバー アーキテクチャの設計方法では、クライアントが何をしようとしてもサーバーによって検証される必要があります。そのため、クライアントがIsTaxabletrue に変更したり、従業員の名前や ID などを変更したりしても、サーバー側に保存されている実際のデータには影響しません。クライアントは、サーバー上のデータを更新する操作を実行する必要があり、その操作を実行する権利がある場合にのみ、そのデータがデータベースとシステムの残りの部分に伝達されます。

クライアントは常に「危険にさらされている」(ユーザーによる操作、ハッカーによるハッキング、ネットワーク経由での盗聴など) ため、サーバーはそのような状況に耐えられるだけの安全性を確保する必要があります。

「転送オブジェクト」は通常、データを運ぶことだけを目的としています。ロジックは、クライアント (たとえば、データをよりユーザーフレンドリーなプレゼンテーションにフォーマットするなど) またはサーバーによって実行されます。クライアントがデータに対して操作を実行する必要がある場合は、サーバーにその操作を依頼する必要があります (中央で更新されるようにするため)。

したがって、あなたの場合、Web サービスは、クライアントが必要なロジックを実行するための操作を公開する必要があります。

もう 1 つ注目したいのは、Contract First Web サービスの作成方法です。これは、Web サービスが他のプラットフォーム (Java など) と相互運用可能であることを保証するだけでなく、クライアントに公開する操作とデータの観点から考えるようになるため、ベスト プラクティスと見なされます。間違い (サーバーだけがアクセスできるオブジェクトのインスタンスを期待するなど)。

コントラクト ファーストとは、操作を記述する WSDL と、XML で転送されるメッセージとオブジェクトを記述する XSD を作成することを意味します。これらの WSDL および XSD ドキュメントからコードを自動的に生成するだけです。

于 2012-12-12T11:48:58.813 に答える
1

You can't do this for an arbitrary client, but if you control both client and server, you can add a reference to the assembly containing your Employee class to the client, then reuse this type for the WCF contract.

In Visual Studio, you can do this with "Add Service Reference" / "Advanced" / "Reuse types in referenced assemblies".

Is the loss of the rich object just a fact of service-oriented life and something that we have to live with?

Yes, this is true. In a true service-oriented architecture, you don't share behavior between client and server, only exchange messages. But if you're using WCF in a client-server architecture where you control both sides, you can use the above approach.

于 2012-12-12T11:59:17.237 に答える