Come si definiscono oggetti e repository di dominio, quando si ha a che fare con più tabelle di database?

3

Immagina un'applicazione che ti permetta di aggiungere elementi pubblicitari a un preventivo. Il risultato finale è come un addetto alle vendite che ti fornisce un foglio stampato con informazioni quali il nome dell'azienda, il nome della persona di vendita e vari articoli di servizio stampati sul preventivo insieme a prezzi, descrizione e quantità.

Per implementarlo a livello di database, ho tabelle Item (contiene 0-to-many items per Quote) e QuoteMeta (contiene meta-informazioni sulle virgolette come chi ha creato la citazione, il numero di preventivo, la revisione, lo stato, ecc).

PoihounoggettodominiochiamatoQuote,chenonèaconoscenzadirettamentedellivellodatabase,maricevedatisiadaItemsiadaQuoteMeta.IlQuoteèil"foglio preventivo" precedentemente descritto.

La mia domanda è come gestire questo oggetto dominio quando ho più di una tabella che lo rappresenta internamente. Ad esempio, con il mio oggetto dominio Quote posso fare qualcosa del tipo ...

Repository singolo, oggetto Dominio singolo

//Repository populates $quote from both database tables
$quote = (new QuoteRepository())->getQuoteById($id);

$quote->getQuoteNumber(); //gets data from quote metadata table
$quote->getItemByLineNumber(5); //gets an item from items table

Quanto sopra "sposa" le tabelle nell'oggetto Quote del dominio. QuoteRepository gestisce le query indirizzate ae da entrambe le tabelle del database. La mia domanda è ... posso farlo?

Ad esempio, sarà meglio tenere separati i concetti, forse così?

Repository multipli, oggetti di domini multipli

//repository strictly deals with quote meta data
$quoteMeta = (new QuoteMetaRepository())->getQuoteMetaById($id);
$quote->getQuoteNumber();

//repository strictly deals with item handling
$items = (new ItemRepository())->getItemsByQuoteId($id);
$items->getItemByLineNumber(5);

Qui le preoccupazioni sono più separate, ma ho complessità nel trattare con più oggetti, quando la rappresentazione fisica di Quote è tipicamente intesa come gli elementi + i metadati di citazione uniti insieme. Non hai solo articoli senza metadati e non ha molto senso avere metadati senza elementi di servizio.

Detto questo, è preferibile tenere separati i repository, o insieme? E se separato, come gestisco cose come le JOIN di tabella che operano su entrambe le tabelle? A quale repository vanno?

Gestione di più tabelle

Per cambiare un po 'le marce, ho qualche scopo del codice di cui eliminare un oggetto. Un record oggetto viene eliminato dalla tabella. Quindi i riferimenti ad altri dati che sono legati all'elemento vengono cancellati da altre 5 tabelle (cose come grafici, design, ecc. E altri dati che appartengono all'elemento). Se questa "eliminazione oggetto" fosse un metodo a singolo gestore che cancelli i dati da più tabelle direttamente nel posto di un metodo, o ogni tabella abbia il proprio rispettivo codice e classe del gestore di repository, e posso chiamare ciascun gestore per cancellare la loro porzione di l'articolo?

Inoltre, nell'esempio in cui elimino l'elemento, non mi interessa molto di QuoteMeta tabella o entità. Quindi potrei usare solo il ItemRepository handler da solo, il che mi spinge verso repository separati in questo caso.

Note su ORM

Nel mio codebase sto usando un ORM, dove ho entità, come Item Entità corrisponde a item tabella, e QuotaMeta corrisponde a quote_meta . Il focus della mia domanda però non è su un ORM. ORM fornisce un modo conveniente per popolare le mie entità dalle tabelle, ma senza ORM potrei comunque compilare Entità (cioè tramite mysqli_fetch_object ), altrimenti utilizzerei gli array. La domanda continua: come modellare i miei oggetti di dominio e i repository corrispondenti? Ho ... ne ho uno per tabella o vado a un livello più alto di astrazione, dove lavoro su più tabelle per singolo dominio / repository?

Considerazioni finali ..

Per essere super-specifico, ho un oggetto dominio Quote che opera su entrambe le tabelle, oppure ho separato ItemGroup e QuoteMeta oggetti, dove uno gestisce gli articoli che appartengono al Preventivo ma non fa t cura dei metadati e uno gestisce i metadati di Quote, senza occuparsi degli elementi che appartengono ad esso?

    
posta Dennis 28.02.2017 - 18:38
fonte

1 risposta

1

Il tuo primo approccio è fondamentalmente la creazione di un ORM. Se ORM è ciò che stai cercando, allora vai con esso, ma ricorda che gli oggetti dell'ORM non rappresentano e non dovrebbero rappresentare il tuo dominio - es. il livello che applica le regole aziendali presentate dagli stakeholder. Sono oggetti che capiscono la persistenza e come tali non dovrebbero contenere regole di business, perché ciò significherebbe infrangere il Principio di Responsabilità Unica, che non è una regola da seguire ciecamente, ma che aumenta notevolmente la leggibilità del codice.

Tenendo presente questo, il tuo livello di dominio non funziona con gli oggetti ORM, dovrai comunque trasformare gli oggetti ORM in oggetti di dominio, il che sembra un po 'inutile.

Apprezzo molto l'approccio del repository diretto, in quanto indica in modo molto chiaro cosa fa ogni oggetto:

  • un oggetto dominio rappresenta un'entità dominio,
  • un repository viene utilizzato per fornire un'astrazione alle operazioni CRUD su un oggetto dominio.

Hai un oggetto dominio e desideri più dati ad esso correlati, quindi usa un servizio che sa come comunicare con il mondo esterno, in questo caso il livello di persistenza.

Inoltre, evitando completamente l'ORM quando si interroga il database, si solleva il vincolo necessario per utilizzare gli oggetti ORM, cosa che non è possibile. Molte volte hai bisogno di rappresentazioni diverse della stessa entità, per scopi diversi, e per questo a volte puoi usare anche DTO molto semplici. Ciò semplifica la costruzione di tali oggetti, riduce l'ingombro della memoria e rende generalmente le applicazioni più veloci, perché è possibile creare query specifiche per ridurre il numero di volte che è necessario passare dal server delle applicazioni al server del database e viceversa.

    
risposta data 28.02.2017 - 21:06
fonte

Leggi altre domande sui tag