Microservice / Soa: come attivare la notifica a seconda del chiamante?

0

Ho questi due casi d'uso in un processo di registrazione utente:

  • Caso 1: l'utente registra un account online e il sistema gli deve inviare una notifica via email per confermare che il suo account è stato creato e convalidare la sua e-mail nello stesso momento.
  • Caso 2: l'account utente viene creato con un agente, in un'agenzia di vendita ufficio: questa volta non è necessario attivare la procedura di notifica della posta.

Quindi mi chiedo come dovrei modellare il mio servizio di restituzione dell'account:

  • Opzione 1: presentare a diversi uri o utilizzare un parametro. In questo caso l'applicazione che chiama il servizio sa quale endpoint di registrazione chiama per il suo caso d'uso.

  • Opzione 2: creare un servizio di alto livello che, a seconda del chiamante, dovrebbe orchestrare la chiamata e attivare il processo di notifica, se necessario?

  • Opzione 3: complica la mia architettura attuale introducendo una mamma e creando un gestore sull'evento di registrazione dell'account, in modo che venga generata una mail di notifica, se necessario ...

posta Dypso 21.12.2018 - 10:24
fonte

2 risposte

1

In definitiva, questa è una questione di incapsulamento. Da dove viene la dichiarazione di if sull'invio o meno di email live?

Opzione 1 (a) - Utilizza un URI diverso

In questa opzione, ci sono almeno due distinti software: l'applicazione chiamante e il servizio. Inoltre, l'istruzione if sull'invio o meno dell'email risiede nell'applicazione chiamante, che indica al servizio quale ramo prendere chiamando diversi endpoint.

Opzione 1 (b): utilizza un parametro

Come sopra, ci sono gli stessi due software, ma l'istruzione if risiede nel servizio, più vicino al codice di creazione dell'utente.

Opzione 2 - Servizio di alto livello

Qui ci sono almeno tre pezzi di software: l'applicazione chiamante, il servizio di alto livello e il servizio di creazione degli utenti. Questa opzione si riduce tecnicamente alla stessa domanda dell'opzione 1: se il servizio di alto livello ora possiede l'istruzione if , come fa a sapere quale ramo eseguire? L'applicazione chiamante chiama un endpoint diverso nel servizio di alto livello? Oppure, passa un parametro ad esso?

Opzione 3: introduce un middleware orientato ai messaggi

Questa opzione suona davvero più come un piuttosto che come cosa. L'introduzione di un MOM riguarda il passaggio di messaggi tramite code e messaggi di passaggio tramite endpoint sui servizi. Pertanto, l'applicazione chiamante dovrebbe sapere se passare diversi tipi di messaggi (utilizzare un diverso endpoint) o se passare un parametro come parte del payload del messaggio (utilizzare un parametro). In altre parole, ti rimangono le stesse due scelte.

Quindi, alla fine, la decisione si riduce a se creare o meno endpoint (o messaggi) separati o passare un parametro (sull'endpoint o nel corpo del messaggio).

Principio di responsabilità singola dice che dovremmo raccogliere insieme le cose che probabilmente cambiano insieme e separano quelle cose che cambieranno per ragioni diverse. Pertanto, dobbiamo decidere se l'istruzione if appartiene o meno ai casi d'uso nell'applicazione chiamante o al servizio stesso.

Mentre scrivevo questo, andavo letteralmente avanti e indietro su quale raccomandare. Non sono sicuro che ci sia una risposta corretta. Alla fine, mi sto orientando verso un'opzione che non era nell'OP, che va così:

Opzione 4 - Usa design basato sui casi

In questa opzione, ci sono tre parti del software, l'applicazione chiamante, il servizio di creazione degli utenti e un servizio di notifica utente. L'applicazione chiamante ha classi di "use case" differenti, ognuna delle quali sa se notificare o meno l'utente. E i servizi sono responsabili solo per l'unica cosa che sa.

Quindi, in questa opzione, l'istruzione if risiede nell'applicazione chiamante e vi è un solo endpoint su ciascuno dei servizi sottostanti:

Chiamata all'applicazione (in pseudo rubino)

class RegistrationController
  def create
    if agent_registration
      UseCases::AgentRegistration.register(user_attributes)
    else
      UseCases::SelfRegistration.register(user_attributes)
    end
  end
end

class AgentRegistrationUseCase
  def register(user_attributes)
    UserRegistrationServivce.create(user_attributes)
  end
end

class UserRegistrationUseCase
  def register(user_attributes)
    UserRegistrationService.create(user_attributes)
    UserNotificationService.create(user_attributes)
  end
end

Si noti che l'istruzione if risiede nell'applicazione chiamante, vicino all'interfaccia utente, e potrebbe facilmente essere sostituita con un'istruzione case nel caso in cui si abbiano casi di utilizzo aggiuntivi. Le classi UseCases sono specifiche per uno dei due casi d'uso. E i servizi hanno solo un singolo create di endpoint su di essi.

    
risposta data 21.12.2018 - 11:36
fonte
0

Potenzialmente, le situazioni per la creazione di un utente potrebbero differire in base a chi sta effettuando la chiamata. Anche se ci sono molti componenti in comune, il giorno in cui devono essere registrate più informazioni per una chiamata da parte dell'agente, è necessario cambiare le cose un po '.

Quindi utilizzare due endpoint separati che hanno entrambi la stessa logica semplice, ovvero richiedere al livello dati di creare un nuovo utente con un parametro aggiuntivo per indicare se tale utente è confermato o meno. Se lo stato confermato è semplicemente un altro campo nella tabella utenti, sarà sufficiente impostare lo stato confermato in un caso e non nell'altro. Solo in uno dei due, eseguirai la logica di business aggiuntiva per seguire un'e-mail.

Questo stesso endpoint può anche gestire la conferma effettiva di detto utente.

Ciò che dovrebbe rimanere lo stesso è il livello dati. A meno che non vi siano differenze significative tra le due richieste (che non sembrano esserci), l'inserimento effettivo nel database dovrebbe essere sia stupido che semplice.

    
risposta data 21.12.2018 - 14:09
fonte

Leggi altre domande sui tag