9

私は、ストレージ システムへのインターフェイスとして機能する一連のクラスを開発するプロジェクトを割り当てられました。要件は、クラスが次のシグネチャを持つ get メソッドをサポートすることです。

public CustomObject get(String key, Date ifModifiedSince)

基本的に、このメソッドは、オブジェクトが の後に変更された場合にのみ、CustomObject関連付けられたを返すことになっています。ストレージ システムに が含まれていない場合、メソッドは null を返す必要があります。keyifModifiedSincekey

私の問題はこれです:

キーは存在するがオブジェクトが変更されていないシナリオをどのように処理すればよいですか?

このクラスを使用する一部のアプリケーションは Web サービスおよび Web アプリケーションになるため、これは重要です。これらのアプリケーションは、404 (見つからない)、304 (変更されていない)、または 200 (データはここにあります) のいずれを返すかを知る必要があります。

私が検討しているソリューションは次のとおりです。

  1. ストレージ システムに key
  2. が失敗したときにカスタム例外をスローし ifModifiedSinceます。
  3. ステータス プロパティを CustomObject に追加します。呼び出し元にプロパティの確認を要求します。

これら 3 つのオプションのいずれにも満足できません。フロー制御に例外を使用するのが好きではないため、オプション 1 と 2 は好きではありません。また、値がなかったことを示すことが意図されている場合に、値を返すことも好きではありません。

それにもかかわらず、私はオプション 3 に傾いています。

検討していないオプションはありますか? これらの 3 つのオプションのいずれかについて強い感情を持っている人はいますか?


この質問への回答、言い換え:

  1. メソッドを提供し、contains 呼び出し元が を呼び出す前にそれを呼び出すことを要求しget(key, ifModifiedSince)、キーが存在しない場合は例外をスローし、オブジェクトが変更されていない場合は null を返します。
  2. 応答とデータ (存在する場合) を複合オブジェクトにラップします。
  3. 事前定義された定数を使用して、状態を示します ( UNMODIFIED, KEY_DOES_NOT_EXIST)。
  4. Caller は、コールバックとして使用されるインターフェイスを実装します。
  5. デザインがイマイチ。

答え #1 を選択できない理由

これが理想的な解決策であることに同意しますが、それは私がすでに (しぶしぶ) 却下したものでした。このアプローチの問題は、これらのクラスが使用されるほとんどのケースで、バックエンド ストレージ システムが Amazon S3 などのサード パーティのリモート システムになることです。これは、containsメソッドがストレージ システムへのラウンド トリップを必要とすることを意味し、ほとんどの場合、その後に別のラウンド トリップが続きます。これには時間と費用の両方がかかるため、オプションではありません。

その制限がなければ、これが最善のアプローチです。

(質問でこの重要な要素について言及しなかったことに気づきましたが、簡潔にしようとしていました。明らかに関連性がありました。)


結論:

すべての回答を読んだ後、この場合はラッパーが最適なアプローチであるという結論に達しました。基本的に、応答コードを含むメタデータ (ヘッダー) とコンテンツの本文 (メッセージ) を使用して、HTTP を模倣します。

4

11 に答える 11

7

実際には、応答コードと見つかったオブジェクトの 2 つの項目を返したいようです。両方を保持し、それらを一緒に返す軽量のラッパーを作成することを検討してください。

public class Pair<K,V>{
  public K first;
  public V second;
}

次に、応答コードとデータを保持する新しいペアを作成できます。ジェネリックを使用することの副作用として、実際に必要なペアに対してこのラッパーを再利用できます。

また、データの有効期限が切れていない場合は、データを返すこともできますが、変更されていないことを知らせる 303 コードを与えます。4xx シリーズは とペアになりnullます。

于 2008-12-06T01:34:17.817 に答える
5

与えられた要件では、これを行うことはできません。

コントラクトを設計した場合は、条件を追加して呼び出し元に呼び出しを行わせる

exists(key): bool

サービスの実装は次のようになります。

if (exists(key)) {
    CustomObject o = get(key, ifModifiedSince);
    if (o == null) { 
      setResponseCode(302);
    } else {
      setResponseCode(200);
      push(o);
   }

} else {
      setResponseCode(400);
}

クライアントは変更されず、事前に検証されたことに気付くことはありません。

あなたが契約書を設計しなかった場合おそらくそれには正当な理由があるか、おそらく設計者 (または建築家) のせいです。ただし、変更することはできませんので、心配する必要はありません。

次に、仕様に準拠し、次のように進める必要があります。

 CustomObject o = get(key, ifModifiedSince);

 if (o != null) {
     setResponseCode(200);
     push(o);
  } else {
     setResponseCode(404); // either not found or not modified.
  }

この場合、302 を送信していませんが、おそらくそれが設計された方法です。

つまり、セキュリティ上の理由から、サーバーはそれ以上の情報を返すべきではありません[プローブは get( key, date ) のみ null または object を返します]

だから心配しないでください。マネージャーと話し、この決定を知らせてください。この決定もコードにコメントしてください。そして、アーキテクトが手元にある場合は、この奇妙な制限の背後にある理論的根拠を確認してください.

おそらく、彼らはあなたがこれを見ていない可能性があり、あなたの提案の後に契約を変更することができます.

