Il modello ActiveRecord segue / incoraggia i principi di progettazione SOLID?


43

Sono interessato a sapere se il modello ActiveRecord, reso famoso da Ruby on Rails, incoraggia o scoraggia l'uso dei principi di progettazione SOLID .

Ad esempio, mi sembra che gli oggetti ActiveRecord contengano entrambi la logica di dominio e la logica di persistenza, che costituisce una violazione della responsabilità singola.


6
Jim Weirich, al termine del suo SOLID Ruby Talk alla conferenza Ruby del 2009, chiede al pubblico: "Gli oggetti ActiveRecord implementano un concetto di dominio e un concetto di persistenza. Ciò viola l'SRP (Single Responsibility Principle)?" Il pubblico concorda sul fatto che viola l'SRP. Jim chiede se questo li disturba. Molti membri del pubblico dicono di sì. Perché? Rende i test più difficili. Rende l'oggetto di persistenza molto più pesante.
David J.

Risposte:


56

Ci sono alcune valide critiche su ActiveRecord. Come sempre, lo zio Bob lo riassume perfettamente :

Il problema che ho con Active Record è che crea confusione su questi due stili di programmazione molto diversi. Una tabella di database è una struttura di dati. Ha dati esposti e nessun comportamento. Ma un Record attivo sembra essere un oggetto. Ha dati "nascosti" e comportamenti esposti. Metto la parola "nascosto" tra virgolette perché, di fatto, i dati non sono nascosti. Quasi tutti i derivati ​​ActiveRecord esportano le colonne del database tramite accessori e mutatori. In effetti, Active Record è pensato per essere usato come una struttura di dati.

D'altra parte, molte persone inseriscono i metodi delle regole di business nelle loro classi Active Record; che li fa apparire come oggetti. Questo porta a un dilemma. Da quale parte della linea cade davvero l'Active Record? È un oggetto? O è una struttura di dati?

Wikipedia riassume le critiche in una preoccupazione di testabilità :

In OOP il concetto di incapsulamento è spesso in contrasto con il concetto di separazione delle preoccupazioni. In generale, i modelli che favoriscono la separazione delle preoccupazioni sono più adatti ai test unitari isolati, mentre i modelli che favoriscono l'incapsulamento hanno API più facili da usare. Active Record favorisce fortemente l'incapsulamento al punto in cui il test senza un database è piuttosto difficile.

In particolare per l'implementazione di Ruby on Rails, Gavin King scrive (enfasi sulla mia):

A questo punto, la maggior parte degli sviluppatori sta pensando um, ok, quindi come diavolo dovrei sapere quali attributi ha un'azienda guardando il mio codice? E come può il mio IDE completarli automaticamente? Naturalmente, la gente di Rails ha una rapida risposta a questa domanda Oh, basta accendere il client del database e guardare nel database !. Quindi, supponendo che tu conosca le regole di capitalizzazione e di pluralizzazione automagiche di ActiveRecord / perfettamente /, sarai in grado di indovinare i nomi degli attributi della tua classe aziendale e digitarli manualmente.

Sempre sull'implementazione di Ruby on Rails, scrive John Januszczak (enfasi sulla mia):

PROBLEMA N. 1: METODI STATICI

...

Alcuni direbbero che l'uso di metodi statici equivale semplicemente a una programmazione procedurale, e quindi è un design orientato agli oggetti scadente. Altri direbbero che i metodi statici sono morte per testabilità.

PROBLEMA N. 2: IMPOSTAZIONI DI CONFIGURAZIONE GLOBALE

...

Pertanto non vi è alcuna iniezione di dipendenza nella classe Account nel mio esempio e, per estensione, nelle istanze Account. Come ormai tutti sappiamo, cercare cose è molto, molto male!

Qualche risorsa in più sul motivo per cui ActiveRecord e ORM sono generalmente considerati anti-pattern:

ActiveRecord si è sempre sentito come un anti-pattern estremamente utile , ma sono d'accordo che va contro SRP e inoltre va contro il principio di inversione di dipendenza.


Aggiornamento IMPORTANTE per rails 5+: "E come può il mio IDE completarli automaticamente? Naturalmente, la gente di Rails ha una rapida risposta a questa domanda Oh, basta avviare il client del database e guardare nel database !." non è valido più. Con gli attributi API puoi definire tutte le colonne disponibili sul modello
Filip Bartuzi,

6

(Suppongo che la classe ActiveRecord sia implementata senza alcuna possibilità di iniezione di dipendenza).

Per esperienza personale posso dire che il modello ActiveRecord diventa un grosso ostacolo per la scrittura di unit test. L'accoppiamento del livello di persistenza e della logica aziendale in una singola "classe ActiveRecord" rende impossibile la scrittura di unit test (a meno che non si esegua prima il refactor). Pertanto, l'unica opzione è scrivere test di integrazione; e questo non è efficace come i test unitari. Questo diventa un grosso problema soprattutto se si rileva un progetto con molte classi ActiveRecord; cede a test di integrazione altamente complicati che sono difficili da mantenere.

Quindi, ActiveRecord è praticamente contro SRP e crea mal di testa per la manutenzione; sembra togliere il potere di scrivere unit test.

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.