Was ist die beste Praxis eine Seife Service (generic vs bestimmte Operation) bei der Definition?

StackOverflow https://stackoverflow.com/questions/180572

  •  05-07-2019
  •  | 
  •  

Frage

Meine Situation ist wie folgt:

Ich habe eine normalisierte Datenbank, in der ich geografische Informationen zu Flughäfen halten. Die Struktur ist:

airport --is in--> city --is in--> country --is in--> continent

Jetzt möchte ich Anwender diese Daten verwalten lassen, ohne dass sie den direkten Zugriff auf die Datenbank zu geben. Wir brauchen diese Administrationsoberfläche über einen Web-Service zu bieten.

Nun, wenn es um die Gestaltung der Service geht, liefen wir in die Diskussion darüber, wie die Vorgänge zu definieren. Wir kamen mit verschiedenen Lösungen:

Lösung A: spezifische Operationen

Für jede der vier Tabellen (Flughafen, Stadt, Land, Kontinent) definieren wir drei Operationen:

  • Einsatz
  • get
  • update

Das zu 12 Operationen führen würde mit 2 Request / Response-Objekten = 24 Objekte

Um ein alle neuen Flughafen mit allen Abhängigkeiten, mindestens 4-Anforderungen notwendig wäre zu erstellen.

Die Lösung B: generic

Es gibt nur eine Operation, die über die Parameter gesteuert wird. Dieser Vorgang ist in der Lage, alles zu schaffen benötigt, um die Datenbank zu verwalten.

Die Operation würde entscheiden, was getan werden muss, und führt sie aus. Wenn ein Fehler occures, wird es alles rückgängig zu machen.

==> 1 Betrieb = 2 hoch komplexes Request / Response-Objekte

Die Lösung C: Treffen in der Mitte 1

Eine generische Operation pro Tabelle, die get ausführen kann, einfügen, aktualisieren, genau wie die Lösung B, sondern konzentrierte sich auf eine Tabelle jeweils.

==> 4 Operationen = 8 komplexe Anforderung / Antwort-Objekte

Die Lösung D: Treffen in der Mitte 2

Eine generische Operation pro Aktion (get, einfügen, löschen), die auf jedem Tisch arbeiten können und lösen Abhängigkeiten.

==> 3 Operationen = 6 etwas komplexere Request / Response-Objekte

Beispiel:

Da dies eher abstrakt, hier ein vereinfachtes Beispiel für Anfrage-Objekte für die Erstellung von (JFK / New York / USA / Nordamerika):

Lösung A:

Anfrage 1/4:

<insertContinent>North America</insertContinent>

Anfrage 2/4:

<insertCountry continent="North America">USA</insertCountry>

Anfrage 3/4:

<insertCity country="USA">New York</insertCity>

Anfrage 4/4:

<insertAirport city="New York">JFK</insertAirport>

Lösung B:

Anfrage 1/1:

<action type="insertCountry" parent="North America">USA</action>
<action type="insertAirport" parent="New York">JFK</action>
<action type="insertContinent" parent="">North America</action>
<action type="insertCity" parent="USA">New York</action>

Lösung C:

Anfrage 1/4:

<countryAction type="insert" parent="North America">USA</countryAction>

Anfrage 2/4:

<airportAction type="insert" parent="New York">JFK</airportAction>

Anfrage 3/4:

<continentAction type="insert" parent="">North America</continentAction >

Anfrage 4/4:

<cityAction type="insert" parent="USA">New York</cityAction >

Lösung D: Anfrage 1/1:

<insert airport="JFK" city="New York" country="USA" continent="North America" />

Die Lösung D für mich eher elegant scheint daher habe ich versucht, dies in XSD zu setzen:

Code:

<complexType name="NewContinent">
    <sequence>
        <element name="NAME" type="string"></element>
    </sequence>
</complexType>

<complexType name="NewCountry">
    <sequence>
        <element name="ISOCODE" type="string"></element>
        <element name="NAME" type="string"></element>
        <choice>
            <element name="newCONTINENT" type="tns:NewContinent"></element>
            <element name="CONTINENT" type="string"></element>
        </choice>
    </sequence>
