L'oggetto figlio dipende dal membro dell'oggetto padre

3

Sto combattendo con questo problema di progettazione OOP. Prendi queste classi base, ad esempio:

class Database
{
    public string ConnectionString { get; set; }
    public Table MyTable { get; set; }
}

class Table
{
    public string Name { get; set; }
}

Questo esempio è troppo semplificato per concentrarsi solo sulla domanda in questione.

Se volevo aggiungere una logica che avrebbe ottenere il conteggio della riga Table , penseresti che naturalmente appartenga alla classe Table :

class Table
{
    public string Name { get; set; }

    public int GetRowCount() { ... }
}

Il problema è che, per ottenere il conteggio delle righe, è necessario che si verifichi una connessione al database . Non è un grosso problema, ma la classe Table non ha modo di recuperare la proprietà Database.ConnectionString per connettersi effettivamente per ottenere il conteggio delle righe della tabella specifica.

Vedo alcune opzioni qui e nessuno di loro sembra davvero un ottimo approccio.

Mantieni la logica fuori dagli oggetti figlio

In questo caso, la logica GetRowCount() dovrebbe vivere nell'oggetto padre. Qualcosa del genere:

class Database
{
    public string ConnectionString { get; set; }
    public Table MyTable { get; set; }

    public int GetRowCount(Table table) { ... }
}

class Table
{
    public string Name { get; set; }
}

La classe Table è ora "stupida" per la logica del conteggio delle righe, che non è del tutto una cosa negativa, ma ora non c'è modo di avere un membro nella classe Table per archiviare o recuperare dati direttamente correlati alla classe Table .

Avere un riferimento all'oggetto padre nell'oggetto Bambino

Questo mi piace anche meno dell'approccio di cui sopra. In questo caso, sarebbe simile a qualcosa del tipo:

class Database
{
    public string ConnectionString { get; set; }
    public Table MyTable { get; set; }
}

class Table
{
    public string Name { get; set; }
    public Database Parent { get; set; }

    public int GetRowCount() { ... }
}

Certo, Table.GetRowCount() può creare un riferimento a Table.Parent.ConnectionString , ma sembra solo una ricorsione inutile e ... sciatta.

L'Explicit trasmette i dati richiesti intorno

Non mi piace neanche questo, ma se l'implementazione di Table.GetRowCount() richiede che la stringa di connessione sia passata a questa, questa logica potrebbe vivere nella classe Table , ma ora c'è una mancanza di DRY e una perdita di Database di dati nell'implementazione Table :

class Database
{
    public string ConnectionString { get; set; }
    public Table MyTable { get; set; }
}

class Table
{
    public string Name { get; set; }

    public int GetRowCount(string connectionString) { ... }
}

Per non parlare del fatto che ciò potrebbe portare a problemi di logica complicati, immagino.

Come viene fatto in genere e qual è l'approccio migliore qui? Voglio che la logica del conteggio delle righe vada dove è naturale, con la classe Table . Ma la logica e i dati dipendono da un membro (la stringa di connessione) che vive naturalmente nella classe Database .

    
posta Thomas Stringer 02.03.2015 - 20:48
fonte

3 risposte

6

Passa una connessione già stabilita al costruttore di Table (come opossed all'altro suggerimento di risposta di passare la stringa di connessione).

Questo è l'approccio che ho usato per anni. Gli oggetti che accedono al database non aprono o chiudono le connessioni del database. Una connessione è fatta da qualche altro componente, di solito la classe principale, e passata ai costruttori delle classi che hanno bisogno di accedere al database.

Un ulteriore vantaggio di questo approccio è che disaccoppia il codice utilizzando la lettura dal codice che lo crea . Ad esempio, ci potrebbero essere diverse versioni del driver del database, o ci potrebbe essere un pool di connessioni, e le classi figlie dovrebbero funzionare tutte uguali.

    
risposta data 02.03.2015 - 21:08
fonte
0

Passa un riferimento a ConnectionString (o meglio ancora, la connessione effettiva) al costruttore della tabella.

Poiché la tabella è già all'interno del database (e in realtà non appartiene a nessun altro), il database può semplicemente assegnargli la stringa magica durante la costruzione e quindi la tabella ha sempre ciò che è necessario per eseguire la logica del conteggio delle righe. Poiché la tua connessione (String) è mutabile, non puoi farla franca con una copia, ma dare alla tabella un riferimento a quella connessione è molto meglio che dargli un riferimento all'intero oggetto Database o forzare il Database a contenere tutto il codice reale.

    
risposta data 02.03.2015 - 20:59
fonte
0

Va perfettamente bene che un oggetto figlio abbia un riferimento al suo genitore. Non c'è nessuna ricorsione superflua e nessuna sciatteria. Naturalmente, sarebbe un parametro di costruzione-tempo, e verrebbe memorizzato in un membro di sola lettura, quindi non ci sarebbe set .

Quindi, la tabella potrebbe ottenere la stringa di connessione dall'oggetto del database, se davvero necessario.

Tuttavia, ti raccomando di non fare ciò che stai cercando di fare. Nessuna delle attività della tabella è ottenere una stringa di connessione e stabilire una connessione per ottenere un conteggio. Il fatto che sia coinvolta una stringa di connessione è un dettaglio di implementazione. L'intero concetto di stringhe di connessione è un hack che è meglio racchiuso nella più piccola quantità di codice che è assolutamente necessaria per portare a termine il lavoro.

Quindi, funziona sempre con un oggetto di connessione separato che è già stato creato (presumibilmente usando una stringa di connessione) o, meglio ancora, rendere il database l'oggetto di connessione, incapsulando completamente il fatto che la sua creazione implicava un trucco noto come stringa di connessione.

    
risposta data 02.03.2015 - 21:38
fonte

Leggi altre domande sui tag