È corretto inserire una chiamata di inizializzazione del database in un costruttore C #? [chiuso]

StackOverflow https://stackoverflow.com/questions/159886

  •  03-07-2019
  •  | 
  •  

Domanda

Ho visto che si tratta di varie basi di codice e volevo sapere se questo in genere non era corretto.

Ad esempio:

public class MyClass
{
   public int Id;

   public MyClass()
   {
      Id = new Database().GetIdFor(typeof(MyClass));
   }
}
È stato utile?

Soluzione

Esistono diversi motivi per cui questo non è generalmente considerato un buon design, alcuni dei quali sono già stati menzionati, come la causa di difficili test unitari e difficoltà di gestione.

Il motivo principale per cui sceglierei di non farlo è che il tuo oggetto e il livello di accesso ai dati sono ora strettamente collegati, il che significa che qualsiasi uso di quell'oggetto al di fuori del suo design originale richiede una rielaborazione significativa. Ad esempio, se ti imbattessi in un'istanza in cui hai bisogno di usare quell'oggetto senza alcun valore assegnato ad esempio per mantenere una nuova istanza di quella classe? ora devi sovraccaricare il costruttore e quindi assicurarti che tutta la tua altra logica gestisca questo nuovo caso, oppure ereditare e sovrascrivere.

Se l'oggetto e l'accesso ai dati fossero disaccoppiati, è possibile creare un'istanza e non idratarla. Oppure se hai un progetto diverso che utilizza le stesse entità ma utilizza un livello di persistenza diverso, gli oggetti sono riutilizzabili.

Detto questo, in passato ho preso la strada più semplice per l'accoppiamento nei progetti :)

Altri suggerimenti

Beh .. non lo farei. Ma poi il mio approccio di solito prevede che la classe NON sia responsabile del recupero dei propri dati.

Sarà anche difficile scrivere unit test per la classe poiché non sarai in grado di forzare la classe a usare una versione Mock / Stub della classe db. Vedere qui: http://en.wikipedia.org/wiki/Dependency_injection

Puoi usare il modello usa e getta se fai riferimento a una connessione DB:

public class MyClass : IDisposable
{
    private Database db;
    private int? _id;

    public MyClass()
    {
        db = new Database();
    }

    public int Id
    {
        get
        {
            if (_id == null) _id = db.GetIdFor(typeof(MyClass));
            return _id.Value;
        }
    }

    public void Dispose()
    {
        db.Close();
    }
}

Utilizzo:

using (var x = new MyClass()) 
{
    /* ... */

} //closes DB by calling IDisposable.Dispose() when going out of "using" scope

Sì, PUOI farlo, ma non è il miglior design e la gestione degli errori nei costruttori non è così ordinata come altrove.

L'unico problema che mi viene in mente con questo approccio è che eventuali errori dall'inizializzazione del DB verranno propagati come eccezioni dal costruttore.

Perché qualcuno dovrebbe voler usare un oggetto / stub finto invece della cosa reale? Concordi sul fatto che i produttori di automobili dovrebbero utilizzare modelli di cartone per crashtest?

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