</complexType>

<complexType name="NewCity">
    <sequence>
        <element name="IATA" type="string"></element>
        <element name="NAME" type="string"></element>
        <choice>
            <element name="COUNTRY" type="string"></element>
            <element name="newCOUNTRY" type="tns:NewCountry"></element>
        </choice>
    </sequence>

</complexType>

<complexType name="NewAirport">
    <sequence>
        <element name="IATA" type="string"></element>
        <element name="NAME" type="string"></element>
        <choice>
            <element name="CITY" type="string"></element>
            <element name="newCITY" type="tns:NewCity"></element>
        </choice>
    </sequence>

</complexType>

Eine entsprechende Anfrage würde dann folgendermaßen aussehen folgt:

<complexType name="Request">
    <choice>
        <element name="AIRPORT" type="tns:NewAirport"></element>
        <element name="CITY" type="tns:NewCity"></element>
        <element name="COUNTRY" type="tns:NewCountry"></element>
        <element name="CONTINENT" type="tns:NewContinent"></element>
    </choice>
</complexType>

Jetzt meine Frage: Ist das wirklich die beste Lösung? Ist das XSD genug zu verstehen, was los ist?

War es hilfreich?

Lösung

Vermutlich schreiben Sie eine Protokollschicht, die Ihre verschiedenen Nachrichtentypen verstehen. Sie werden auch eine Anwendungsschicht benötigen Sie den Inhalt der Nachricht zu analysieren. Die verschiedenen Ansätze, die Sie erwähnen, die Last der Parsen zwischen diesen beiden Schichten verschieben. So zum Beispiel:

Lösung A : Die Protokollschicht macht die ganze Analyse und liefert die Daten und Befehl. Die Anwendungsschicht kann nur die Daten verwenden. Dies wird auch als RPC-Muster bekannt.

Vorteile: Sie können Ihre Nachrichten validieren. Sie können Nachrichten direkt an Anwendungsaufrufe Karte.

Nachteile:. Wenn Sie eine Änderung an der Schnittstelle, das Protokoll Änderungen vornehmen

Die Lösung B : Die Protokollschicht gibt zwei Werte und einen Befehl aus. Die Anwendungsschicht muss den Befehl verwenden, um die Werte in Typen zu analysieren.

Pros:. Das Protokoll ändert sich nie

Nachteile: Sie können keine Nachrichten validieren. Ihr Anwendungscode ist komplizierter.

Die Lösung C : Die Protokollschicht gibt zwei bekannte Arten und einen Befehl, die analysiert werden müssen. Die Anwendungsschicht kann nur den Befehl analysieren und die Daten verwenden.

Pros:. Ich kann nicht von jedem denkt, scheint nicht sehr guter Kompromiss

Nachteile:. Verläßt das Parsen nur teilweise getan

Die Lösung D : Die Protokollschicht kehrt bekannten Typen (wie Sie implementiert es) und ein allgemeiner Befehl. Die Anwendungsschicht muss an den Daten schauen sie empfangen, und den generischen Befehl in einen bestimmten Befehl umwandeln. Dies ist vergleichbar mit der REST-Architektur.

Vorteile: Die Anrufe sind verschiedene Operationen, so dass Sie zum Beispiel Cache könnte Antworten bekommen

.

Nachteile: Komplexität in der Anwendungsschicht

Das REST-Modell ist in der Regel anders umgesetzt als Sie skizziert haben. Es verwendet HTTP GET, POST, PUT, DELETE Nachrichten beliebige Dokumente zu kommunizieren. Die Parameter werden als Teil der URL angegeben. So zum Beispiel:

<insert airport="JFK" city="New York" country="USA" continent="North America" />

wird

<insert URL="airport?city=Chicago">ORD</insert>

Oder wenn Sie HTTP verwenden, wird es eine POST-Anforderung an einen Flughafen URL mit einem param der Stadt mit den Inhalten Informationen über den Flughafen. Beachten Sie, dass einige dieser wird klarer mit mehr compliated Daten, bei denen Sie mehrere Elemente und Mischtypen haben. Zum Beispiel, wenn Sie wollen die Flughafen Abkürzung, lange Namen und Höhe senden.