正しく進めたいと思っていても、間違った進め方をして、アプリのセキュリティが損なわれることがあります。

チームと通信します。

于 2008-12-06T01:08:46.527 に答える
3

変更されていないことを示す「マーカー」として特別な最終 CustomObject を作成できます。

static public final CustomObject UNCHANGED=new CustomObject();

.equals() の代わりに "==" を使用して一致をテストします。

変更されていない場合に null を返し、存在しない場合に例外をスローすることもできますか? あなたの 3 つのうちの 1 つを選ばなければならないとしたら、1 を選びます。

于 2008-12-06T00:37:55.917 に答える
3

存在しないオブジェクトを探すことは、私には例外的なケースのように思えます。呼び出し元がオブジェクトが存在するかどうかを判断できるようにするメソッドと組み合わせると、存在しないときに例外をスローしても問題ないと思います。

public bool exists( String key ) { ... }

発信者は次のことができます:

if (exists(key)) {
   CustomObject modified = get(key,DateTime.Today.AddDays(-1));
   if (modified != null) { ... }
}

or

try {
    CustomObject modified = get(key,DateTime.Today.AddDays(-1));
}
catch (NotFoundException) { ... }
于 2008-12-06T00:39:15.413 に答える
2

例外の問題は、例外的で異常な動作による「フェイル ファスト」シナリオ (つまり、処理されない場合、例外によってアプリケーション が停止する) を通知することを意図していることです。

「キーは存在するが、オブジェクトは変更されていない」というシナリオは例外的なものではなく、決して異常なものではないと思います。

したがって、私は例外を使用しませんが、結果 (プロパティまたは特別なオブジェクト) を正しく解釈するために呼び出し元が実行する必要があるアクションを文書化します。

于 2008-12-06T00:45:56.697 に答える
1

そのメソッド署名の要件はどのくらい厳格ですか?

まだ進行中のプロジェクトに取り組んでいるようです。あなたのクラスの利用者が他の開発者である場合、要求したメソッド シグネチャが不十分であることを彼らに納得させることができますか? おそらく彼らは、2 つの固有の障害モード (キーが存在せず、オブジェクトが変更されていない) が存在する必要があることにまだ気づいていません。

可能であれば上司に相談してみます。

于 2008-12-06T01:02:59.250 に答える
1

私はまだnullを返します。

プロパティの意図は、指定された日付以降に変更されたオブジェクトを返すことです。オブジェクトがない場合に null を返すことが問題ない場合は、変更されていないオブジェクトに対して null を返すことも問題ありません。

個人的には、変更されていないオブジェクトに対して null を返し、存在しないオブジェクトに対して例外をスローします。そのほうが自然に思えます。

ところで、フロー制御に例外を使用しないのはまったく正しいので、これらの 3 つのオプションしかない場合、直感は正しいです。

于 2008-12-06T01:10:43.200 に答える
1

の .Net ライブラリ パターンに従い、CustomObject.Emptyという名前のCustomObject型のカスタム オブジェクト(string.Empty や Guid.Empty など) に public static readonly フィールドを持つことができます。オブジェクトが変更されていない場合は、これを返すことができます (関数の消費者はそれと比較する必要があります)。
編集:あなたがJavaで作業していることに気付いたばかりですが、原則は引き続き適用されます

これにより、次のオプションが提供されます

  • キーが存在しない場合は null を返します。

  • キーが存在するがオブジェクトが変更されていない場合、CustomObject.Emptyを返します。

欠点は、消費者が null の戻り値と CustomObject.Empty の戻り値の違いを知る必要があることです。

おそらく、このプロパティはCustomObject.NotModifiedと呼ばれる方が適切でしょう。これは、Empty は null にできないため、実際には Value 型を対象としているためです。また、 NotModifiedはフィールドの意味をより簡単に消費者に伝えます。

于 2008-12-06T01:10:48.457 に答える
1

要件に関する (意図した) インターフェースが深刻に壊れています。1 つのメソッド内で関係のないことをしようとします。これはソフトウェア地獄への道です。

于 2008-12-06T02:10:43.030 に答える
1

Callback クラスがイベント ドリブンまたはセッター ドリブンのいずれかである引数として Callback を指定します。

発生する可能性のあるさまざまなエラーをクラスのインターフェイスで定義し、必要に応じて CustomObject をイベントのパラメーターとして渡します。

public interface Callback {
  public void keyDoesNotExist();
  public void notModified(CustomObject c);
  public void isNewlyModified(CustomObject c);
  .
  .
  .
}

このように、Callback インターフェースの実装者は、イベントが発生したときに何をするかを定義できます。また、その条件で取得したオブジェクトを渡す必要があるかどうかを、インターフェースを介して選択できます。最後に、返品時のロジックの複雑さが軽減されます。あなたの方法はそれを一度行います。API の実装者は、それを行う必要はまったくありません。

于 2008-12-08T04:34:33.940 に答える
0

許容できる場合は、増幅された CustomObject (ラッパー) を返すことができます。これには、オブジェクトとその変更状態 (存在する場合) を表す値が含まれていました。

于 2008-12-06T00:45:05.043 に答える