API RESTful contro One Endpoint Do-All

3

La mia azienda ha sviluppato un'API RESTful che viene utilizzata da alcune applicazioni interne. Questa API consente ai clienti di addebitare pagamenti una tantum e pagamenti ricorrenti. Entrambe queste cose sono costituite da risorse; una persona richiede un metodo di pagamento per creare un abbonamento che creerà una transazione . I dati sono molto relazionali, ma uno dei nostri flussi di lavoro è il seguente.

Supponiamo che una nuova persona stia cercando di impostare un pagamento ricorrente. Il nostro flusso di lavoro è simile a questo:

  • Crea una persona
  • Crea un metodo di pagamento collegato a quella persona
  • Crea un abbonamento collegato a quel metodo di pagamento
  • Crea una transazione collegata a quell'abbonamento

Ciascuna di queste operazioni è rappresentata da un endpoint su uno dei nostri controller che costituisce l'API REST della nostra applicazione.

Man mano che l'app è cresciuta, molte persone mettono in dubbio perché siamo così fermi nel rispettare questo design modulare dell'API. Ogni volta che un nuovo cliente deve integrarsi con questa applicazione per creare abbonamenti, è necessario implementare il codice che segue questi quattro passaggi. La nostra risposta è sempre stata: "buona progettazione del software e REST, promuovere la separazione delle preoccupazioni e mantenere la costruzione di un tipo di risorsa separata da un'altra ci consente di mantenere le cose flessibili e mantenibili". Il principale contrappunto a questo è che, come tutti i software, abbiamo riscontrato alcuni bug tra le fasi di questo processo e le persone sostengono che i nostri problemi sarebbero stati risolti (o meno problematici) se avessimo un endpoint che ha fatto tutto. / p>

Il progetto ha pochi anni e ha visto un buon uso della produzione. Sono molto riluttante a credere che un endpoint "tutto-in-comune" sia la cosa giusta da fare ma sento che tutto ciò che devo sostenere in questo dibattito è teoria e principi. Alcuni dei nostri problemi sarebbero probabilmente stati risolti riducendo il chatter tra i sistemi, ma qualcosa sembra intrinsecamente sbagliato mettendo un gruppo di operazioni distinte in un unico metodo e chiamandolo un giorno.

C'è qualcosa che mi manca? Sono forse di parte perché ho aiutato a progettare l'app fino a questo punto o gli altri sviluppatori stanno sacrificando manutenzione e design per risolvere i problemi di oggi?

Spero che questa domanda non venga chiusa come "basata principalmente sull'opinione pubblica" perché sto cercando alcune risposte basate sull'esperienza del mondo reale piuttosto che sulla teoria / opinione (poiché credo già che io, in teoria, ho ragione).

    
posta Will Custode 29.09.2017 - 20:35
fonte

2 risposte

5

< inserisci rant su come l'obiettivo è fornire valore ed essere RESTful o seguire alcuni dettami OOAD non è fine a se stesso, anche YAGNI / >

Penso che potresti avere un (comune) fraintendimento di REST. Non so se questo è il caso, ma alcuni di quello che hai detto suggerisce che potresti avere una corrispondenza approssimativamente uno a uno tra le risorse REST e le tabelle del database. Anche se non lo fai, il "dilemma" che esprimi è falso. Niente su REST o altri principi di progettazione ti impedisce di aggiungere qualcosa come /person/3/recurring_payment/ 1 È del tutto normale e previsto per avere più risorse che si riferiscono alla stessa entità . Un POST a tale risorsa può fare tutto il lavoro di creazione di un metodo di pagamento, una sottoscrizione e una transazione. Ciò potrebbe portare a una risorsa /person/3/recurring_payment/1 che potrebbe essere solo un alias per la transazione creata o potrebbe fornire un riepilogo di tutti i dati rilevanti.

Ovviamente nessun principio di progettazione del software afferma che non è possibile fornire funzioni convenienti che combinino funzionalità per acquisire schemi ricorrenti comuni. Dovresti comunque cercare di trovare entità concettuali coerenti. In effetti, non mi è chiaro che la tua API corrente non esponga essenzialmente i dettagli di implementazione.