Ich denke, die REST-Architektur ganz gut für die Schnittstelle arbeiten könnten Sie beschreiben. Solange alles, was Sie tun müssen, ist die CRUD-Operationen unterstützen. Das sind viele Websites, die Sie die Vor- und Nachteile des REST architektonischen Stil geben wird.

Persönlich ziehe ich den RPC-Stil (Lösung A) mit einigen REST-ful Attributen. Ich mag das Protokoll die Parsing-Arbeit zu tun, und die Nachrichten zu validieren. Dies ist in der Regel, wie die Menschen SOAP Webservice-Schnittstellen implementieren.

Ihre Schnittstelle kann einfach heute aussieht, aber morgen einer Ihrer Kunden wird Sie für einen neuen Anruf stellen, die nicht das REST-Modell so gut passen, und Sie werden ihr es in die bestehenden vier Nachrichten finden verkeilen.

Andere Tipps

Dies ist eine alte Frage, und ich bin sicher, dass der Dienst vor langer Zeit geschrieben wurde, aber ich wollte sowieso eine Antwort beitragen.

Der RESTful Ansatz wäre, eine Flughafen-Ressource zu definieren, wie folgt aus:

<airport href="/airports/JFK">
    <name>JFK</name>
    <city>New York</city>
    <country>USA</country>
    <continent>North America</continent>
</airport>

Oder, wenn Sie einen Browser-kompatiblen Mikroformat verwenden:

<div class="object airport" href="/airports/JFK">
    <ul class="attributes"> 
        <li class="name">JFK</li>
        <li class="city">New York</li>
        <li class="country">USA</li>
        <li class="continent">North America</li>
    </ul>
</div>

Diese Ressource bei einer URI wie /airports/JFK befinden würde, die mit einem GET Verfahren abgerufen werden würden, mit einem PUT Verfahren aktualisiert, und mit einem DELETE Verfahren gelöscht.

In einem Entwurf so würde der URI /airports/ einen Container Ressource darstellt für alle von den Flughäfen in der Datenbank, und URIs wie /airports/?city=New+York und /airports/?country=USA wäre Filter auf den Behälter eine Teilmenge der Flughäfen zurückzukehren. Beide würden GET Methoden sein, und die Mittel würden eine Liste der Flughafen Ressourcen enthalten, wie oben definiert, die entweder vollständig (da sie klein ist) oder mit einem paar nützlichen Eigenschaften und dem href, die für jeden Flughafen der vollen Ressource Punkte .

Schließlich könnte eine neue Ressource hinzugefügt entweder eine PUT Methode auf dem vollständigen URI des Flughafens oder eine POST Methode auf /airports/. In beiden Fällen ist der Körper des Antrags ist der Flughafen Ressource wie oben gezeigt. Der Unterschied zwischen den Methoden ist, der die endgültige URI für den Flughafen zu entscheiden, bekommt: Der Kunde entscheidet sich für PUT und der Service entscheidet sich für POST. Welche Sie verwenden, hängt davon ab, ob oder nicht Ihre Kunden die richtige URI vernünftigerweise bestimmen kann. Normalerweise entscheidet der Service, da die URIs eine numerische eindeutige Kennung enthält und der Service muss, dass wählen.

Jetzt natürlich Ihre ursprüngliche Frage war über SOAP, nicht zur Ruhe. Ich würde gehen Sie vor und legen Sie ein RESTful-Design, wie ich beschrieben habe, dann meine Ressourcen als komplexe Typen beschreiben mit XSD und einen SOAP-Dienst mit Aktionen, die die GET, PUT, DELETE und POST Operationen des RESTful Service dupliziert. Dadurch erhalten Sie die RPC-Äquivalent:

class Airport
    has String name
    has String city
    has String country
    has String continent
    method void update(name, city, country, continent)
    method void delete()

class AirportList
    method Airport[] get(opt name, opt city, opt country, opt continent)
    method void add(name, city, country, continent)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top