Frage

Ich habe ein Projekt zugewiesen eine Reihe von Klassen zu entwickeln, die als Schnittstelle zu einem Speichersystem handeln. Voraussetzung ist, dass die Klasse eine get-Methode mit folgenden Signatur unterstützen:

public CustomObject get(String key, Date ifModifiedSince)

Im Grunde ist das Verfahren soll den CustomObject mit dem key zugeordnet zurück, wenn und nur wenn das Objekt nach ifModifiedSince modifiziert wurde. Wenn das Speichersystem nicht die key enthält dann die Methode sollte null zurück.

Mein Problem ist folgendes:

Wie gehe ich das Szenario, in dem der Schlüssel, aber das Objekt existiert hat nicht verändert?

Dies ist wichtig, da einige Anwendungen, die diese Klasse verwenden Web-Services und Web-Anwendungen sein. Diese Anwendungen müssen wissen, ob eine 404 (nicht gefunden) zurückzukehren, 304 (nicht modifiziert) oder 200 (OK, hier die Daten).

Die Lösungen, die ich bin mit einem Gewicht sind:

  1. Werfen Sie eine benutzerdefinierte Ausnahme, wenn die Speichersystem enthält nicht die key
  2. Werfen Sie eine benutzerdefinierte Ausnahme, wenn die ifModifiedSince ausfällt.
  3. Fügen Sie eine Status-Eigenschaft auf den CustomObject. Erfordern Anrufer Eigenschaft zu überprüfen.

Ich bin nicht glücklich mit jedem dieser drei Optionen. Ich weiß nicht wie die Optionen 1 und 2, weil ich nicht mag Ausnahmen für die Ablaufsteuerung verwenden. Ich auch nicht wie ich einen Wert zurückkehrt, wenn meine Absicht, um anzuzeigen, dass es keinen Wert .

Dennoch bin ich Neigung zu Option 3.

Gibt es eine Möglichkeit, die ich überlege mir nicht? Hat jemand starke Gefühle über eine dieser drei Optionen?


Antworten auf diese Frage, Umschrieben:

  1. Geben Sie eine contains Verfahren und erfordern Anrufer es zu nennen vor get(key, ifModifiedSince) Aufruf, werfen Ausnahme, wenn Schlüssel nicht vorhanden ist, null zurück, wenn das Objekt nicht gewesen geändert.
  2. Wickeln Sie die Antwort und Daten (falls vorhanden) in einem zusammengesetzten Objekt.
  3. Verwenden Sie eine vordefinierte Konstante etwas Zustand (UNMODIFIED, KEY_DOES_NOT_EXIST) zu bezeichnen.
  4. Caller implementiert Schnittstelle zu sein verwendet als Rückruf.
  5. Das Design saugt.

Warum ich nicht Antwort # kann wählen 1

Ich bin damit einverstanden, dass dies die ideale Lösung ist, aber es war ein Ich habe bereits (ungern) zurückgewiesen. Das Problem bei diesem Ansatz ist, dass in der Mehrheit der Fälle, in denen diese Klassen verwendet werden sollen, wird das Back-End-Speichersystem ein Drittes Remote-System sein, wie Amazon S3. Dies bedeutet, dass eine Methode contains eine Rundreise mit dem Speichersystem erfordern würde, was in den meisten Fällen durch eine andere Rundreise folgen würde. Da dieses würde Zeit und Geld kosten , es ist keine Option.

Wenn nicht für diese Einschränkung, dies ist der beste Ansatz sei.

(Ich weiß, ich habe nicht dieses wichtige Element erwähne in der Frage, aber ich habe versucht, es zu halten kurz. Offensichtlich war es relevant.)


Fazit:

Nachdem alle Antworten zu lesen ich zu dem Schluss gekommen, dass ein Wrapper der beste Ansatz ist in diesem Fall. Im Wesentlichen HTTP imitiert Ich werde mit Metadaten (Header) mit einem Antwortcode und Inhaltskörpern (Meldung).

War es hilfreich?

Lösung

