Domanda

Come saperne di più e di più su OOP, e iniziare ad attuare i vari modelli di progettazione, che continuano a tornare ai casi in cui le persone sono criticare Record Attivo.

Spesso, la gente dice che non scala bene (citando Twitter come primo esempio) - ma nessuno in realtà spiega perché non scala bene;e / o come raggiungere il pro di AR senza i contro (via è simile ma diverso modello?)

Speriamo che questo non si trasformerà in una guerra santa su modelli di progettazione -- tutti, vorrei sapere ****in particolare:**** cosa c'è di sbagliato con il Record Attivo.

Se non scala bene, perché no?

Quali altri problemi ci sono?

È stato utile?

Soluzione

C'è ActiveRecord il Modello di Progettazione e ActiveRecord Rotaie Libreria ORM, e c'è anche una tonnellata di knock-off per .NET, e in altre lingue.

Queste sono tutte cose diverse.Essi seguono per lo più che di un modello di progettazione, ma di estendere e modificare in molti modi diversi, quindi prima che qualcuno dice "ActiveRecord fa Schifo" ha bisogno di essere qualificato dicendo "che ActiveRecord, c'è un sacco?"

Io sono solo familiarità con Rails ActiveRecord, cercherò di rispondere a tutti i reclami che sono stati sollevati in contesto di utilizzo.

@BlaM

Il problema che vedo con i Record Attivi è, che è sempre e solo su una tabella

Codice:

class Person
    belongs_to :company
end
people = Person.find(:all, :include => :company )

Questo genera SQL con LEFT JOIN companies on companies.id = person.company_id, e genera automaticamente Azienda associata oggetti in modo che si può fare people.first.company e non c'è bisogno di colpire il database perché i dati sono già presenti.

@pix0r

Il problema inerente con l'Record è che le query di database vengono generati automaticamente eseguito per popolare gli oggetti e modificare i record del database

Codice:

person = Person.find_by_sql("giant complicated sql query")

Questo è sconsigliato in quanto è brutta, ma per i casi in cui è solo pianura e semplicemente bisogno di scrivere raw SQL, è fatto facilmente.

@Tim Sullivan

...e si seleziona diverse istanze del modello, stai praticamente facendo un "select * from ..."

Codice:

people = Person.find(:all, :select=>'name, id')

Questo sarà solo selezionare il nome e l'ID colonne dal database, tutti gli altri attributi in oggetti mappati appena saranno nulle, a meno di non ricaricare manualmente l'oggetto, e così via.

Altri suggerimenti

Ho sempre trovato che ActiveRecord è buono per una rapida CRUD-ha basato le applicazioni in cui il Modello è relativamente piatta (come in, non un sacco di gerarchie di classi).Tuttavia, per le applicazioni complesse OO gerarchie DataMapper è probabilmente una soluzione migliore.Mentre ActiveRecord, presuppone un rapporto di 1:1 tra le tabelle e gli oggetti dati, che tipo di rapporto diventa ingombrante più complessi domini.Nel suo libro sui modelli, Martin Fowler punti che ActiveRecord tende a rompersi in condizioni in cui il Modello è abbastanza complessa, e suggerisce un DataMapper come alternativa.

Ho trovato questo per essere vero in pratica.Nel caso In cui si dispone di un sacco di eredità del dominio, è più difficile la mappa dell'ereditarietà RDBMS che è una mappa di associazioni o di composizione.

Il mio modo di fare è avere il "dominio" di oggetti che sono accessibile per il controller tramite questi DataMapper (o "livello di servizio") classi.Questi non direttamente specchio del database, ma anche agire come il tuo OO rappresentazione per qualche oggetto del mondo reale.Supponiamo di avere una classe Utente del dominio, e la necessità di avere riferimenti, o raccolte di altri oggetti, già caricato quando si recupera l'oggetto Utente.I dati possono provenire da diverse tabelle, e un ActiveRecord modello può rendere veramente difficile.

