Perché abbiamo bisogno di oggetti entità? [chiuso]


139

Devo davvero vedere un dibattito onesto e ponderato sui meriti del paradigma di progettazione di applicazioni aziendali attualmente accettato .

Non sono convinto che dovrebbero esistere oggetti entità.

Per oggetti entità intendo le cose tipiche che tendiamo a costruire per le nostre applicazioni, come "Persona", "Account", "Ordine", ecc.

La mia attuale filosofia progettuale è questa:

  • Tutti gli accessi al database devono essere effettuati tramite procedure memorizzate.
  • Ogni volta che sono necessari dati, chiamare una procedura memorizzata e scorrere su un SqlDataReader o sulle righe in una DataTable

(Nota: ho anche creato applicazioni enterprise con Java EE, gente Java si prega di sostituire l'equivalente per i miei esempi .NET)

Non sono anti-OO. Scrivo molte classi per scopi diversi, non solo entità. Devo ammettere che gran parte delle classi che scrivo sono classi di supporto statiche.

Non sto costruendo giocattoli. Sto parlando di applicazioni transazionali di grandi volumi distribuite su più macchine. Applicazioni Web, servizi Windows, servizi Web, interazione b2b, il nome.

Ho usato OR Mapper. Ne ho scritti alcuni. Ho usato lo stack Java EE, CSLA e alcuni altri equivalenti. Non solo le ho utilizzate, ma ho sviluppato e mantenuto attivamente queste applicazioni in ambienti di produzione.

Sono giunto alla conclusione battaglia-testato che oggetti entità sono sempre nel nostro modo, e la nostra vita sarebbe così molto più facile senza di loro.

Considera questo semplice esempio: ricevi una chiamata di supporto su una determinata pagina della tua applicazione che non funziona correttamente, forse uno dei campi non viene persistito come dovrebbe essere. Con il mio modello, lo sviluppatore assegnato per trovare il problema apre esattamente 3 file . Un ASPX, un ASPX.CS e un file SQL con la procedura memorizzata. Il problema, che potrebbe essere un parametro mancante alla chiamata della procedura memorizzata, richiede alcuni minuti per essere risolto. Ma con qualsiasi modello di entità, invaderai inevitabilmente il debugger, inizierai a sfogliare il codice e potresti finire con 15-20 file aperti in Visual Studio. Quando scendi in fondo alla pila, ti sei dimenticato da dove hai iniziato. Possiamo solo tenere così tante cose in testa contemporaneamente. Il software è incredibilmente complesso senza aggiungere livelli inutili.

La complessità dello sviluppo e la risoluzione dei problemi sono solo un aspetto della mia lamentela.

Ora parliamo di scalabilità.

Gli sviluppatori si rendono conto che ogni volta che scrivono o modificano qualsiasi codice che interagisce con il database, devono fare un'analisi approfondita dell'impatto esatto sul database? E non solo la copia di sviluppo, intendo un mimico della produzione, quindi puoi vedere che la colonna aggiuntiva che ora richiedi per il tuo oggetto ha invalidato il piano di query corrente e che un rapporto in esecuzione in 1 secondo ora richiederà 2 minuti, solo perché hai aggiunto una singola colonna all'elenco di selezione? E risulta che l'indice di cui hai bisogno ora è così grande che il DBA dovrà modificare il layout fisico dei tuoi file?

Se lasci che le persone si allontanino troppo dall'archivio di dati fisici con un'astrazione, creeranno il caos con un'applicazione che deve essere ridimensionata.

Non sono un fanatico. Posso essere convinto se sbaglio, e forse lo sono, dal momento che c'è una forte spinta verso Linq verso Sql, ADO.NET EF, Hibernate, Java EE, ecc. Ti prego di pensare attraverso le tue risposte, se mi manca qualcosa che voglio davvero sapere di cosa si tratta e perché dovrei cambiare il mio modo di pensare.

[Modificare]

Sembra che questa domanda sia improvvisamente di nuovo attiva, quindi ora che abbiamo la nuova funzione di commento ho commentato direttamente diverse risposte. Grazie per le risposte, penso che questa sia una discussione salutare.

Probabilmente avrei dovuto essere più chiaro che sto parlando di applicazioni aziendali. Non posso davvero commentare, per esempio, un gioco in esecuzione sul desktop di qualcuno o un'app mobile.

Una cosa che devo mettere qui in alto in risposta a diverse risposte simili: l'ortogonalità e la separazione delle preoccupazioni sono spesso citate come ragioni per andare entità / ORM. Le procedure memorizzate, per me, sono il miglior esempio di separazione delle preoccupazioni a cui posso pensare. Se si proibisce qualsiasi altro accesso al database, tranne che attraverso le procedure memorizzate, si potrebbe teoricamente riprogettare l'intero modello di dati e non violare alcun codice, purché si mantengano gli input e gli output delle procedure memorizzate. Sono un perfetto esempio di programmazione per contratto (solo se si evita "seleziona *" e si documentano i set di risultati).

Chiedi a qualcuno che è stato nel settore da molto tempo e ha lavorato con applicazioni di lunga durata: quanti strati di applicazioni e interfaccia utente sono andati e venuti mentre un database ha vissuto? Quanto è difficile ottimizzare e riformattare un database quando vi sono 4 o 5 diversi livelli di persistenza che generano SQL per ottenere i dati? Non puoi cambiare nulla! Gli ORM o qualsiasi codice che genera SQL bloccano il database in pietra .


Dalla lettura della tua domanda, siamo molto simili e mi chiedo esattamente la stessa cosa da anni ormai (da quando ho sentito parlare di framework di entità di terze parti e ora di Microsoft)
pearcewg

1
Stai dicendo che la logica di business è gli oggetti helper o nei proc memorizzati? Sto chiedendo come molte persone sembrano pensare che stai dicendo in seguito ... ma quello che penso tu stia dicendo è che hai ancora la logica di business negli oggetti codificati, stai semplicemente ottenendo i dati direttamente dal database e usando quei dati , piuttosto che un ORM o la mappatura su oggetti specializzati per contenere i dati. Tendo a sentirmi allo stesso modo, ma sto anche valutando EF4 per vedere se ne potrebbe valere la pena.
alchemico

"I consumatori innovatori sono spesso quelli che vengono fregati". - qualcuno con esperienza
Uğur Gümüşhan,

Ho ereditato un sistema con oltre 2500 SPROC in cui l'applicazione è vista semplicemente come un mezzo per attivare gli SPROC e dare un senso al loro output. Ogni dato letto e scritto ha il proprio SPROC. Non ci sono punti di controllo centrali. È orribile e malleabile come il granito. Considero l'ottimizzazione dei database. I 2500 SPROCS mi hanno messo al mio posto. Rispetto a un sistema con un livello di dominio ben organizzato e un codice DAL riutilizzabile, sembra mal concepito ed è un incubo di supporto. Compiti semplici richiedono ore e stanno distruggendo l'anima. Gli SPROC devono essere utilizzati per carichi elevati o metodi speciali IMO
trucker_jim

Informazioni sul tuo esempio di "debug": con i unit test, sapresti molto più rapidamente dove le cose vanno male.
MarioDS,

Risposte:


59

Penso che dipenda da quanto sia complicata la "logica" dell'applicazione e da dove l'hai implementata. Se tutta la tua logica è nelle procedure memorizzate, e tutto ciò che la tua applicazione fa è chiamare quelle procedure e visualizzare i risultati, lo sviluppo di oggetti di entità è davvero una perdita di tempo. Ma per un'applicazione in cui gli oggetti hanno interazioni complesse tra loro e il database è solo un meccanismo di persistenza, può esserci valore avere tali oggetti.

Quindi, direi che non esiste una risposta valida per tutti. Gli sviluppatori devono essere consapevoli che, a volte, provare a essere troppo OO può causare più problemi di quanti ne risolva.


Kristopher sembra che tu abbia resuscitato questa domanda collegandola ad un'altra domanda. Mi chiedo cosa intendi per "interazioni ricche" e come sarebbe poco pratico implementarle senza oggetti?
Eric Z Beard,

4
Tutto ciò che può essere fatto con oggetti può anche essere fatto senza oggetti. Trovo che la progettazione OO sia di solito molto più semplice dei metodi non OO per fare qualcosa di "complicato", ma capisco che non funziona per tutti.
Kristopher Johnson,

Sono d'accordo - la risposta di "quando usare gli oggetti" dipende dal fatto che le proprietà degli oggetti possano richiedere o meno azioni o cambiamenti nella logica aziendale. Ad esempio, le istanze utente o persona potrebbero avere Password e LoginName -> le azioni del codice cambiano in base a quali sono i valori in esse. Al contrario, se avessi un prodotto, avresti dovuto visualizzare (niente di più, nessuna altra azione) che ottenere un DataSet da db e creare semplicemente la GUI.
Yordan Georgiev,

5
C'è un equilibrio. Evita la religione e scegli ciò che funziona.
Jeff Davis,

27

La teoria afferma che le implementazioni altamente coerenti e vagamente accoppiate sono la via da seguire.

Quindi suppongo che tu stia mettendo in dubbio tale approccio, vale a dire separando le preoccupazioni.

Il mio file aspx.cs dovrebbe interagire con il database, chiamare uno sproc e comprendere IDataReader?

In un ambiente di squadra, specialmente dove ci sono meno persone tecniche che si occupano della parte aspx dell'applicazione, non ho bisogno che queste persone siano in grado di "toccare" queste cose.

Separare il mio dominio dal mio database mi protegge dalle modifiche strutturali del database, sicuramente una cosa positiva? L'efficacia del database è assolutamente importante, quindi lascia che qualcuno che sia il più eccellente in quella roba gestisca quella roba, in un posto, con il minor impatto possibile sul resto del sistema.

A meno che non fraintenda il vostro approccio, un cambiamento strutturale nel database potrebbe avere una vasta area di impatto con la superficie della vostra applicazione. Vedo che questa separazione delle preoccupazioni consente a me e al mio team di minimizzarlo. Inoltre, ogni nuovo membro del team dovrebbe comprendere meglio questo approccio.

Inoltre, il tuo approccio sembra sostenere la logica di business della tua applicazione per risiedere nel tuo database? Questo mi sembra sbagliato, SQL è davvero bravo a interrogare i dati e non a esprimere la logica aziendale.

Pensiero interessante, anche se mi sento a un passo da SQL nell'aspx, che dai miei brutti vecchi tempi non strutturati, mi riempie di terrore.


Sono d'accordo sul fatto che avere un sacco di SQL dinamico sparsi in tutto il code-behind sia male. Devi mantenere le chiamate Db chiare e distinte. L'avvolgimento delle chiamate sproc nei metodi di supporto statici consente di ottenere una sorta di separazione senza scendere lungo la rotta ORM.
Eric Z Beard,

1
Anche se non ho mai lavorato in un ambiente asp, sono sicuro che alcune delle persone meno tecniche lascerebbero a bocca aperta i calzini con un codice javascript sul lato client, il che si traduce in una bella esperienza utente indipendentemente da qualsiasi interfaccia scadente al retro tecnico -fine.
crowne,

Sono d'accordo con te qui e sono stato conosciuto per fare anche un po 'di javascript sul lato client, il che ha provocato un'esperienza utente non troppo squallida, anche se lo dico io stesso. Mi piacerebbe pensare che le interfacce back-end non siano pessime e che i programmatori lato client non debbano preoccuparsi di nulla, perché ho cercato di separare le mie preoccupazioni.
nachojammers,

2
"Mi sembra sbagliato, SQL è davvero bravo a interrogare i dati e non a esprimere la logica di business". - A meno che tu non usi, per esempio, PL / SQL, che aggiunge un ricco linguaggio di programmazione sopra (e strettamente integrato con) l'SQL, e il tuo codice è archiviato all'interno del database. Aumenta le prestazioni evitando roundtrip di rete. E incapsula la tua logica aziendale indipendentemente dal client che si collega al database.
ObiWan Kenobi,

25

Un motivo: separare il modello di dominio dal modello di database.

Quello che faccio è usare Test Driven Development, quindi scrivo prima i miei livelli UI e Model e il livello Data è deriso, quindi l'interfaccia utente e il modello sono costruiti attorno a oggetti specifici del dominio, quindi in seguito li associo a qualsiasi tecnologia che sto usando il livello dati. È una cattiva idea lasciare che la struttura del database determini la progettazione della tua applicazione. Laddove possibile, scrivi prima l'app e lascia che influenzi la struttura del tuo database, non viceversa.


9
Devo dire che non sono affatto d'accordo, almeno per le applicazioni aziendali. I dati sono l'applicazione.
Eric Z Beard,

3
perché vorresti avere due modelli separati degli stessi dati?
Seun Osewa,

3
Perché per alcuni scopi, un'interpretazione del modello può essere più adatta. Alcune logiche funzionano molto meglio sugli oggetti che sulle righe.
Wouter Lievens,

1
Penso che sia una buona idea implementata male.
Jeff Davis,

21

Per me si riduce a non voglio che la mia domanda riguardasse il modo in cui i dati sono archiviati. Probabilmente verrò schiaffeggiato per aver detto questo ... ma la tua applicazione non è i tuoi dati, i dati sono un artefatto dell'applicazione. Voglio che la mia applicazione stia pensando in termini di Clienti, Ordini e Articoli, non una tecnologia come DataSet, DataTables e DataRows ... perché chissà per quanto tempo rimarranno.

Concordo sul fatto che esiste sempre una certa quantità di accoppiamento, ma preferisco che l'aggancio raggiunga verso l'alto piuttosto che verso il basso. Riesco a modificare gli arti e le foglie di un albero più facilmente di quanto possa modificare il suo tronco.

Tendo a riservare sprocs per la segnalazione poiché le query tendono a diventare un po 'più cattive dell'accesso ai dati generali delle applicazioni.

Tendo anche a pensare con un corretto test unitario all'inizio che quello scenario è come se una colonna non persistente non fosse probabilmente un problema.


3
"la tua applicazione non è i tuoi dati, i dati sono un artefatto dell'applicazione." - L'applicazione è inutile senza i dati. I dati hanno un grande valore senza l'applicazione. Le applicazioni vanno e vengono (vengono riscritte) continuamente, i dati in qualsiasi applicazione non banale vengono sempre conservati. E il modello di dati rimane sorprendentemente stabile nel tempo.
ObiWan Kenobi,

16

Eric, sei morto. Per qualsiasi applicazione davvero scalabile / facilmente gestibile / robusta, l'unica vera risposta è quella di rinunciare a tutta la spazzatura e attenersi alle basi.

Ho seguito una traiettoria simile con la mia carriera e sono giunto alle stesse conclusioni. Certo, siamo considerati eretici e guardiamo divertente. Ma la mia roba funziona e funziona bene.

Ogni riga di codice dovrebbe essere guardata con sospetto.


2
certo, funziona sicuramente bene quando hai tonnellate di personale e risorse, ma penso che se sei un team di un uomo, pensare che le "nuove" tecniche possano aiutare molto ..
Carl Hörberg

10

Vorrei rispondere con un esempio simile a quello che hai proposto.

Nella mia azienda ho dovuto creare una semplice sezione CRUD per i prodotti, ho creato tutte le mie entità e un DAL separato. Successivamente un altro sviluppatore ha dovuto modificare una tabella correlata e ha anche rinominato diversi campi. L'unico file che ho dovuto modificare per aggiornare il mio modulo era il DAL per quella tabella.

Ciò che (a mio avviso) le entità portano a un progetto è:

Ortogonalità: le modifiche in un livello potrebbero non influire su altri livelli (ovviamente, se si apportano modifiche enormi al database, si incrocerebbero su tutti i livelli, ma la maggior parte delle piccole modifiche no).

Testabilità: puoi testare la tua logica senza toccare il database. Ciò aumenta le prestazioni dei test (consentendoti di eseguirli più frequentemente).

Separazione delle preoccupazioni: in un grande prodotto è possibile assegnare il database a un DBA e lui può ottimizzarlo. Assegnare il modello a un esperto aziendale che abbia le conoscenze necessarie per progettarlo. Assegnare moduli individuali a sviluppatori più esperti di moduli Web ecc.

Infine, vorrei aggiungere che la maggior parte dei mapper ORM supportano le procedure memorizzate poiché è quello che si sta utilizzando.

Saluti.


2
Le procedure memorizzate sono probabilmente il miglior esempio di ortogonalità e separazione delle preoccupazioni. Se utilizzati correttamente, incapsulano completamente il database.
Eric Z Beard,

1
@Eric Z Beard: Sì, ma come si possono scrivere test unitari sulle procedure memorizzate isolando solo la logica all'interno della procedura memorizzata? Le procedure memorizzate sono strettamente collegate alla base di dati e alla maggior parte di noi tipi ORM non piace. Per scrivere un test unitario per una procedura memorizzata, è necessario fare affidamento su determinati dati per essere nel database. e non è possibile rieseguire questo test più e più volte senza tale dipendenza dei dati. Quel test che scriveresti non sarebbe più un test unitario ma sarebbe invece un Test di integrazione.
settimane

8

Penso che potresti "mordere più di quello che puoi masticare" su questo argomento. Ted Neward non era irriverente quando lo chiamò il " Vietnam dell'informatica ".

Una cosa che ti posso assolutamente garantire è che non cambierà il punto di vista di nessuno sulla questione, come è stato dimostrato così spesso su innumerevoli altri blog, forum, podcast ecc.

È certamente ok avere una chiara delusione e un dibattito su un argomento controverso, è solo che questo è stato fatto così tante volte che entrambe le "parti" hanno deciso di non essere d'accordo e hanno appena iniziato a scrivere software.

Se vuoi fare qualche altra lettura su entrambi i lati, vedi gli articoli sul blog di Ted, Ayende Rahein, Jimmy Nilson, Scott Bellware, Alt.Net, Stephen Forte, Eric Evans ecc.


1
Hai ragione, molte persone non cambieranno le loro opinioni. Mi rendo conto che l'obiettivo di Stack Overflow dovrebbe essere una domanda oggettiva, ma quelle soggettive sono molto più divertenti! Personalmente, ho imparato molto da questa discussione.
Eric Z Beard,

Penso che i vari approcci siano specifici del contesto e che questa discussione possa servire a chiarire quali scenari traggono beneficio o sminuiscono dai diversi modelli di persistenza. Gli esperti sull'argomento non cambieranno rapidamente le loro opinioni, ma questo è un sito di domande in cui le persone cercano altre esperienze.
TheXenocide,

Wow. +1 per il link all'articolo "Vietnam of Computer Science" che presenta un'eccellente introduzione al tema ORM vs. non ORM.
lambacck,

7

@Dan, scusa, non è il genere di cosa che sto cercando. Conosco la teoria. La tua affermazione "è una pessima idea" non è supportata da un vero esempio. Stiamo provando a sviluppare software in meno tempo, con meno persone, con meno errori e vogliamo la possibilità di apportare facilmente modifiche. Il tuo modello multi-layer, secondo la mia esperienza, è negativo in tutte le categorie di cui sopra. Soprattutto per quanto riguarda il rendere il modello di dati l'ultima cosa che fai. Il modello di dati fisici deve essere una considerazione importante dal primo giorno.


caspita, qualcun altro che pensa come me su questo ... le mie app riguardano quasi sempre la manipolazione dei dati, ecco cosa fanno realmente.
alchemico

Sarebbe meglio come commento ora che quelle funzionalità sono disponibili
Casebash

1
Scusami se sono pedante, ma dato che questa è una domanda popolare e l'errore che hai fatto è comune, ho pensato di doverlo sottolineare. "Meno tempo" è corretto, ma "meno persone" e "meno errori" dovrebbero essere "meno persone" e "meno errori". Se hai meno farina, puoi fare meno biscotti. (Inoltre, se usi troppa farina, creerai troppi biscotti - una distinzione meno comunemente dimenticata.) Ancora una volta, mi scuso; sto solo cercando di essere d'aiuto.
WCWedin

4

Ho trovato la tua domanda davvero interessante.
Di solito ho bisogno di oggetti entità per incapsulare la logica aziendale di un'applicazione. Sarebbe davvero complicato e inadeguato inserire questa logica nel livello dati.
Cosa faresti per evitare questi oggetti entità? Quale soluzione hai in mente?


Sarebbe meglio come commento
Casebash il

4

Entity Objects può facilitare la memorizzazione nella cache a livello di applicazione. Buona fortuna nella memorizzazione nella cache di un cacciatore.


4

Dovremmo anche parlare del concetto di cosa siano realmente le entità. Quando leggo questa discussione, ho l'impressione che molte persone qui guardino le entità nel senso di un modello di dominio anemico . Molte persone stanno considerando l'Anemic Domain Model come un antipattern!

C'è valore nei modelli di dominio avanzati. Questo è il Domain Driven Design . Personalmente credo che OO sia un modo per conquistare la complessità. Ciò significa non solo complessità tecnica (come accesso ai dati, interfaccia utente, sicurezza ...) ma anche complessità nel dominio aziendale !

Se possiamo applicare le tecniche OO per analizzare, modellare, progettare e implementare i nostri problemi aziendali, questo è un enorme vantaggio per la manutenibilità e l'estensibilità di applicazioni non banali!

Esistono differenze tra le entità e le tabelle. Le entità dovrebbero rappresentare il tuo modello, le tabelle rappresentano solo l'aspetto dei dati del tuo modello!

È vero che i dati vivono più a lungo delle app, ma considera questa citazione di David Laribee : i modelli sono per sempre ... i dati sono un felice effetto collaterale.

Alcuni altri collegamenti su questo argomento:


1
Francamente, sto iniziando a credere che i dati vivano più a lungo del software che li circonda, perché spesso viene prestata così poca attenzione alla progettazione del software lungo una vera comprensione del business.
flq

4

Domanda davvero interessante. Onestamente non posso dimostrare perché le entità siano buone. Ma posso condividere la mia opinione sul perché mi piacciono. Codice come

void exportOrder(Order order, String fileName){...};

non preoccupa da dove provenga l'ordine: da DB, da richiesta web, da unit test, ecc. Rende questo metodo più esplicitamente dichiarato ciò che richiede esattamente, invece di prendere DataRow e documentare quali colonne si aspetta di avere e quali tipi dovrebbero essere. Lo stesso vale se lo si implementa in qualche modo come procedura memorizzata: è comunque necessario inviare l'ID record ad esso, mentre non è necessario che sia presente nel DB.

L'implementazione di questo metodo verrebbe effettuata in base all'astrazione dell'Ordine, non in base a come è presentato esattamente nel DB. La maggior parte di tali operazioni che ho implementato in realtà non dipende da come questi dati vengono archiviati. Capisco che alcune operazioni richiedono l'accoppiamento con la struttura DB per scopi di perfomance e scalabilità, solo nella mia esperienza non ce ne sono troppe. Nella mia esperienza molto spesso è sufficiente sapere che Person ha .getFirstName () che restituisce String e .getAddress () che restituisce Indirizzo e indirizzo ha .getZipCode (), ecc. - e non importa quali tabelle sono coinvolte per archiviare quei dati .

Se devi affrontare i problemi che hai descritto, come quando ulteriori interruzioni di colonna segnalano prestazioni, allora per le tue attività il DB è una parte critica e in effetti dovresti essere il più vicino possibile. Mentre le entità possono fornire alcune utili astrazioni, possono anche nascondere alcuni dettagli importanti.

La scalabilità è un punto interessante qui - la maggior parte dei siti Web che richiedono un'enorme scalabilità (come Facebook, Livejournal, Flickr) tendono ad usare l'approccio ascetico del DB, quando il DB è usato il più raro possibile e i problemi di scalabilità sono risolti dalla cache, specialmente dall'utilizzo della RAM. http://highscalability.com/ contiene alcuni articoli interessanti.


2
La scalabilità nelle applicazioni aziendali non è spesso risolvibile mediante la memorizzazione nella cache, poiché gran parte di essa modifica frequentemente i dati transazionali su tabelle con milioni di righe. Vedo facebook et. al. come siti Web ad alto volume, in cui la parte difficile serve così tante richieste web.
Eric Z Beard,

4

Vi sono altre buone ragioni per gli oggetti entità oltre all'astrazione e all'accoppiamento lento. Una delle cose che mi piace di più è la tipizzazione forte che non puoi ottenere con un DataReader o un DataTable. Un altro motivo è che, se fatto bene, le classi di entità appropriate possono rendere il codice più gestibile usando costrutti di prima classe per termini specifici del dominio che chiunque guardi al codice è probabile che capisca piuttosto che un mucchio di stringhe con nomi di campi in essi utilizzati per indicizzare un DataRow. Le procedure memorizzate sono davvero ortogonali all'uso di un ORM poiché molti framework di mappatura offrono la possibilità di mappare gli sprocs.

Non considererei sprocs + datareaders un sostituto di un buon ORM. Con le stored procedure, si è ancora vincolati e strettamente associati alla firma del tipo di procedura, che utilizza un sistema di tipi diverso rispetto al codice chiamante. Le procedure memorizzate possono essere soggette a modifiche per adattarsi a opzioni aggiuntive e modifiche allo schema. Un'alternativa alle procedure memorizzate nel caso in cui lo schema sia soggetto a modifiche consiste nell'utilizzare le viste: è possibile mappare gli oggetti alle viste e quindi mappare nuovamente le viste alle tabelle sottostanti quando le si modifica.

Posso capire la tua avversione per gli ORM se la tua esperienza consiste principalmente in Java EE e CSLA. Potresti voler dare un'occhiata a LINQ to SQL, che è un framework molto leggero ed è principalmente un mapping one-to-one con le tabelle del database, ma di solito ha bisogno solo di un'estensione minore per essere oggetti business completi. LINQ to SQL può anche mappare oggetti di input e output su parametri e risultati delle procedure memorizzate.

Il framework di entità ADO.NET ha l'ulteriore vantaggio che le tabelle del database possono essere visualizzate come classi di entità ereditate l'una dall'altra o come colonne di più tabelle aggregate in un'unica entità. Se è necessario modificare lo schema, è possibile modificare la mappatura dal modello concettuale allo schema di archiviazione senza modificare il codice dell'applicazione reale. E ancora, le stored procedure possono essere utilizzate qui.

Penso che più progetti IT nelle aziende falliscano a causa della non manutenibilità del codice o della scarsa produttività degli sviluppatori (che può accadere, ad esempio, dalla commutazione del contesto tra sproc-writing e app-writing) rispetto ai problemi di scalabilità di un'applicazione.


Penso che un buon compromesso sarebbe la mappatura di un ORM su stored procedure, tranne per il fatto che ciò può essere facilmente eseguito male: se si creano solo i 4 processi CRUD per ogni tabella, non si ottiene nulla. Riesci a mappare procs grandi e a grana grossa su entità o non ti porta davvero da nessuna parte?
Eric Z Beard,

Oltre alle operazioni CRUD, gli ORM di Microsoft consentono di aggiungere metodi alle classi di entità che si associano direttamente a qualsiasi processo memorizzato che si desidera eseguire (a condizione che tutti i tipi di input / output siano mappabili).
Mark Cidade,

3

Vorrei anche aggiungere alla risposta di Dan che la separazione di entrambi i modelli potrebbe consentire l'esecuzione dell'applicazione su server di database diversi o persino modelli di database.


3

Cosa succede se è necessario ridimensionare l'app bilanciando il carico di più di un server Web? È possibile installare l'app completa su tutti i server Web, ma una soluzione migliore è far parlare i server Web con un server delle applicazioni.

Ma se non ci sono oggetti entità, non avranno molto di cui parlare.

Non sto dicendo che non dovresti scrivere monoliti se si tratta di un'applicazione semplice, interna e di breve durata. Ma non appena diventa moderatamente complesso, o dovrebbe durare una notevole quantità di tempo, devi davvero pensare a un buon design.

Ciò consente di risparmiare tempo quando si tratta di mantenerlo.

Dividendo la logica dell'applicazione dalla logica di presentazione e l'accesso ai dati e passando tra loro i DTO, li si disaccoppia. Consentire loro di cambiare in modo indipendente.


3
Molte persone generano il disaccoppiamento e consentono a uno strato di cambiare senza influenzare l'altro. Le procedure memorizzate lo fanno meglio di qualsiasi ORM! Posso modificare radicalmente il modello di dati e finché le procedure restituiscono gli stessi dati, nulla si interrompe.
Eric Z Beard,

2
A mio avviso, le procedure memorizzate E un modello di entità non si escludono a vicenda. Le procedure memorizzate possono fornire un meccanismo per memorizzare il modello di entità. La domanda è: la tua logica aziendale funziona con le entità o accede direttamente alle procedure memorizzate?
jbandi,

3

Potresti trovare interessante questo post su comp.object.

Non sto affermando di essere d'accordo o in disaccordo, ma è interessante e (penso) pertinente a questo argomento.


È un bel post. Riassume i miei pensieri sugli ORM quasi perfettamente.
Eric Z Beard,

3

Una domanda: come gestite le applicazioni disconnesse se tutta la vostra logica aziendale è intrappolata nel database?

Nel tipo di applicazione Enterprise che mi interessa, dobbiamo occuparci di più siti, alcuni dei quali devono essere in grado di funzionare in uno stato disconnesso.
Se la tua logica aziendale è incapsulata in un livello Dominio che è semplice da incorporare in vari tipi di applicazione - ad esempio, dll- posso creare applicazioni che siano a conoscenza delle regole aziendali e che, se necessario, possano applicarle localmente.

Per mantenere il livello Dominio nelle procedure memorizzate nel database, è necessario attenersi a un singolo tipo di applicazione che necessita di una visuale permanente del database.

Va bene per una certa classe di ambienti, ma certamente non copre l'intero spettro di applicazioni Enterprise .


2

@jdecuyper, una massima che ripeto a me stesso spesso è "se la tua logica aziendale non è nel tuo database, è solo una raccomandazione". Penso che Paul Nielson l'abbia detto in uno dei suoi libri. I livelli di applicazione e l'interfaccia utente vanno e vengono, ma i dati di solito vivono per molto tempo.

Come posso evitare oggetti entità? Principalmente procedure memorizzate. Ammetto anche liberamente che la logica aziendale tende a raggiungere tutti i livelli di un'applicazione, indipendentemente dal fatto che tu lo voglia o no. Una certa quantità di accoppiamento è inerente e inevitabile.


Sono d'accordo, la logica di business che si trova nell'applicazione spesso non riesce a tenere conto degli altri modi in cui i dati possono essere immessi, cancellati o modificati. Questo di solito causa problemi di integrità dei dati che vanno avanti sulla strada.
HLGEM,

E perché dovresti sempre usare un livello di servizio per gestire la discrepanza tra il mondo degli oggetti e il mondo relazionale. La logica aziendale che attraversa tutti i livelli NON è certamente inevitabile.
cdaq,

2

Ultimamente ho pensato a questa stessa cosa; Sono stato un grande utente di CSLA per un po 'e adoro la purezza di dire che "tutta la tua logica aziendale (o almeno quanto è ragionevolmente possibile) è incapsulata nelle entità aziendali".

Ho visto che il modello di entità aziendale fornisce molto valore nei casi in cui la progettazione del database è diversa dal modo in cui si lavora con i dati, come nel caso di molti software aziendali.

Ad esempio, l'idea di un "cliente" può consistere in un record principale in una tabella Clienti, combinato con tutti gli ordini che il cliente ha effettuato, nonché tutti i dipendenti del cliente e le loro informazioni di contatto, e alcune delle proprietà di un cliente e i suoi figli possono essere determinati dalle tabelle di ricerca. È davvero bello dal punto di vista dello sviluppo essere in grado di lavorare con il Cliente come una singola entità, poiché dal punto di vista aziendale, il concetto di Cliente contiene tutte queste cose e le relazioni possono o meno essere applicate nel database.

Mentre apprezzo la citazione che "se la tua regola aziendale non è nel tuo database, è solo un suggerimento", credo anche che non dovresti progettare il database per far rispettare le regole aziendali, dovresti progettarlo per essere efficiente, veloce e normalizzato .

Detto questo, come altri hanno già notato, non esiste un "design perfetto", lo strumento deve adattarsi al lavoro. Ma l'utilizzo di entità aziendali può davvero aiutare con la manutenzione e la produttività, poiché sai dove andare a modificare la logica aziendale e gli oggetti possono modellare i concetti del mondo reale in modo intuitivo.


2

Eric,

Nessuno ti impedisce di scegliere il framework / approccio che vorresti. Se hai intenzione di seguire il percorso "data driven / stored procedure-powered", allora procedi! Soprattutto se davvero, ti aiuta davvero a fornire le tue applicazioni su specifiche e puntuali.

Essendo un avvertimento (un rovescio della domanda che è), TUTTE le regole aziendali dovrebbero essere sulle procedure memorizzate e l'applicazione non è altro che un thin client.

Detto questo, le stesse regole si applicano se si fa la propria domanda in OOP: essere coerenti. Segui i principi di OOP e questo include la creazione di oggetti entità per rappresentare i tuoi modelli di dominio.

L'unica vera regola qui è la parola coerenza . Nessuno ti impedisce di diventare incentrato su DB. Nessuno ti impedisce di fare programmi strutturati (alias, funzionali / procedurali) di vecchia scuola. Diavolo, nessuno sta impedendo a nessuno di scrivere codice in stile COBOL. MA una domanda deve essere molto, molto coerente una volta percorsa questa strada, se desidera raggiungere un certo grado di successo.


Sono d'accordo con coerenza in tutta l'app. Ad essere sincero, ho cambiato direzione sul mio progetto attuale qualche tempo fa e non sono mai riuscito a risolvere il 100% del modello originale, il che rende le cose confuse. Le decisioni giuste devono essere prese presto.
Eric Z Beard,

Eric, davvero vero. Una volta ero un fanatico di OOP (il modo in cui sembrano essere gli altri in questo thread) ma ho incontrato un ragazzo che possiede una società che ha molto successo nella vendita di app basate su DB. Questo ha scosso il mio mondo. Sono ancora un appassionato di OOP / TDD, ma non vedo più il DB-centric.
Jon Limjap,

Il problema è che a volte le persone vendono la loro ideologia, potresti potenzialmente guadagnarti da vivere vendendo solo siti html e javascript, se avessi una buona metodologia per metterli in moto.
Mark Rogers,

2

Non sono sicuro di cosa consideri "Applicazioni aziendali". Ma ho l'impressione che tu lo stia definendo come un'applicazione interna in cui l'RDBMS verrebbe messo in pietra e il sistema non dovrebbe essere interoperabile con qualsiasi altro sistema sia interno che esterno.

E se aveste un database con 100 tabelle che equivalgono a 4 Stored procedure per ogni tabella solo per le operazioni CRUD di base che sono 400 procedure memorizzate che devono essere mantenute e non sono fortemente tipizzate, quindi sono sensibili ai refusi e non possono essere testate in unità . Cosa succede quando si ottiene un nuovo CTO che è un evangelista Open Source e vuole cambiare RDBMS da SQL Server a MySql?

Molti software oggi, indipendentemente dal fatto che le applicazioni o i prodotti aziendali utilizzino la SOA e abbiano alcuni requisiti per esporre i servizi Web, almeno il software che sono e con cui sono stato coinvolto. Usando il tuo approccio finiresti per esporre una DataTable o DataRows serializzata. Ora questo può essere considerato accettabile se il Cliente è garantito per essere .NET e su una rete interna. Ma quando il client non è noto, dovresti cercare di progettare un'API che sia intuitiva e nella maggior parte dei casi non vorrai esporre lo schema del database completo. Certamente non vorrei spiegare a uno sviluppatore Java cos'è un DataTable e come usarlo. C'è anche la considerazione di Bandwith e dimensioni del payload e DataTables serializzati, i DataSet sono molto pesanti.

Non esiste un proiettile d'argento con la progettazione del software e dipende davvero da dove risiedono le priorità, per me è nel codice Unit Testable e componenti liberamente accoppiati che possono essere facilmente consumati da qualsiasi cliente.

solo i miei 2 centesimi


No, la mia definizione di Enterprise Application è l'opposto. Lo schema cambia spesso e ci sono molte applicazioni che usano il db e interagisce con molti partner esterni. In un'app aziendale reale , non cambierai mai e poi mai in un RDBMS diverso. Semplicemente non succede.
Eric Z Beard,

E creare 4 proc per ogni tabella è una cattiva pratica. Ti accoppia strettamente al modello di dati proprio come generato sql da un ORM, quindi non ti compra nulla. I proc devono essere operazioni commerciali a grana grossa, non solo CRUD su ogni tabella.
Eric Z Beard,

Ma non è questa la risposta ?: più codice devi scrivere, più hai bisogno di funzionalità per il supporto della programmazione su larga scala: incapsulamento, digitazione di stringhe, refactoring, stile sofisticato e controllo degli errori, ecc .; Java e .NET supportano moltissimo in questo settore, mentre i linguaggi di stored procedure no.
reinierpost,

2

Vorrei offrire un altro punto di vista sul problema della distanza tra OO e RDB: la storia.

Qualsiasi software ha un modello di realtà che è in qualche modo un'astrazione della realtà. Nessun programma per computer può catturare tutte le complessità della realtà e i programmi sono scritti solo per risolvere una serie di problemi dalla realtà. Pertanto, qualsiasi modello di software è una riduzione della realtà. A volte il modello software forza la realtà a ridursi. Come quando vuoi che la compagnia di autonoleggio ti riservi una macchina fintanto che è blu e ha leghe, ma l'operatore non può rispettare perché la tua richiesta non si adatta al computer.

RDB proviene da una tradizione molto antica di mettere le informazioni nelle tabelle, chiamate contabilità. La contabilità è stata fatta su carta, poi su schede perforate, quindi su computer. Ma la contabilità è già una riduzione della realtà. La contabilità ha costretto le persone a seguire il suo sistema così a lungo che è diventato realtà accettata. Ecco perché è relativamente facile realizzare software per la contabilità, la contabilità ha avuto il suo modello informativo, molto prima che arrivasse il computer.

Data l'importanza di buoni sistemi contabili e l'accettazione che si ottiene da qualsiasi dirigente aziendale, questi sistemi sono diventati molto avanzati. Le basi del database sono ora molto solide e nessuno esita a conservare i dati vitali in qualcosa di così affidabile.

Immagino che OO debba essere arrivato quando le persone hanno scoperto che altri aspetti della realtà sono più difficili da modellare della contabilità (che è già un modello). OO è diventata un'idea di grande successo, ma la persistenza dei dati OO è relativamente sottosviluppata. RDB / Contabilità ha avuto vittorie facili, ma OO è un campo molto più ampio (praticamente tutto ciò che non è contabile).

Quindi molti di noi hanno voluto utilizzare OO ma vogliamo comunque archiviare in sicurezza i nostri dati. Cosa può esserci di più sicuro che archiviare i nostri dati come fa il sistema contabile stimato? È una prospettiva allettante, ma ci imbattiamo tutti nelle stesse insidie. Pochissimi si sono presi la briga di pensare alla persistenza di OO rispetto ai massicci sforzi dell'industria RDB, che ha avuto il vantaggio della tradizione e della posizione della contabilità.

Prevayler e db4o sono alcuni suggerimenti, sono sicuro che ce ne sono altri di cui non ho sentito parlare, ma nessuno sembra aver ottenuto metà della stampa come, per esempio, il letargo.

Memorizzare i tuoi oggetti in buoni vecchi file non sembra nemmeno essere preso sul serio per le applicazioni multiutente, e in particolare le applicazioni web.

Nella mia lotta quotidiana per chiudere l'abisso tra OO e RDB, utilizzo OO il più possibile, ma cerco di ridurre al minimo l'eredità. Non uso spesso SP. Userò le query avanzate solo in aspetti che sembrano contabilità.

Sarò felicemente soppresso quando l'abisso sarà chiuso per sempre. Penso che la soluzione arriverà quando Oracle lancerà qualcosa come "Oracle Object Instance Base". Per farcela davvero, dovrà avere un nome rassicurante.


Non penso che tu abbia bisogno di ORM affinché OO sia considerato utile. Uso i proc memorizzati e scrivo molte classi helper statiche nel mio codice, ma quelle classi sono costruite sull'enorme framework .NET, che è una fantastica raccolta di oggetti.
Eric Z Beard,

La tua logica ha senso, ma non credo che la premessa sia corretta. Non ho mai sentito parlare di qualcosa che non può essere mappato con RDB.
Jeff Davis,

1

Non molto tempo al momento, ma proprio dalla cima della mia testa ...

Il modello di entità consente di fornire un'interfaccia coerente al database (e ad altri possibili sistemi) anche al di là di ciò che può fare un'interfaccia di procedura memorizzata. Utilizzando modelli di business a livello aziendale è possibile assicurarsi che tutte le applicazioni influenzino i dati in modo coerente, il che è MOLTO importante. Altrimenti si finiscono con dati errati, il che è semplicemente un male.

Se hai una sola applicazione, non hai davvero un sistema "aziendale", indipendentemente dalla grandezza di tale applicazione o dei tuoi dati. In tal caso puoi usare un approccio simile a quello di cui parli. Basta essere consapevoli del lavoro che sarà necessario se si decide di far crescere i propri sistemi in futuro.

Ecco alcune cose che dovresti tenere a mente (IMO):

  1. Il codice SQL generato è errato (seguono le eccezioni). Mi dispiace, so che molte persone pensano che sia un enorme risparmio di tempo, ma non ho mai trovato un sistema in grado di generare codice più efficiente di quello che potrei scrivere e spesso il codice è semplicemente orribile. Spesso finisci anche per generare una tonnellata di codice SQL che non viene mai utilizzato. L'eccezione qui è modelli molto semplici, come forse le tabelle di ricerca. Molte persone però si lasciano trasportare.
  2. Entity <> Tabelle (o anche entità del modello di dati logici necessariamente). Un modello di dati ha spesso regole di dati che dovrebbero essere applicate il più vicino possibile al database, il che può includere regole su come le righe della tabella si relazionano tra loro o altre regole simili che sono troppo complesse per il RI dichiarativo. Questi dovrebbero essere gestiti in stored procedure. Se tutte le procedure memorizzate sono semplici processi CRUD, non è possibile farlo. Inoltre, il modello CRUD di solito crea problemi di prestazioni perché non minimizza i round trip attraverso la rete al database. Questo è spesso il più grande collo di bottiglia in un'applicazione enterprise.

Concordato su SQL generato. Causa sempre più problemi di quanti ne risolva. E sono decisamente contrario alla semplice creazione di un livello CRUD con processi memorizzati. I proc dovrebbero essere il più grossolani possibile. Non sono sicuro di come definire "una sola applicazione".
Eric Z Beard,

Per applicazione, intendo una singola applicazione scritta da un singolo gruppo nell'organizzazione. Al momento, dove sto consultando, hanno un database aziendale a cui accedono almeno tre gruppi separati che lavorano su tre diverse applicazioni con comunicazioni limitate tra loro.
Tom H,

1

A volte, l'applicazione e il livello dati non sono così strettamente accoppiati. Ad esempio, potresti avere un'applicazione di fatturazione telefonica. Successivamente si crea un'applicazione separata che monitora l'utilizzo del telefono per a) pubblicizzare meglio l'utente b) ottimizzare il proprio piano telefonico.

