Le migliori pratiche di progettazione dell'API Web - con molte (simili) operazioni

0

Ho un servizio web (axis2) e il server esegue 4 operazioni primarie: createX, removeX, getX e updateX

Dove X è rappresentato da una combinazione di 4 valori: id1, id2, id3 e id4

Quindi, per semplificare la vita degli sviluppatori, abbiamo creato 3 funzioni di supporto extra:

removeXForId, getXForId e updateXForId dove rappresentiamo l'insieme di 4 valori come 1 Identifier in modo che gli sviluppatori che ci chiamano non debbano passare tutti e 4 i valori ancora e ancora e solo archiviare l'identificatore univoco sulla loro estremità.

Ma non possiamo rimuovere completamente completamente le operazioni removeX, getX e updateX semplicemente affidandoci all'identificatore univoco in quanto alcuni casi d'uso devono superare tutti e 4 i valori.

Quindi, ora abbiamo circa 7 operazioni in cui metà (3) di esse sono operazioni duplicate con valori di input diversi.

Operazioni:

/createX
/getX {input: id1, id2, id3, id4}
/getXForId {input: id1234}
/removeX
/removeXForId
/updateX
/updateXForId

Questa è una buona pratica?

UPDATE:

getX è esattamente lo stesso di getXForId in termini di comportamento tranne gli argomenti di input.

getX accetta 4 input: val1, val2, val3 e val4. Ma getXForId occupa solo 1 ID che rappresenta (val1, val2, val3 e val4)

val1, val2, val3 e val4 sono in qualche modo legati l'uno all'altro, in combinazione rappresentano un collegamento univoco a un prodotto nel nostro sistema. Quindi abbiamo provato a raggrupparli insieme.

    
posta zengr 22.05.2012 - 22:46
fonte

3 risposte

4

Sarebbe più sensato per me organizzare l'API attorno alle risorse e usare i verbi (GET, PUT, POST, DELETE) forniti con il protocollo http, in breve: renderlo più RESTful , che è sicuramente considerato una buona pratica.

Questo è un buon resoconto sintetico sul design dell'API che analizza anche le API più diffuse come Facebook o Twitter.

Mi sono perso sulla differenza tra /getX e /getXForId , quindi non posso davvero darti un esempio di come cambierei la tua API.

Modifica

Ho provato a modellare l'API in Sinatra . È abbastanza auto esplicativo e diretto. (Ho visto che stai usando l'asse ma è passato un po 'di tempo da quando ho usato Java seriamente). Se sei serio riguardo a RESTful, probabilmente vorresti abbandonare l'approccio con i quattro id. Tuttavia l'approccio funziona:

require "sinatra"
require "sinatra/reloader"

def all_ids_given?(ids_given, ids_needed)
  ids_needed.reduce(true){|memo, id| memo &= ids_given.include? id}
end

#Your old /getXForId
get '/X/:combined_id' do |id|
  "Getting X with combined id #{id}\r\n"
end

#Your old /createX
post '/X' do
  post_params = request.body.read
  "Creating a new X with #{post_params} \r\n"
end

#Your old /updateXForId
put '/X/:combined_id' do |id|
  put_params = request.body.read
  "Updating X with combined id #{id}: New values are #{put_params}\r\n"
end

#Your old /removeXForId
delete '/X/:combined_id' do |id|
  "Deleting X with combined id #{id}\r\n"
end

#Your old /getX
get '/X' do
  if all_ids_given?(params.keys, ["id1","id2","id3","id4"])
    "Getting X with the ids #{params}\r\n"
  else
    "Error: Need arguments for id1, id2, id3 and id4\r\n" 
  end
end

#Your old /updateX
put '/X' do 
  if all_ids_given?(params.keys, ["id1","id2","id3","id4"])
    put_params = request.body.read
    "Updating X with the ids #{params}: New values are #{put_params}\r\n"
  else
    "Error: Need arguments for id1, id2, id3 and id4\r\n" 
  end
end

#Your old /removeX
delete '/X' do 
  if all_ids_given?(params.keys, ["id1","id2","id3","id4"])
    "Deleting X with combined id #{params}\r\n"
  else
    "Error: Need arguments for id1, id2, id3 and id4\r\n" 
  end
end

#Extensibility
get '/X/:combined_id/Y' do |id|
  "Getting all Ys for the X with combined id #{id}\r\n"
end

Test dell'API con curl:

base_url="http://localhost:4567/"