Invece di caricare l'oggetto Utente direttamente e accesso ai dati tramite un ActiveRecord stile API, il codice del controller recupera un oggetto Utente utilizzando le API di UserMapper.getUser() il metodo, per esempio.È che mapper è responsabile del caricamento di eventuali oggetti associati dal loro rispettive tabelle e ritorno completato Utente "dominio" oggetto chiamante.

In sostanza, si sono solo l'aggiunta di un altro strato di astrazione per rendere il codice più gestibile.Se il vostro DataMapper classi contengono materie SQL personalizzato, o chiamate per un livello di astrazione dati API, o anche solo un ActiveRecord modello di se stessi, non importa, per il codice del controller che riceve una bella, popolata oggetto Utente.

Comunque, questo è come lo faccio.

Penso che non c'è, probabilmente, di un diverso insieme di motivi tra cui le persone sono "odiare" a ActiveRecord e cosa è "sbagliato" con esso.

Sul odiare problema, c'è un sacco di veleno verso qualcosa di Guide correlate.Per quanto riguarda quello che è sbagliato con esso, è probabile che sia come tutta la tecnologia e ci sono situazioni in cui non è una buona scelta e in situazioni in cui ci sono scelte migliori.La situazione in cui non si arriva a sfruttare la maggior parte delle caratteristiche di Guide di ActiveRecord, nella mia esperienza, è quello in cui il database è strutturato male.Se si accede a dati senza chiavi primarie, con le cose che violano la prima forma normale, dove ci sono un sacco di stored procedure necessarie per accedere ai dati, è meglio utilizzare qualcosa che è più di un SQL wrapper.Se il database è relativamente ben strutturato, ActiveRecord consente di approfittare di questo.

Per aggiungere al tema di rispondere ai commentatori che dicono che le cose sono difficili in ActiveRecord, con un frammento di codice controreplica

@Sam McAfee supponga di avere una classe Utente del dominio, e la necessità di avere riferimenti, o raccolte di altri oggetti, già caricato quando si recupera l'oggetto Utente.I dati possono provenire da diverse tabelle, e un ActiveRecord modello può rendere veramente difficile.

user = User.find(id, :include => ["posts", "comments"])
first_post = user.posts.first
first_comment = user.comments.first

Utilizzando l'opzione includi, ActiveRecord consente di ignorare l'impostazione predefinita lazy-loading comportamento.

La mia lunga e ritardo di risposta, non e ' ancora completo, ma una buona spiegazione del PERCHÉ odio questo motivo, opinioni e anche alcune emozioni:

1) versione breve:Record attivo crea una "strato sottile"di "associazione forte"tra il database e l'applicazione del codice.Che risolve nessuna logica, nessun altro-problemi, senza problemi a tutti.IMHO non fornisce ALCUN VALORE, ad eccezione di alcuni zucchero sintattico per il programmatore (che può quindi utilizzare un "oggetto" sintassi per accedere ad alcuni dati, che esiste in un database relazionale).Lo sforzo per creare un po ' di conforto per i programmatori dovrebbe (IMHO...) meglio essere investito in basso a livello di database, strumenti di accesso, ad es.alcune variazioni di semplice, facile, normale hash_map get_record( string id_value, string table_name, string id_column_name="id" ) e metodi simili (naturalmente, i concetti e l'eleganza varia notevolmente con il linguaggio).

2) versione lunga:In ogni base di dati-guidato progetti in cui ho avuto il "concettuale controllo" delle cose, ho evitato di AR, ed è stato bello.Io di solito costruire un architettura a livelli (si, prima o poi, non dividere il software in strati, almeno nel medio-grandi progetti):

A1) il database, tabelle, relazioni, anche un po ' di logica se il DBMS consente (MySQL è anche cresciuto ora)

A2) molto spesso, c'è più di un archivio di dati:file di sistema (blob nel database non sono sempre una buona decisione,...), sistemi legacy (immaginate il "come" saranno accessibili, molte varietà possibile..ma non è questo il punto...)