Es klingt wie Sie tatsächlich zwei Artikel zurückgeben möchten: den Antwortcode und das Objekt gefunden. Sie betrachten könnte eine leichte Wrapper zu schaffen, die sie beide und das Rückzusammenhält.

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

Dann können Sie ein neues Paar erstellen, die Ihre Antwort-Code und die Daten enthalten. Als Nebeneffekt Generika zu verwenden, können Sie dann diese Wrapper wieder verwenden, was auch immer für Paar Sie tatsächlich benötigen.

Auch wenn die Daten nicht abgelaufen ist, können Sie immer noch darauf zurückkommen, aber es hat eine 303-Code geben, um ihnen mitzuteilen, dass es unverändert ist. 4xx Serie würde mit null kombiniert werden.

Andere Tipps

Mit der gegebenen Anforderung können Sie dies nicht tun.

Wenn Sie den Vertrag entworfen , dann eine Bedingung hinzuzufügen, und der Anrufer machen aufrufen

exists(key): bool

Die Service-Implementierung sieht wie folgt aus:

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

} else {
      setResponseCode(400);
}

Der Kunde bleibt unverändert und nie bemerken Sie im Voraus validiert haben.

Wenn Sie nicht den Auftrag haben entwerfen Wahrscheinlich gibt es einen guten Grund dafür, oder es ist wahrscheinlich nur der Konstrukteur (oder Architekt) Fehler. Aber da du es nicht ändern können, dann müssen Sie auch nicht kümmern.

Dann sollten Sie auf die Spezifikationen einhalten und gehen Sie wie folgt aus:

 CustomObject o = get(key, ifModifiedSince);

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

Ok, Sie senden nicht 302 in diesem Fall, aber wahrscheinlich das ist so, wie es entworfen wurde.

Ich meine, aus Gründen der Sicherheit, der Server nicht mehr Informationen als die Rückkehr sollte [die Sonde erhält (Schlüssel, Datum) nur entweder null oder Objekt zurückgeben]

Also keine Sorge darüber. Sprechen Sie mit Ihren Vorgesetzten und lassen Sie ihn diese Entscheidung mit. Kommentieren Sie den Code mit dieser zu Entscheidung. Und wenn Sie die Architekten in der Hand bestätigt die Logik hinter dieser seltsamen Einschränkung.

Die Chancen stehen gut sie Sie nicht kommen sehen, und sie können den Vertrag nach Ihrem Vorschlag ändern.

Manchmal während wollen Recht gehen wir falsch gehen kann und die Sicherheit unserer App gefährden.

Kommunizieren Sie mit Ihrem Team.

Sie können eine spezielle endgültige CustomObject als „Marker“, um anzuzeigen, unverändert erstellen

static public final CustomObject UNCHANGED=new CustomObject();

und Test für eine Übereinstimmung mit "==" statt .equals ().

Es könnte auch auf unverändert null zurück arbeiten und eine Ausnahme auslösen, auf gar nicht existiert? Wenn ich eine Ihrer 3 wählen hätte, würde ich 1 wählen, weil das die außergewöhnlichste Fall zu sein scheint.

für ein Objekt suchen, das nicht scheint mir wie ein Ausnahmefall nicht existiert. Gekoppelt mit einer Methode, die ein Anrufer ermöglicht, zu bestimmen, ob ein Objekt vorhanden ist, denke ich, es wäre in Ordnung, um die Ausnahme zu werfen, wenn es nicht.

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

Anrufer tun können:

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) { ... }

Das Problem mit Ausnahmen ist sie sollen einen „fail schnell“ -Szenario signalisieren (dh wenn nicht verarbeitet, wird eine Ausnahme Stop eine Anwendung) aufgrund eines außergewöhnlichen und abnormal Verhalten.

Ich glaube nicht, dass „das Szenario, in dem der Schlüssel vorhanden ist, aber das Objekt nicht modifiziert worden ist“ ist ein aussergewöhnliches, schon gar nicht ein abnormer ein.