Infine, personalmente, non penso che REST sia effettivamente appropriato per le API interne in molti casi. Gli obiettivi di REST consistono nel rendere le API di lunga durata, in grado di evolvere indipendentemente da domini amministrativi separati (ad esempio società separate) e scalabili per documenti a grana grossa che cambiano lentamente 2 . Sebbene queste proprietà siano desiderabili, spesso non sono requisiti delle API interne. Inoltre, il loro completamento aggiunge complessità nell'implementazione e nelle specifiche, nonché problemi come una maggiore latenza. Il risultato è che in pratica molte API sono REST solo nel nome . È molto probabile che questo si applichi alla tua API. Ad esempio, hai specificato qualsiasi tipo di media ? In caso contrario, probabilmente non stai facendo REST. Che va bene, ma probabilmente dovresti smetterla di sforzarti vagamente. Ci sono anche, ora, nuovi modelli di API che stanno chiaramente uscendo in una direzione diversa rispetto a REST, ad es. GraphQL . Il tempo dirà come si comportano, ma REST non è un ideale perfetto per la progettazione dell'API.

1 Questo suggerimento è solo per avere qualcosa di concreto di cui parlare. C'è un altro malinteso comune su REST, ovvero che è in qualche modo l'organizzazione dei percorsi URI in determinati modi. In realtà, a REST non importa come i percorsi degli URI siano organizzati e idealmente un cliente potrebbe (e dovrebbe) essere completamente all'oscuro di esso. Questo porta a cose come HATEOAS .

2 "L'interfaccia REST è progettata per essere efficiente per il trasferimento di dati ipermediali di grana grossa, ottimizzando per il caso comune del Web, ma risultando in un'interfaccia che non è ottimale per altre forme di interazione architettonica. "

    
risposta data 29.09.2017 - 23:05
fonte
4

Is there something I'm missing?

Sì. Per cominciare, ti manca che la tua API non sia molto buona.

Diamo un'occhiata al tuo esempio in dettaglio

Suppose a new person is looking to set up a recurring payment. Our workflow looks like this:

  • Create a person
  • Create a payment method linked to that person
  • Create a subscription linked to that payment method
  • Create a transaction that is linked to that subscription

Tradotto: il consumatore dell'API sta provando a raggiungere un'attività una . Ciò richiede l'orchestrazione di quattro diversi sottoprogrammi. E la tua API insiste sul fatto che il consumatore esegua il lavoro per ottenere l'orchestrazione .

Ciò che i tuoi consumatori chiedono è di inviare un messaggio a un concierge ; e per il concierge di rompere quel messaggio nelle sue parti componenti e gestire l'invio.

La home page di Google era un esempio perfetto di questo; c'era un link da quella pagina nel protocollo di ricerca di Google, in cui le risorse ti fornivano i collegamenti per navigare in un catalogo di risultati che corrispondevano alla tua ricerca. Ma c'era anche un secondo link, al protocollo "Mi sento fortunato" di Google, che scambiava il controllo a grana fine del protocollo di ricerca per un'esperienza pratica e senza pubblicità.

Non c'è assolutamente alcun motivo per cui le tue risorse API non dovrebbero supportare più protocolli. Ciò potrebbe significare che hai molte risorse che rappresentano lo stesso concetto di dominio, in cui ogni risorsa è specializzata in un particolare protocollo. Questo è normale per REST.

Jim Webber, nel suo talk REST: DDD nel grande

URIs do NOT map onto domain objects - that violates encapsulation. Work (ex: issuing commands to the domain model) is a side effect of managing resources. In other words, the resources are part of the anti-corruption layer. You should expect to have many many more resources in your integration domain than you do business objects in your business domain.

In altre parole, REST non impone ostacoli che potrebbero impedirti di migliorare l'esperienza dell'API per i tuoi clienti.

L'offerta della tua API è invece analoga a una burocrazia di Vogon, in cui un singolo pagamento ricorrente richiede la compilazione di quattro diverse forme e la consegna a mano a ciascuno dei quattro diversi reparti.

I tuoi utenti API non dovrebbero essere obbligati a preoccuparsi che il tuo protocollo sia implementato come quattro diversi oggetti di dominio con quattro diversi database che vivono in quattro diversi microservizi: il punto dell'API è quello di isolare il consumatore dai dettagli così che puoi modificare più facilmente i dettagli in futuro .

    
risposta data 30.09.2017 - 02:31
fonte

Leggi altre domande sui tag