Dove dovrebbe andare la logica aziendale in un'architettura a più livelli?

5

Prima di tutto, non sto parlando di validazione nel senso del nullability o della lunghezza di un campo come in questo e questo domande dove possiamo utilizzare i metodi isValid () nelle business class o un validatore esterno. Tuttavia, la mia domanda è correlata alla convalida o meno nelle lezioni di business. Utilizzo uno stile di architettura a livelli con servizi che utilizzano il livello dell'origine dati e interagiscono con il modello di dominio.

Facendo semplicemente i requisiti del dominio, supponiamo di avere film e recensioni e gli utenti possono fare solo una recensione per film. Quindi, una seconda recensione è un oggetto valido ma le regole aziendali non dovrebbero consentire il completamento della revisione.

Quindi, potrei fare:

ReviewService >> addReview(review,movie)
  loggedUser = getLoggedUser()
  review = reviewRepository.searchReviewFrom(loggedUser,movie)
  if (review == null)
    reviewRepository.save(review)
  else
    // some mechanism to inform the error, it could be NotificationPattern

Oppure:

Movie >> addReview(review)
   for r in this.reviews
     if r.user = review.user
       throw ReviewAlreadyUploaded
   // if no expcetion is thrown
   this.reviews.add(review)

Penso che la convalida oneReviewPerUser sia una regola puramente aziendale, e dovrebbe andare nelle classi business, in questo caso nella classe Movie. Quindi le regole aziendali sono contenute nel dominio e non sparse tra i livelli. Tuttavia, se gli elenchi di recensioni dei film sono grandi in quasi tutti i casi, questa opzione implica la query e crea un'istanza di un numero elevato di oggetti Review e itera su tutti gli elementi.

Supponiamo che io scelga l'opzione 1, devo assicurare che ogni cliente che vuole creare una recensione per un filmato deve utilizzare il servizio, perché potrebbe violare il vincolo aziendale di 1 recensione per utente se, ad esempio, si usa direttamente il ReviewRepository. Questo inizia a sembrare un livello di servizi con tutta la logica aziendale e un AnemicModel con classi di dominio che sono insiemi di attributi per trasportare dati da e verso il database.

Dove si trova la linea che separa la logica aziendale che dovrebbe essere su Servizi da quella che dovrebbe essere su Classi di dominio.

    
posta gabrielgiussi 12.07.2015 - 21:48
fonte

2 risposte

3

In un'applicazione DDD (Domain Driven Design) che utilizza un'architettura a strati convenzionale, la logica di business entra nel livello dominio . Ora, tieni presente che questo livello non contiene solo le entità di dominio ( Movie , Review ), ma anche servizi di dominio (come una classe ReviewService ) e gli archivi. Quindi, ReviewService è anche una classe business.

La tua preoccupazione per ogni cliente che ha di utilizzare il metodo commerciale appropriato ( addReview ) non è realistico. Non esiste un modo pratico per evitare che una classe di client scritta male stia violando le regole aziendali, se gli sviluppatori non si attengono alle regole dell'architettura scelta. Ad esempio, se Movie ha un metodo getReviews() (o una proprietà reviews ) che espone una collezione mutevole di recensioni, il codice cliente può sempre aggiungere una revisione arbitraria. E anche se è immutabile, il codice cliente può sempre creare Review non valido nel database utilizzando direttamente un repository.

A mio parere, è meglio avere solo metodi di business relativamente semplici nelle entità di dominio, e di solito solo per le operazioni di sola lettura. La logica aziendale più complessa viene assegnata al meglio alle classi di servizi di dominio coesive. Altrimenti, le tue classi di entità diventeranno rapidamente troppo grandi e complesse. Quindi, ad esempio, un'operazione commerciale che aggiunge una recensione di un film soggetta a regole di convalida aziendale sarebbe meglio inserirla in una classe di servizio di dominio ReviewMaintenance o anche in una classe di ReviewCreation se l'operazione "aggiungi recensione" è sufficientemente complessa. / p>     

risposta data 12.07.2015 - 23:09
fonte
1

Stai tralasciando la possibilità di limitare l'input nel database. Se in effetti può esserci solo una recensione di un determinato film da parte di un particolare utente, questo dovrebbe essere un vincolo del database. Se lo fai, la tua preoccupazione è come gestire un tentativo fallito di inserire una seconda recensione: come viene segnalato all'utente.

    
risposta data 13.07.2015 - 03:14
fonte

Leggi altre domande sui tag