Queste applicazioni presentano preoccupazioni e requisiti di dati diversi (anche se i dati provengono dallo stesso database), determinerebbero progetti diversi. La tua base di codice può finire in un disordine assoluto (in entrambe le applicazioni) e un incubo da mantenere se lasci che il database guidi il codice.


1

Le applicazioni che hanno una logica di dominio separata dalla logica di archiviazione dei dati sono adattabili a qualsiasi tipo di applicazione di origine dati (database o altro) o UI (web o windows (o Linux ecc.)).

Sei praticamente bloccato nel tuo database, il che non è male se sei con una società che è soddisfatta del sistema di database corrente che stai utilizzando. Tuttavia, poiché i database si evolvono nel tempo, potrebbe esserci un nuovo sistema di database che è davvero pulito e nuovo che la tua azienda desidera utilizzare. E se volessero passare a un metodo di accesso ai dati dei servizi Web (come fa qualche volta l'architettura orientata ai servizi). Potrebbe essere necessario eseguire il porting delle procedure memorizzate in tutto il luogo.

Inoltre, la logica del dominio estrae l'interfaccia utente, che può essere più importante in sistemi complessi di grandi dimensioni che hanno UI in continua evoluzione (soprattutto quando sono costantemente alla ricerca di più clienti).

Inoltre, mentre concordo sul fatto che non esiste una risposta definitiva alla domanda sulle procedure memorizzate rispetto alla logica del dominio. Sono nel campo della logica di dominio (e penso che stiano vincendo nel tempo), perché credo che le procedure di archiviazione elaborate siano più difficili da mantenere rispetto all'elaborata logica di dominio. Ma questo è un altro dibattito


0

Penso che tu sia abituato a scrivere un tipo specifico di applicazione e a risolvere un certo tipo di problema. Sembra che tu stia attaccando questo dal punto di vista del "primo database". Ci sono molti sviluppatori là fuori dove i dati sono conservati su un DB ma le prestazioni non sono una priorità assoluta. In molti casi, mettere un'astrazione sul livello di persistenza semplifica notevolmente il codice e il costo delle prestazioni non è un problema.

Qualunque cosa tu stia facendo, non è OOP. Non è sbagliato, non è solo OOP e non ha senso applicare le tue soluzioni a tutti gli altri problemi.


I dati vengono sempre per primi. È la ragione per cui hai il programma per computer in primo luogo. Quindi "database first" è probabilmente l'unico approccio valido per la progettazione di app.
gbjbaanb,

0

Domanda interessante. Un paio di pensieri:

  1. Come testereste l'unità se tutta la vostra logica aziendale fosse nel vostro database?
  2. Le modifiche alla struttura del database, in particolare quelle che interessano diverse pagine della tua app, sarebbero una seccatura da cambiare in tutta l'app?

0

Buona domanda!

Un approccio che preferisco è quello di creare un oggetto iteratore / generatore che emetta istanze di oggetti rilevanti per un contesto specifico. Di solito questo oggetto racchiude alcune cose di accesso al database sottostante, ma non ho bisogno di saperlo quando lo si utilizza.

Per esempio,

Un oggetto AnswerIterator genera oggetti AnswerIterator.Answer. Sotto il cofano si sta ripetendo un'istruzione SQL per recuperare tutte le risposte e un'altra istruzione SQL per recuperare tutti i commenti correlati. Ma quando utilizzo l'iteratore uso semplicemente l'oggetto Answer che ha le proprietà minime per questo contesto. Con un po 'di codice scheletro questo diventa quasi banale da fare.

Ho scoperto che funziona bene quando ho un enorme set di dati su cui lavorare, e quando fatto bene mi dà piccoli oggetti transitori che sono relativamente facili da testare.

Fondamentalmente è una sottile impiallacciatura sulle cose di accesso al database, ma mi dà ancora la flessibilità di astrarlo quando ne ho bisogno.


0

Gli oggetti nelle mie app tendono a relazionarsi uno a uno con il database, ma sto trovando che usare Linq To Sql piuttosto che sprocs rende molto più facile scrivere query complicate, in particolare essere in grado di costruirle usando l'esecuzione differita. ad es. da r in Images.User.Ratings dove ecc. Questo mi fa risparmiare cercando di elaborare diverse istruzioni di join in sql e avere Skip & Take per il paging semplifica anche il codice piuttosto che incorporare il numero di riga e il codice 'over'.


C'è un grande pericolo nel fare le cose in questo modo. Le query più complesse finiscono per dover essere riscritte interamente da un DBA per renderle scalabili. Nessuna quantità di ottimizzazione dell'indice può fare ciò che a volte può fare la modifica di una query. Questo tipo di Linq2Sql è un accoppiamento estremamente stretto.
Eric Z Beard,

0

Perché fermarsi agli oggetti entità? Se non vedi il valore con oggetti entità in un'app a livello aziendale, fai semplicemente l'accesso ai tuoi dati in un linguaggio puramente funzionale / procedurale e collegalo a un'interfaccia utente. Perché non tagliare semplicemente tutta la "lanugine" OO?


Non vedo OO come "lanugine". È solo che nell'ultimo decennio circa, MSFT, Sun, ecc. Hanno scritto il 99% degli oggetti di cui avremo mai bisogno. Solo perché scrivo molte classi statiche in cima al framework, non significa che non sto usando OO.
Eric Z Beard,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.