OOP e database relazionali [duplicati]

4

Vedo molte parole nel mondo OOP su principi e leggi come Apri / Chiudi e Accoppiamento sciolto , posso capire come siano così apprezzati, Tuttavia, mi sembra che si sia imbattuto in un problema con l'applicazione di questi principi e leggi una volta che comincio a includere i database relazionali.

Ad esempio, se ho un'applicazione che siamo in grado di separare bene in più componenti (design Apri / Chiudi ) e consentire loro di lavorare tra loro, se necessario, comincio a incorrere in problemi quando si cerca di applicare integrità referenziale . Se imposto una configurazione relazionale e impone l'integrità tramite chiavi esterne e così via, le tabelle diventano dipendenti l'una dall'altra, gradualmente la logica dell'applicazione OOP inizia a cadere a pezzi e diventa un unico grande sistema.

Ovviamente posso rimuovere tutti i riferimenti alle tabelle, ma poi rischio di rendere i dati ridondanti e di iniziare a ripetere codice / dati, che quindi va contro il principio Non ripetere te stesso.

Ci sono già stati problemi simili? Se sì, come hai fatto a gestirlo? Forse c'è un modo per ottenere sia l'integrità referenziale sia i componenti di apertura / chiusura OOP.

Grazie

    
posta cecilli0n 21.02.2014 - 22:19
fonte

3 risposte

2

Il mio suggerimento:

Devi imporre l'integrità referenziale con FK. Lascia che l'RDBMS funzioni e lascia che le classi generino eccezioni.

Le tabelle correlate non hanno nulla a che fare con l'accoppiamento di classi o principi SOLID. È roba delle classi.

Le tabelle sono ortogonali alle classi.

Non sovraccaricare le cose.

    
risposta data 22.02.2014 - 07:02
fonte
1

Prima di tutto: hai ragione, questo è un vero problema. Poiché spesso i problemi di progettazione emergono quando provi a testare cose. Sebbene il test sia per la maggior parte del tempo abbastanza facile se si hanno alcune capacità di progettazione e un codice basato su OOP, le cose diventano complicate quando il database viene coinvolto.

Un sintomo è che se vuoi avere un'entità A (cioè un oggetto persistente in un database) hai bisogno dell'intero albero delle dipendenze e non hai un modo semplice per deriderle.

La ragione di questo tipo di problema è che non esiste alcuna separazione tra runtime e tempo di compilazione nei database, quindi una dipendenza che si desidera avere / utilizzare in runtime è sempre presente.

Una soluzione teorica è creare un sistema di database che abbia in realtà qualcosa di simile alle interfacce. Ma probabilmente è fuori portata per la maggior parte di noi.

La soluzione più realistica è quella di separare il database in modo molto rigoroso dal resto del codice, isolando così il grande blob contorto che viene comunemente definito schema del database dall'applicazione ben strutturata.

Il primo passo è quello di avere i repository che restituiscono le tue entità e non perdono nessuna informazione su dove e come queste entità vengono mantenute. Un buon modo per garantire questo è avere due implementazioni di quelli: uno in realtà utilizza il tuo database e uno che usa ad esempio semplici HashMaps per l'archiviazione. I successivi sono anche molto utili per i test. Diffidare di eventuali strutture che sanguinano nel codice del dominio. L'ibernazione, ad esempio, ha l'abitudine di farlo tramite il caricamento lento e meccanismi simili.

Il secondo passo è identificare gli aggregati nel senso di Domain Driven Design. Cioè sacche di entità che vengono controllate da un'entità e dal suo repository, la root dell'entità. Ad esempio, LineItems of Orders dovrebbe probabilmente essere caricato e aggiornato solo tramite un Ordine, mai da solo. Ma le entità che appartengono a un aggregato diverso (ad esempio i clienti) dovrebbero essere caricate tramite il proprio repository e non tramite una sorta di caricamento lazy magico sulla navigazione. In questo modo puoi memorizzare diverse entità in diversi datastore, alla tua applicazione non interessa. Se si trovano nello stesso database (come probabilmente fanno) possono avere chiavi esterne, nessun problema.

Potrebbe esserci una sfida tecnica con questo approccio causato dai vincoli: i vincoli normali vengono applicati su ogni singola istruzione DML. Se ciò causa problemi, potresti considerare vincoli posticipati che vengono applicati solo al commit. Ciò potrebbe effettivamente migliorare le prestazioni, ma potrebbe anche rendere più difficile il debug, perché ora potresti ottenere violazioni delle chiavi esterne sul commit, molto tempo dopo che sono state eseguite le tue dichiarazioni DML.

    
risposta data 22.02.2014 - 07:57
fonte
0

Penso che OOP e RDBMS non siano buoni amici. OOP mi sembra più adatto a gestire "righe" in ogni tabella. RDBMS si occupa di "set di righe".

Tuttavia, ci sono molti framework che cercano di superare questi problemi, ma perdono la "purezza" di OOP.

    
risposta data 21.02.2014 - 22:43
fonte

Leggi altre domande sui tag