B) database access layer (a questo livello, strumento di metodi, gli assistenti di accedere facilmente ai dati nel database sono i benvenuti, ma AR non fornisce alcun valore qui, ad eccezione di alcuni " zucchero sintattico)

C) gli oggetti dell'applicazione di strato:"gli oggetti dell'applicazione" a volte sono semplici righe di una tabella nel database, ma il più delle volte sono composto oggetti comunque, e hanno una maggiore logica allegato, in modo da investire il tempo in AR oggetti a questo livello è proprio chiaramente inutile, uno spreco di prezioso programmatori tempo, perché il "valore reale", il "più logica" di questi oggetti deve essere implementato su AR oggetti, in ogni caso - con e senza AR!E, per esempio, perché vuoi avere un'astrazione della "voce del Registro di oggetti"?App il codice di logica li scrive, ma che dovrebbe avere la possibilità di aggiornare o cancellare?sembra sciocco, e App::Log("I am a log message") alcune grandezze più facile da usare rispetto le=new LogEntry(); le.time=now(); le.text="I am a log message"; le.Insert();.E per esempio:l'uso di una "voce del Registro oggetto" in vista del registro dell'applicazione funzionerà per 100, 1000 o anche 10000 righe di registro, ma prima o poi dovrai ottimizzare - e scommetto che nella maggior parte dei casi, è sufficiente utilizzare che piccolo e bello istruzione SQL SELECT app logica (che rompe totalmente AR idea..), invece per il confezionamento di piccole istruzione rigida fissa AR idea fotogrammi con un sacco di codice di avvolgimento e di nascosto.Il tempo è sprecato con la scrittura e/o la costruzione di AR codice avrebbe potuto essere investito molto più intelligente di interfaccia per la lettura di liste di log-voci (molti, molti modi, il cielo è il limite).I programmatori dovrebbero "osare inventare nuove astrazioni per realizzare il loro logica dell'applicazione che si adattano al tipo di applicazione, e non stupidamente re-implementare sciocco modelli, che buon suono a prima vista!

D) la logica di applicazione - implementa la logica di interazione con oggetti e la creazione, l'eliminazione e la quotazione(!) la logica delle applicazioni oggetti (NO, queste attività non si dovrebbe mai essere ancorati alla logica dell'applicazione di oggetti di per sé:il foglio di carta sulla scrivania dirvi i nomi e le posizioni di tutti gli altri fogli del tuo ufficio?dimenticate "statico" metodi per la quotazione di oggetti, che è sciocco, un cattivo compromesso creato per fare in modo umano di pensare di inserirsi in [alcuni-non-tutti-i-AR-quadro-come-]AR pensiero)

E) l'interfaccia utente - beh, quello che sto per scrivere nelle righe seguenti è molto, molto, molto soggettiva, ma secondo la mia esperienza, i progetti che hanno costruito su AR, spesso trascurata, l'interfaccia utente di una parte di un'applicazione in tempo è stato sprecato su di creazione di oscurare le astrazioni.Alla fine queste applicazioni sprecato un sacco di programmatori, il tempo e la voglia di applicazioni da programmatori per programmatori, tech-incline all'interno e all'esterno.I programmatori sentire bene (un duro lavoro finalmente finito, tutto finito e corretto, secondo il concetto sulla carta...), e i clienti "solo per imparare che deve essere così", perché quello è "professionale"..ok, scusa, sto divagando ;-)

Beh, certo, tutto questo è soggettivo, ma la mia esperienza (Ruby on Rails escluso, potrebbe essere diverso, e ho zero esperienza pratica con questo approccio).

Pagato progetti, ho spesso sentito l'esigenza di iniziare con la creazione di alcuni "record attivo" oggetti come un blocco di costruzione per il più alto livello di logica dell'applicazione.Nella mia esperienza, questo vistosamente spesso era una specie di scusa per il cliente (un software dev società nella maggior parte dei casi) non hanno un buon concetto, una grande vista, una panoramica di ciò che il prodotto deve, infine, essere.Quei clienti che in telai rigidi ("nel progetto di dieci anni fa, ha funzionato bene.."), essi possono consolidare entità, si può definire entità relazioni, possono abbattere relazioni dati e definire la base della logica dell'applicazione, ma poi si fermano e la mano a te, e penso ecco tutto il necessario...essi spesso non hanno un concetto di logica dell'applicazione, utente, interfaccia, usabilità e così via e così via...a loro manca la grande vista e mancanza di amore per i dettagli, e vogliono seguire che AR modo di cose, perché..beh, perché, ha funzionato in quel progetto anni fa, mantiene le persone occupate e in silenzio?Non so.Ma i "dettagli" separa gli uomini dai ragazzi, o ..come è stato l'annuncio originale slogan ?;-)