Daher würde ich nicht Ausnahme verwenden, sondern würde ich die Aktion die Anrufer müssen dokumentieren, um zu tun, um richtig das Ergebnis (Eigentum oder spezielles Objekt) zu interpretieren.

Wie streng ist die Voraussetzung für diese Methode Signatur?

Es scheint, als ob Sie an einem Projekt arbeiten, die noch im Gang ist. Wenn die Verbraucher Ihrer Klasse andere Entwickler sind, können Sie sie davon überzeugen, dass die Signatur der Methode sie für unzureichend gefragt ist? Vielleicht haben sie noch nicht realisiert, dass es zwei eindeutige Ausfallarten sein (Schlüssel nicht vorhanden ist und Objekt nicht verändert wurde).

Ich würde es mit Ihren Vorgesetzten besprechen, ob das eine Option ist.

Ich würde immer noch null zurück.

Die Absicht der Immobilie ist das Objekt zurückzugeben, die nach dem angegebenen Datum geändert wurden. Wenn für kein Objekt null Rückkehr in Ordnung ist, dann sicher null für ein nicht modifizierte Objekt Rückkehr ist auch ok.

Ich persönlich würde null zurück, für ein nicht-modifizierten Objekt, und eine Ausnahme für ein nicht vorhandenes Objekt werfen. Das scheint natürlicher.

Sie haben ganz recht nicht BTW Ausnahmen für die Ablaufsteuerung zu verwenden, wenn Sie also nur die drei Möglichkeiten, Ihr Bauchgefühl richtig ist.

Sie könnten die Net-Bibliothek Mustern folgen und ein öffentliches statisches Nur-Lese-Feld in dem benutzerdefinierten Objekt haben genannt CustomObject.Empty , der vom Typ CustomObject (wie String. leere und Guid.Empty). Man könnte dies zurück, wenn das Objekt nicht geändert wird (die Funktion Verbraucher müssen dagegen vergleichen).
Edit: ich gerade erst entdeckt, dass Sie in Java arbeiten, aber das Prinzip gilt immer noch

Das gibt Ihnen die Möglichkeit, die folgenden

  • null zurück, wenn der Schlüssel nicht vorhanden ist.

  • Zurück CustomObject.Empty , wenn der Schlüssel vorhanden ist, aber das Objekt nicht geändert wurde.

Der Nachteil ist, dass der Verbraucher den Unterschied zwischen einem Nullrückgabewert und einem CustomObject.Empty Rückgabewert zu wissen brauchen würde.

Vielleicht wäre das Eigentum mehr wird treffend als CustomObject.NotModified als Leere wirklich für Werttypen bestimmt ist, da sie nicht null sein können. Auch NotModified würde vermittelt die Bedeutung des Feldes leichter für die Verbraucher.

Die (beabsichtigte) Schnittstelle, um die Anforderungen in Bezug auf ernsthaft gebrochen. Sie versuchen, unabhängige Dinge innerhalb einer Methode zu tun. Dies ist der Weg zur Software Hölle.

Rückruf als Argument Stellen, wo die Callback-Klasse könnte entweder angetrieben ereignisgesteuert, oder Setter werden.

Sie haben Schnittstelle Ihre Klasse die verschiedenen Fehler definieren, die auftreten können, als Parameter für das Ereignis in der CustomObject vorbei, wenn nötig.

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

Auf diese Weise können Sie die Implementierer der Callback-Schnittstelle zu definieren, was zu tun ist, wenn das Ereignis eintritt, und Sie können über die Schnittstelle wählen, ob die Bedingungen für die Weitergabe des abgerufenen Objekts erfordert. Schließlich verringert es die Komplexität der Logik auf eine Rückkehr. Ihre Methode macht das einmal. Implementierer der API erfordern es überhaupt nicht tun, da es für sie getan hat.

Wenn es akzeptabel ist, kann eine amplifizierte CustomObject (a wrapper) zurückzukehren, welche Werte enthalten, die das Objekt und seine Modifikationszustand repräsentiert, wenn überhaupt, etc.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top