Architecture persistenza (e altri sistemi interni). Interfacce, composizione, pura ereditarietà o centralizzazione?

4

Supponiamo che tu debba implementare la persistenza, penso che tu sia generalmente limitato a quattro opzioni (correggimi se sbaglio, per favore)

Ogni classe persistente:

  1. Dovrebbe implementare un'interfaccia (IPersistent)
  2. Contiene un oggetto "persist-me" che è un oggetto specializzato (o classe) creato solo per essere utilizzato con la classe che lo contiene.
  3. Eredita da Persistent (una classe base)

Oppure puoi creare una gigantesca classe (o pacchetto) chiamata Database e creare la tua logica di persistenza lì.

Quali sono i vantaggi e i problemi che possono derivare da ciascuno di essi? In una piccola app (5kloc) e algoritmicamente (o organizzativa) semplice, qual è probabilmente l'opzione migliore?

    
posta Julio Rodrigues 17.12.2012 - 00:04
fonte

3 risposte

1

In a small (5kloc) and algorithmically (or organisationally) simple app what is probably the best option?

5kloc può sembrare piccolo, ma se devi mantenerlo nel tempo, beneficerai di un design chiaro e di un codice ben strutturato (leggi: più classi o moduli, ognuno focalizzato su un particolare compito). Detto questo - senza sapere di più sulla tua applicazione - il mio consiglio generale è questo:

  1. cerca sempre di eliminare la persistenza dal codice dell'algoritmo (detto anche "logica di dominio"). Ciò mantiene il codice dell'algoritmo pulito e semplice e semplifica la manutenzione della logica di persistenza. Mescolare la persistenza con il codice dell'algoritmo introduce una complessità che sarà difficile da mantenere a lungo termine.

  2. implementa la persistenza in modo tale che sia ben incapsulato. Idealmente la tua logica di dominio (e tutte le sue classi / oggetti) non sa che è persistente.

  3. Se possibile, utilizza un framework di persistenza (ad esempio ORM), ciò semplifica enormemente la progettazione e riduce la necessità di scrivere codice specifico (ad esempio SQL, mappatura di oggetti, ecc.).

  4. Se ci sono un gran numero di classi, raggruppale per "coesione interna", cioè scopri quali classi appartengono l'una all'altra e organizza la persistenza per gruppo.

In altre parole, non centralizzare tutta la logica di persistenza in una grande classe di database, ma piuttosto centralizzare per un gruppo di classi. Ciò mantiene la progettazione del sistema trattabile e il codice leggibile.

    
risposta data 28.12.2012 - 11:15
fonte
0
  1. Il codice è molto leggibile: sai esattamente cosa ti ostini.

  2. Questo mi ricorda il pattern di Memento. È bene ripristinare le modifiche.

  3. È come 1. ma per ereditarietà - la classe di base definisce l'interfaccia. Può causare problemi se hai o non hai ereditarietà multipla.

  4. I database non possono salvare ogni oggetto ma solo alcuni con vincoli. Ti importa di cosa consiste l'oggetto.

  5. Gemstone / S e MagLev consente di memorizzare qualsiasi oggetto. Al contrario di 1-4 usa le transazioni. Alla fine di una transazione tutti gli oggetti modificati sono persistenti.

Esempi

In Python e marshalling-aproaches: la persistenza spesso usa 1. per convertire un oggetto in qualcosa di persistibile e 3 per non implementarlo troppo spesso. Un Marshaller come in 4. abilita l'identità dell'oggetto nella persistenza e nella ricorsione. (la persistenza di un oggetto crea due volte un riferimento).

I Webframework Rails in Ruby usano 4. e 3. per memorizzare il modello del programma Model-View-Controller. Lavori su copie dell'oggetto originale. Hai gli attributi degli oggetti digitati.

Come iniziare

Puoi iniziare con 1. e un metodo toString() .

Una volta che hai di nuovo bisogno dello stesso algoritmo, puoi utilizzare 3. .

Se è necessario mantenere strutture ricorsive o garantire l'identità dell'oggetto, introdurre un Marshaller che lo gestisce. (È anche responsabile per oggetti il cui comportamento di persistenza non può essere toccato.)

Se hai molti oggetti semplici e non ti preoccupare dell'identità ma solo alcuni dati: usa un database 4. .

2. sembra non essere bilanciato e può essere creato in ogni soluzione.

5. se la tua lingua lo supporta. Usa ciò che è stato dato.

    
risposta data 17.12.2012 - 14:06
fonte
0

La mia prima risposta sarebbe di risparmiarti il problema e trovare un buon ORM di mappatura dei dati e concentrarti sui tuoi oggetti di business e sulla logica, e lasciare che l'ORM si preoccupi della persistenza. La parte "data mapper" è importante qui, perché ti permette di avere un livello di dominio completamente separato dalla persistenza. Quindi avrai solo classi semplici senza perdite di persistenza sotto forma di classe base, interfaccia o altro.

Ora, se vuoi ancora provare a crearne uno tuo, questo è come lo farei io:

Questo è strongmente basato su come funziona Doctrine2 ORM per PHP: Il punto di ingresso per qualsiasi codice sta usando l'ORM è il tuo EntityManager, questo è quello che usi per recuperare e salvare i tuoi oggetti entità / dominio. Poi hai il tuo livello di mappatura dei dati, che dovrebbe essere in grado di essere iniettato con informazioni di mappatura (in xml o qualsiasi altra cosa), in modo che possa capire come connettere le tabelle alle classi e alle colonne e come gestire le relazioni. Sotto tutto questo, hai il livello di accesso db actuall, che deve essere abbastanza flessibile da gestire diversi database. Quindi, quando chiedi un'entità dall'EM, passerà attraverso il livello del mappatore per trovare la tabella da usare, quindi il dbal per recuperare i dati e ancora attraverso il mapper per mappare i dati su un oggetto. Quando salvi un'entità, EM utilizza il livello di mappatura per scoprire la tabella / le colonne dall'oggetto / proprietà e invia i dati al db per salvarlo effettivamente. Doctrine utilizza anche classi proxy generate automaticamente per i tuoi oggetti. Questi proxy sono iniettati con l'EM per consentire il caricamento delle relazioni.

Questa è una versione semplificata delle cose, e sono sicuro che qualcuno l'ha già fatto in qualunque lingua tu stia usando. Ad esempio Doctrine ha anche un ODM, per MongoDB (questo è ancora beta).

EDIT: Noterai che non ho mai menzionato nulla come una classe base o un'interfaccia che useresti nei tuoi oggetti di dominio. Dovrebbero essere assolutamente stupidi quando si tratta di persistenza, e l'unica "perdita" dalla persistenza ai livelli del dominio avviene nelle classi proxy, che dovrebbero apparire esattamente come gli oggetti del dominio per l'applicazione che li sta usando. In questo modo il tuo codice di dominio rimane pulito e semplice.

    
risposta data 27.01.2013 - 23:40
fonte

Leggi altre domande sui tag