Quali sono gli svantaggi del pattern ActiveRecord?

28

Sono curioso di sapere quali sono gli svantaggi dell'utilizzo del pattern ActiveRecord per l'accesso ai dati / oggetti business. L'unico che mi viene in mente è che viola il Principio di Responsabilità Unica, ma il pattern AR è abbastanza comune che questo motivo da solo non sembra "abbastanza buono" da giustificare il fatto di non usarlo (ovviamente il mio la vista può essere distorta poiché spesso nessuno del codice con cui lavoro segue qualsiasi dei principi SOLID).

Personalmente sono not un fan di ActiveRecord (con l'eccezione di scrivere un'applicazione Ruby on Rails, dove AR si sente "naturale") perché sembra che la classe stia facendo troppo e dati l'accesso non dovrebbe essere all'altezza della classe stessa da gestire. Preferisco usare i repository che restituiscono oggetti business. La maggior parte del codice con cui lavoro tende ad usare una variante di ActiveRecord, nella forma di (non so perché il metodo sia booleano):

public class Foo
{
    // properties...

    public Foo(int fooID)
    {
        this.fooID = fooID;
    }

    public bool Load()
    {
        // DB stuff here...
        // map DataReader to properties...

        bool returnCode = false;
        if (dr.HasRows)
            returnCode = true;

        return returnCode;
    }
}

o talvolta il modo più "tradizionale" di avere un metodo public static Foo FindFooByID(int fooID) per i finder e qualcosa sulla falsariga di public void Save() per il salvataggio / l'aggiornamento.

Ho capito che ActiveRecord è in genere molto più semplice da implementare e utilizzare, ma sembra un po ' troppo semplice per applicazioni complesse e potresti avere un'architettura più robusta incapsulando la tua logica di accesso ai dati in un repository (per non parlare del fatto che è più facile scambiare le strategie di accesso ai dati, ad esempio magari usi Processi memorizzati + DataSet e vuoi passare a LINQ o qualcosa di simile)

Quindi quali sono gli altri svantaggi di questo modello che dovrebbero essere considerati quando si decide se ActiveRecord è il miglior candidato per il lavoro?

    
posta Wayne Molina 21.04.2011 - 20:08
fonte

3 risposte

26

Lo svantaggio principale è che le "entità" sono consapevoli della propria persistenza che porta a molte altre cattive decisioni di progettazione.

Gli altri problemi sono che la maggior parte dei toolkit di registrazione attivi basicamente mappano 1 a 1 ai campi della tabella con zero livelli di riferimento indiretto. Funziona su piccole scale ma cade a pezzi quando hai problemi più complessi da risolvere.

Bene, avere i tuoi oggetti a conoscenza della loro persistenza significa che devi fare cose come:

  • facilmente avere connessioni database disponibili ovunque. Questo in genere porta a una cattiva codifica o una sorta di connessione statica che viene colpita da ogni parte.
  • i tuoi oggetti tendono ad assomigliare più a SQL che a oggetti.
  • È difficile fare qualcosa nell'app disconnesso perché il database è così radicato.

In fin dei conti ci sono un sacco di altre cattive decisioni.

    
risposta data 21.04.2011 - 20:45
fonte
14

Il più grande svantaggio della registrazione attiva è che il dominio di solito diventa strettamente associato a un particolare meccanismo di persistenza. Se quel meccanismo richiede una modifica globale, forse dalla persistenza basata su file a quella basata su DB o tra i quadri di accesso ai dati, OGNI classe che implementa questo modello potrebbe cambiare. A seconda della lingua, del framework e del design, anche qualcosa di così semplice come cambiare dove si trova il DB o chi "possiede" potrebbe richiedere di passare attraverso ogni oggetto per aggiornare i metodi di accesso ai dati (questo è raro nella maggior parte delle lingue che forniscono un facile accesso per configurare i file con stringhe di connessione).

In genere richiede anche che tu ripeta te stesso. La maggior parte dei meccanismi di persistenza ha un sacco di codice comune, per connettersi a un DB e avviare una transazione. DRY (Do not Repeat Yourself) ti direbbe come coder per centralizzare tale logica.

Rende anche le operazioni atomiche ingannevoli. Se un gruppo di oggetti deve essere salvato in modo tutto-o-niente (come una Fattura e le sue InvoiceLines e / o Customer e / o GL), un oggetto deve conoscere tutti questi altri oggetti e controllarne la persistenza ( che allarga la portata dell'oggetto di controllo: grandi record interconnessi possono facilmente diventare "oggetti di dio" che sanno tutto sulle loro dipendenze), o il controllo sull'intera transazione deve essere gestito dall'esterno del dominio (e in tal caso perché stai usando AR?)

È anche "sbagliato" da una prospettiva orientata agli oggetti. Nel mondo reale, una fattura non sa come archiviarsi, quindi perché un oggetto codice fattura può sapere come salvarsi nel DB? Ovviamente, l'adesione eccessivamente religiosa agli "oggetti dovrebbe solo modellare ciò che le loro controparti del mondo reale possono fare" porterebbe a modelli di dominio anemici (una fattura inoltre non sa come calcolare il proprio totale, ma suddividendo il calcolo di quel totale in un altro oggetto è generalmente considerato una cattiva idea).

    
risposta data 16.09.2011 - 21:57
fonte
2

Lo svantaggio di base è che rende il tuo modello di dominio complesso perché non solo mantiene la logica aziendale ma anche le informazioni sulla persistenza.

Quindi la soluzione è utilizzare l'implementazione Data Mapper di ORM. Questo separa il livello di persistenza e ora siamo più incentrati sulla logica aziendale dell'entità. Doctrine è Data Mapper ORM.

Ma questo approccio ha anche una certa complessità. Per interrogare ora dipendi troppo dal Data Mapper, rende l'ambiente orientato alle query. Per semplificarlo, viene introdotto un altro livello tra Modello di dominio e Mappatore dati è chiamato Repository .

Repository estrae il livello di persistenza. Fa sensazione di programmazione orientata agli oggetti nel senso, è raccolta di tutti gli stessi oggetti di tipo (come tutte le entità memorizzate nella tabella del database) ed è possibile eseguire operazioni su di essi come operazione di raccolta, aggiungi , Rimuovi . contiene ecc.

Ad esempio per Entità utente , ci sarà UserRepository che rappresenta la raccolta dello stesso tipo di oggetti utente (memorizzati nella tabella utenti) su cui è possibile eseguire operazioni. Per eseguire query sulla tabella utenti utilizza Mapping dati utente , ma è stato estratto in Utente modello dominio .

Modello di repository è un tipo di Livello di accesso ai dati , un altro è Oggetto di accesso ai dati solo differenze Repository ha < strong> Funzione radice aggregata

    
risposta data 16.08.2016 - 23:25
fonte

Leggi altre domande sui tag