Dopo molti anni (dieci anni di esperienza di sviluppo), ogni volta che un cliente parla di un "modello di record attivo", il mio campanello di allarme suona.Ho imparato a cercare di ottenere torna all'essenziale concezionale fase, pensino due volte, provare a mostrare le loro debolezze concettuali o semplicemente evitare a tutti se sono undiscerning (alla fine, si sa, un cliente che non sa ancora cosa vuole, forse, pensa anche che lo sa, ma non lo fa, o cerca di esternare lavoro di concetto per ME è gratis, mi costa tanti preziosi le ore, i giorni, le settimane e i mesi del mio tempo, dal vivo è troppo breve ...).

Così, finalmente:TUTTO QUESTO è il motivo per cui odio questo stupido "modello di record attivo", e faccio e di evitare, ogni volta che è possibile.

MODIFICA:Vorrei anche chiamare questo un Non-Modello.Non a risolvere qualsiasi problema (modelli non sono destinati a creare " zucchero sintattico).Crea molti problemi:la radice di tutti i suoi problemi (citato in molte risposte qui..) è che e ' appena nasconde il buon vecchio ben sviluppata e potente SQL dietro un'interfaccia che è da modelli di definizione estremamente limitata.

Questo modello sostituisce la flessibilità con zucchero sintattico"!

Penso che il problema non AR risolvere per voi?

Alcuni messaggi sono sempre perplesso.Alcune risposte sono andato a "ORM" vs "SQL" o qualcosa di simile.

Il fatto è che AR è una semplificazione modello di programmazione in cui si sfruttano gli oggetti del dominio di scrivere ci database di codice di accesso.

Questi oggetti di solito hanno business attributi (proprietà del bean) e alcuni comportamenti (metodi che di solito lavoro su queste proprietà).

AR dice solo "aggiungere alcuni metodi per questi oggetti di dominio" di database relativi compiti.

E devo dire che, dal mio parere ed esperienza, che non mi piace il modello.

A prima vista può sembrare piuttosto buono.Alcuni moderni strumenti Java come Spring Roo utilizza questo modello.

Per me, il vero problema è solo con OOP preoccupazione.AR modello ti costringe, in qualche modo, per aggiungere una dipendenza dall'oggetto per infraestructure oggetti.Questi infraestructure gli oggetti del dominio oggetto di interrogare il database attraverso i metodi suggeriti da AR.

Ho sempre detto che i due strati sono la chiave per il successo di un progetto.Il livello di servizio (dove il ritmo di logica risiede o possono essere esportati tramite un qualche tipo di remoting tecnologia, come Servizi Web, per esempio) e il livello di dominio.A mio parere, se si aggiungono alcune dipendenze (non è realmente necessario) per il dominio sugli oggetti del livello per la risoluzione di AR motivo, i nostri oggetti del dominio sarà più difficile da condividere con altri strati o (raro) applicazioni esterne.

Spring Roo attuazione dell'AR è interessante, perché non si basa sull'oggetto stesso, ma in alcuni AspectJ file.Ma se poi non si vuole lavorare con Roo e necessario rielaborare il progetto, l'AR metodi da realizzare direttamente a oggetti del dominio.

Un altro punto di vista.Immaginate di non utilizzare un Database Relazionale per memorizzare i nostri oggetti.Immaginate l'applicazione memorizza i nostri oggetti di dominio in un Database NoSQL o in file XML, per esempio.Vorremmo implementare i metodi che fare queste operazioni in nostro dominio oggetti?Io non la penso così (per esempio, nel caso di XM, vorremmo aggiungere XML relative dipendenze per i nostri oggetti di dominio...Veramente triste che penso).Perché allora dobbiamo implementare il DB relazionali metodi nel dominio di oggetti, come le Ar modello dice?

Per riassumere, l'AR modello può sembrare più semplice e buona per i piccoli e semplici applicazioni.Ma, quando ci sono grandi e complesse applicazioni, penso che la classica architettura a più livelli è un approccio migliore.

La domanda è su Active Record di design pattern.Non è un orm Strumento.

La domanda è etichettato con binari e si riferisce a Twitter, che è costruito in Ruby on Rails.ActiveRecord quadro di Rotaie è un'implementazione di Fowler Attivo Record di design pattern.

La cosa principale che ho visto per quanto riguarda i reclami su Active Record è che quando si crea un modello intorno a un tavolo, e si seleziona diverse istanze del modello, stai praticamente facendo un "select * from ...".Questo va bene per la modifica di un record o la visualizzazione di un record, ma se si vuole, per esempio, visualizzare un elenco di città per tutti i contatti presenti nel database, si potrebbe fare "seleziona la Città da ..." e solo ottenere le città.Fare questo con l'Record richiederebbe che si sta selezionando tutte le colonne, ma solo attraverso la Città.

Naturalmente, diverse implementazioni di gestire questo in modo diverso.Tuttavia, è un problema.

Ora, è possibile ottenere tutto questo con la creazione di un nuovo modello per la specifica cosa stai cercando di fare, ma alcune persone sostengono che si tratta di uno sforzo maggiore del beneficio.

Me, io scavo Record Attivo.:-)