echo "Getting a X with a combined id"
echo -n "-> "; curl ${base_url}X/id1234
echo "Creating a new X with a list of properties"
echo -n "-> "; curl --data "property_1=test"  ${base_url}X
echo "Updating an existing X with a combined id"
echo -n "-> "; curl -X PUT --data "property_1=test&property_2=another_test"  ${base_url}X/id1234
echo "Deleting an existing X with a combined id"
echo -n "-> "; curl -X DELETE ${base_url}X/id1234

echo "Getting a X with 4 ids"
echo -n "-> "; curl ${base_url}"X?id1=1&id2=2&id3=3&id4=4"
echo "Getting a X with 4 ids, but supplying only 3"
echo -n "-> "; curl ${base_url}"X?id1=1&id3=3&id4=4"
echo "Updating a X with 4 ids"
echo -n "-> "; curl -X PUT --data "property_1=test&property_2=another_test"  ${base_url}"X?id1=1&id2=2&id3=3&id4=4"
echo "Updating a X with 4 ids"
echo -n "-> "; curl -X DELETE ${base_url}"X?id1=1&id2=2&id3=3&id4=4"

echo "\r\nTesting the extensibility"
echo "Getting all Ys for a single X (Unrelated example: /post/2/comments would give all comments to a single post with the id 2)"
echo -n "-> "; curl ${base_url}X/id1234/Y
echo "This won't work for the 4 ids"
echo -n "-> "; curl ${base_url}"X?id1=1&id2=2&id3=3&id4=4/Y"

Lo script restituisce quanto segue:

Getting a X with a combined id
-> Getting X with combined id id1234
Creating a new X with a list of properties
-> Creating a new X with property_1=test 
Updating an existing X with a combined id
-> Updating X with combined id id1234: New values are property_1=test&property_2=another_test
Deleting an existing X with a combined id
-> Deleting X with combined id id1234
Getting a X with 4 ids
-> Getting X with the ids {"id1"=>"1", "id2"=>"2", "id3"=>"3", "id4"=>"4"}
Getting a X with 4 ids, but supplying only 3
-> Error: Need arguments for id1, id2, id3 and id4
Updating a X with 4 ids
-> Updating X with the ids {"id1"=>"1", "id2"=>"2", "id3"=>"3", "id4"=>"4", "property_1"=>"test", "property_2"=>"another_test"}: New values are property_1=test&property_2=another_test
Updating a X with 4 ids
-> Deleting X with combined id {"id1"=>"1", "id2"=>"2", "id3"=>"3", "id4"=>"4"}

Testing the extensibility
Getting all Ys for a single X (Unrelated example: /post/2/comments would give all comments to a single post with the id 2)
-> Getting all Ys for the X with combined id id1234
This won't work for the 4 ids
-> Getting X with the ids {"id1"=>"1", "id2"=>"2", "id3"=>"3", "id4"=>"4/Y"}

Quello che puoi vedere è che le risorse di nidificazione e l'approccio a quattro parametri non funzionano bene insieme. Forse uno potrebbe modellarlo in modo diverso e fare qualcosa come /X/:id1/:id2/:id3/:id4 .

    
risposta data 22.05.2012 - 23:07
fonte
1

Quale problema risolvono le tue "identificazioni combinate"? Dici che è perché non vuoi inviare tutti gli identificatori separatamente, ma immagino che devi inviarli tutti indipendentemente dall'operazione che usi. Quindi, a meno che non ci siano altri problemi che le operazioni "extra" stanno risolvendo, la semplice risposta è semplicemente non averli.

Se davvero desidera queste operazioni "extra" perché rende il client più facile da implementare, puoi sempre implementarle nel codice client e usarle quando ne hai bisogno. Ad esempio, potresti avere una funzione che analizza l'identificatore combinato e quindi puoi utilizzarla ogni volta che devi effettuare una chiamata API. In questo modo l'API rimane pulita e le operazioni extra hanno un ambito appropriato.

    
risposta data 23.05.2012 - 03:48
fonte
-2

Sembra terribile, la memorizzazione di un ID univoco come stato sul server non si ridimensionerà a lungo termine.

Un sistema basato su REST stateless sarebbe un scelta infinitamente migliore.

Il passaggio di tutti i valori ogni volta è ciò che lo renderà scalabile. Cercare di salvare alcuni caratteri che uno sviluppatore deve digitare per inviare argomenti ti costerà 1000 volte di più per provare a tracciare e scalare lo stato sul lato server.

Abbandona ciò che stai facendo prima che sia troppo tardi per tornare indietro e tu ei tuoi successori dovete affrontare questa cattiva decisione progettuale per i prossimi 10 anni.

Il tuo chiarimento nel tuo aggiornamento è altrettanto grave ma in un modo diverso, viola completamente il Principio ASCIUTTO .

    
risposta data 22.05.2012 - 23:16
fonte

Leggi altre domande sui tag