DDD, dove utilizzare i servizi di infrastruttura

5

Sto cercando di imparare DDD e sto avendo qualche problema con i servizi di infrastruttura.

In effetti, capisco a cosa mirano, ma non vedo dove si inseriscono all'interno della mia applicazione.

In realtà, sto avendo le seguenti cose

  • Un servizio di applicazione (API REST)
  • Alcuni servizi di dominio (gestiti con Pattern di specifica)
  • Alcuni servizi di infrastruttura (archivi e e-mail mittente)

Domanda 1 Mi chiedevo se fosse il ruolo del servizio di dominio da utilizzare (ovvero i servizi di infrastruttura inseriti nei servizi di dominio), qualcosa di simile (in un modo molto minimalista):

class UserDomainService {

  constructor (userRepository, emailService) {
    this.userRepository = userRepository
    this.emailService = emailService
  }

  saveUser (user) {
    /** Apply some business rules here ...*/
    const user = this.userRepository.save(user)
    this.emailService.send('New user added : ' + user.firstName)
  }

}

O dovrebbe essere il ruolo del servizio Applicazione, in questo modo:

class ApplicationService {

  constructor (userDomainService, userRepository, emailService) {
    this.userDomainService = userDomainService
    this.userRepository = userRepository
    this.emailService = emailService
  }

  postUser (user) {
    if (this.userDomainService.manageSomeRules(user)) {
      this.userRepository.save(user)
      this.emailService.send('New user added : ' + user.firstName)
      return user
    }
    return new RuleNotSatisfied()
  }

}

Domanda 2

Chi è responsabile della conversione dell'utente ricevuto, dagli endpoint POST (API REST), a una buona entità?

MODIFICA sulla domanda 2: Che tipo di servizio può convertire Entity in DTO e viceversa? Dove dovrei metterli?

    
posta mfrachet 07.09.2016 - 08:12
fonte

2 risposte

3

Domanda 1

Va bene che il servizio di dominio utilizzi i servizi di infrastruttura, se i servizi di infrastruttura accettano e restituiscono concetti di dominio - entità e oggetti valore.

Inoltre, i servizi di dominio dovrebbero incapsulare una parte della logica aziendale che non può rientrare in un'entità. Quindi saveUser non è un ottimo metodo per un servizio di dominio.

La domanda da porsi è - sta inviando un'email a un importante concetto di dominio? Email è un'entità nel tuo dominio? In tal caso, potresti avere un'interfaccia per un mittente dell'e-mail definito nel tuo livello di dominio, con un'implementazione separata nel livello infrastruttura e potresti fare in modo significativo quanto segue in un servizio di dominio -:

sendEmailIfWhiteListed(id) {
    Email = this.emailRepository.get(id);
    if (email.isWhiteListed) {
        this.emailSender.send(email);
    }
}

Ma è ragionevole solo se le email sono entità nel tuo dominio. Se non lo sono, allora pensa: perché inviare l'e-mail alla responsabilità di salvare l'utente?

Nel tuo caso, non sembra che le email siano entità nella tua lingua ubiquitaria . Quindi, qui preferisco il schema degli eventi di dominio . La creazione di un nuovo utente dovrebbe generare un evento di dominio NewUserCreated e il gestore per l'evento di dominio, che inserirò nel livello applicazione, delegherebbe a un mittente dell'e-mail per inviare l'e-mail.

Domanda 2

Chi è responsabile della conversione dei dati dei post in un'entità significativa? Dipende da cosa stai facendo:

  1. Se aggiungi un nuovo utente
    1. Se si tratta di una logica semplice, il servizio dell'applicazione può chiamare new Entity() e passare argomenti di dominio significativi (oggetti di valore) mappati dall'argomento% a% di%
    2. Se si tratta di una logica complessa, è possibile utilizzare uno speciale servizio di dominio denominato factory con data e di nuovo, passare in argomenti di dominio significativi (oggetti di valore) mappati dall'argomento% a% di%
    3. In entrambi i casi, l'entità o la factory non dovrebbero essere a conoscenza della struttura di this.entityFactory.Create() in quanto questa è una preoccupazione di api
  2. Se si aggiorna un utente
    1. il servizio applicativo dovrebbe utilizzare un repository per ottenere l'utente esistente
    2. l'utente dovrebbe avere metodi per aggiornare i dati rilevanti. Ma vorrei evitare i metodi in stile CRUD come data - pensa a perché i dati utente vengono aggiornati? DDD ci incoraggia a pensare ai processi e agli obiettivi aziendali.
      1. L'utente viene aggiornato perché ha partecipato a qualche processo aziendale? Quindi modellare esplicitamente il processo aziendale e modificare i dati dell'utente come un effetto collaterale del processo
      2. L'utente viene aggiornato a causa di una semplice interazione CRUD, ad esempio la modifica di una pagina del profilo? Anche così, incoraggerei un metodo di entità come data per essere esplicito sullo scopo dell'operazione.

DDD è tutto sulla lingua - ascolta la lingua utilizzata dagli esperti di dominio, concorda su un ubiquitious linguaggio e usalo fedelmente nel tuo codice. Se gli esperti del tuo dominio non dicono user.update o user.UpdateProfile , non utilizzare queste parole nel tuo livello dominio.

    
risposta data 07.09.2016 - 21:24
fonte
2

Penso che la risposta DDD sia la prima. Metti la logica nell'oggetto dominio. Inietti servizi se necessario.

Avrei un altro 'hosting layer' per convertire il messaggio in arrivo nell'oggetto dominio

Il livello applicazione utilizza gli oggetti dominio per ottenere l'effetto richiesto.

Tuttavia. Non penso che il DDD si adatti molto bene al modello di servizio. Nella mia mente la logica spesso appartiene al servizio, non all'oggetto dominio.

vale a dire. Avrei RecordPlayer.PlayRecord(record) piuttosto che Record.Play()

Inoltre, la natura di questi servizi è che sono apolidi, io suono un disco, restituisco il risultato e butto via tutto.

Mentre in un'app desktop, DDD funziona meglio. Potrei avere diversi record istanziati ed eseguire varie funzioni su di essi nel tempo. Ricevi dallo scaffale, giocare, mettere in pausa, ecc. Il codice di stile DDD corrisponde alle azioni dell'utente e al processo di pensiero. 'Io suono questo disco' - > record.Play()

    
risposta data 07.09.2016 - 09:31
fonte

Leggi altre domande sui tag