HTH

Mi piace il modo in Subsonico fa una colonna unica cosa.
Sia

DataBaseTable.GetList(DataBaseTable.Columns.ColumnYouWant)

, o:

Query q = DataBaseTable.CreateQuery()
               .WHERE(DataBaseTable.Columns.ColumnToFilterOn,value);
q.SelectList = DataBaseTable.Columns.ColumnYouWant;
q.Load();

Ma Linq è ancora il re quando si tratta di caricamento pigro.

@BlaM:A volte mi regolata implementato un record attivo per un risultato di un join.Non sempre deve essere la Tabella di relazione <--> Record Attivo.Perché non è "il Risultato di un'istruzione Join" <--> Record Attivo ?

Ho intenzione di parlare di Record Attivo come un modello di progettazione, non ho ancora visto ROR.

Alcuni sviluppatori odio Record Attivo, perché leggere smart libri sulla scrittura pulita e in ordine di codice, e questi libri sono stati active record viola singolo resposobility linea di principio, viola DDD regola di dominio in oggetto dovrà essere persistente ignorante, e molte altre norme da questo tipo di libri.

La seconda cosa che gli oggetti di dominio in Active Record tendono ad essere di 1 a 1 con il database, che può essere considerato un limite, un qualche tipo di sistemi (n-tier per lo più).

Thats a cose astratte, non ho visto ruby on rails effettiva attuazione di questo modello.

Il problema che vedo con i Record Attivi è, che è sempre e solo sul uno tabella.Va bene, fintanto che è veramente il lavoro con un solo tavolo, ma quando si lavora con i dati nella maggior parte dei casi hanno un qualche tipo di join da qualche parte.

Sì, join di solito è peggio no join quando si tratta di prestazioni, ma join di solito è meglio "falso" join prima di leggere tutta la tabella A e quindi utilizzando il ricavato informazioni per leggere e filtrare la tabella B.

Il problema con ActiveRecord, è che la query genera automaticamente per voi può causare problemi di prestazioni.

Si finisce per fare alcuni intuitivo trucchi per ottimizzare le query che lasciare vi state chiedendo se sarebbe stato più efficaci in tempo per scrivere la query a mano, in primo luogo.

Anche se tutti gli altri commenti relativi a SQL ottimizzazione sono certamente valida, la mia lamentela principale con il modello di record attivo è che di solito porta a mancata corrispondenza di impedenza.Mi piace mantenere il mio dominio pulito e ben incapsulato, che il modello di record attivo di solito distrugge ogni speranza di fare.

Prova a fare molti-a-molti polimorfici rapporto.Non è così facile.Soprattutto quando non la si utilizza STI.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top