Estratto DAL - Utilizza l'interfaccia con la classe interna?

8

Abbiamo un livello di business logic (BLL) strettamente accoppiato al nostro livello di accesso ai dati (DAL). Facciamo chiamate in questo modo:

using (FooData data = new FooData())
{
  data.DoSomething();
}

È importante notare che tutte le nostre classi di dati sono internal e sono nello stesso assembly delle classi logiche, in modo che solo il BLL possa accedere al DAL.

Per disaccoppiare questi (per facilitare il test delle unità), un'idea è quella di creare interfacce IDataClass, come IFooData. All'inizio ho pensato che potesse essere un problema perché dovevamo rendere pubbliche le nostre classi di dati per implementare le interfacce. Ma dovremmo essere in grado di mantenere le classi di dati interne, anche se abbiamo ancora bisogno che i metodi siano pubblici:

public interface IFooData
{
  void DoSomething();
}

internal class FooData : IFooData  // Notice the class is internal
{
  public void DoSomething();  // Method is public, but that's ok because class is internal
}

Quindi, anche se il metodo è pubblico, poiché la classe stessa è interna, dovremmo comunque consentire solo il nostro accesso BLL.

C'è qualcosa di intrinsecamente sbagliato in questo approccio? C'è un modo migliore per astrarre il DAL, per testare le unità, senza aprire il DAL al mondo rendendolo pubblico?

    
posta Bob Horn 19.08.2012 - 20:32
fonte

5 risposte

13

L'estrazione di un'interfaccia e la garanzia che BLL stia utilizzando solo i tipi di interfaccia è un buon modo per rendere il BLL testabile senza il database.

Quello che stai facendo è assolutamente perfetto.

    
risposta data 19.08.2012 - 20:36
fonte
1

Puoi utilizzare InternalsVisibleToAttribute per interrompere il tuo DAL fuori dal tuo Business Layer, ma continua a mantenere i metodi DAL interni. Alla fine creerai il tuo DAL come gruppo di amici .

Questo potrebbe non essere un ottimo approccio, come dovresti specificare nel file Assembly.cs del tuo DAL, che gli assembly possono accedere al DAL. Quindi c'è ancora qualche accoppiamento coinvolto (DAL che sa di BLL).

Quindi, per rispondere alla tua domanda, non c'è niente di sbagliato nel tuo approccio. Ma approfittare degli assembly degli amici può fornirti un po 'più di astrazione e probabilmente aiutarti a rendere il tuo codice più testabile.

Spero che questo aiuti.

    
risposta data 19.08.2012 - 02:31
fonte
1

Sembri immateriale alle tue idee che esponi nella tua domanda, ma comunque tenderò a una risposta - qualcuno potrebbe trovarlo utile in futuro.

Se si insiste a mantenere il DAL interno ma si desidera comunque eseguirlo con alcuni test unitari e non si preoccupa di utilizzare gli strumenti Microsoft Unit Testing, quindi provare PrivateObject approccio. Si tratta di un wrapper per la riflessione che potresti sempre codificarti, ma ti consente di risparmiare alcune righe di digitazione.

Tieni presente che l'utilizzo di InternalsVisibleTo è un approccio praticabile, ma è maldestro: se lo stai utilizzando, potresti già essere in una rapida discesa in discesa. internal significa che qualcosa è pubblico solo all'interno del suo assembly, quel modificatore è normalmente usato perché non vuoi roba utilizzabile da all'esterno di quell'assembly, quindi ti gira prontamente e violi questo concetto dichiarando un InternalsVisibleTo ... quella è una grande bandiera rossa sporca che sta gridando per qualche refactoring. Il disaccoppiamento è una perdita di tempo quando solo un gruppo chiama l'altro, puoi anche incollarli insieme. Il disaccoppiamento indica che più gruppi chiamano il bersaglio (l'introduzione del test unitario non conta per il "multiplo" perché ci sono modi per arrivare all'assemblea obiettivo come ho già detto).

    
risposta data 19.08.2012 - 15:49
fonte
1

Tecnicamente, non c'è niente di sbagliato nel tuo design.

Tuttavia, prenderei in considerazione un approccio alternativo: invece di disaccoppiare il tuo BLL dal tuo DAL, meglio disaccoppiare il tuo DAL dal tuo database. Consenti la creazione di oggetti DAL in memoria e se il BLL ha bisogno di caricare oggetti DAL da qualche parte, usa il modello di repository (vedi qui ) per evitare il contatto diretto della BLL nel database. In questo modo, puoi

  • crea unit test per gli oggetti DAL facilmente senza bisogno di un database
  • crea unit test per il tuo BLL fornendo oggetti DAL creati in memoria attraverso un repository finto come dati di test (ok, puoi discutere ora se quei test dovrebbero essere veramente chiamati unit -tests)

In effetti, ciò che perdi è la capacità di testare il BLL con i DAL mock. Ma in realtà, quegli oggetti DAL mock appariranno in genere molto simili ai veri oggetti DAL per fornire una base per test utili del BLL. IMHO evita molte duplicazioni di codice e sforzi inutili quando riutilizzi i tuoi oggetti DAL reali per i test automatici della BLL.

    
risposta data 20.08.2012 - 13:52
fonte
0

L'approccio all'interfaccia è buono / mainstream per deridere il tuo DAL durante test di utenti come BLL.

Una cosa da notare, tuttavia, è che rendendo le tue lezioni concrete DAL interne, è possibile che tu stia rendendo più difficile testare il tuo DAL concreto direttamente, poiché ciò implica che anche i test dell'unità DAL devono essere inclusi in questo assembly senza necessità di usa le porte posteriori come il riflesso.

Inoltre, a un certo punto in futuro potresti prendere in considerazione l'utilizzo di un contenitore IoC per costruire l'implementazione dietro un'interfaccia, che potrebbe anche inciampare nell'interno.

Potresti imitare l'incapsulamento che stai cercando di ottenere con "solo interno" aggiungendo una regola LTRI / convenzione che il tuo BLL / altri livelli deve accoppiare al DAL tramite l'interfaccia, non sull'implementazione concreta.

    
risposta data 20.08.2012 - 08:37
fonte

Leggi altre domande sui tag