Programming Languages Hacks

Importanti regole per linguaggi di programmazione rilevanti come Java, C, C++, C#…

  • Subscribe

  • Lettori

    I miei lettori abituali

  • Twitter

Where condition: IEnumerable vs IQueryable

Posted by Ricibald on 8th August 2013

Check this LINQ To Entities query

    IEnumerable<Book> books = ObjectContext.Books.Where(x => x.Id == 23);
    books = books.Where(x => !x.IsActive);

The query is, as expected, defferred: only when iterating we’ll get the value.

But…this is the query it produces (!!!):

SELECT *
FROM [dbo].[Books]
WHERE [Id] = 23

But… wait!! And the IsActive condition? This is the trap…!!

Solving the main trap

The extension method where exists in two forms:

If at compile time whe are using the first extension method we’ll execute query using LINQ To Objects. It’s deferred, but the filter is applied in memory on the entire result set and doesn’t filter in the data source…!!!

To fix it, “just” make sure to always use IQueryable.Where:

    IQueryable<Book> books = ObjectContext.Books.Where(x => x.Id == 23);
    books = books.Where(x => !x.IsActive);

Or… better (another reason to always use var!!):

    var books = ObjectContext.Books.Where(x => x.Id == 23);
    books = books.Where(x => !x.IsActive);

This produces the following correct query:

SELECT * 
FROM [dbo].[Books]
WHERE ([Id] = 23) AND ([IsActive] <> cast(1 as bit))

Solving the dependent trap

Now that we know the rule… take attention to write a similar code or you’ll have the same error:

void Test() 
{
    IQueryable<Book> books = ObjectContext.Books.Where(x => x.Id == 23);
    books = FilterActive(books);
    books.Dump();   // show data
}

IQueryable<Book> FilterActive(IEnumerable<Book> books) 
{
    return books.Where(x => !x.IsActive);
}

In the example you are filtering using IEnumerable.Where and this leads to the same error. You need to take in input IQueryable collection.

However, if you need to use IEnumerable because you’ll want to be indipendent of IQueryable you can write the following and it will work:

void Test() 
{
    var books = ObjectContext.Books.Where(x => x.Id == 23);
    books = FilterActive(books).AsQueryable();
}

IEnumerable<Book> FilterActive(IEnumerable<Book> books) 
{
    return books.AsQueryable().Where(x => !x.IsActive);
}

This is a trap, but not a bug. This strange behavior enable this scenario (thanks to @Enzo): the DAL works internally passing IQueryable objects and returns to the caller only IEnumerable. The Business Layer uses the detached IEnumerable to refine the query in memory. The Presentation Layer execute only if needed the mixed query (because deferred).

Posted in .net | 1 Comment »

Evoluzione dei test – Debugger, TDD, BDD, LINQPad

Posted by Ricibald on 24th June 2013

Uno strumento fondamentale per sviluppare in .NET si sta sempre più rilevando LINQPad.

Nonostante sia nato per analizzare le query prodotte da LINQ, di fatto lo strumento è molto di più: consente infatti di testare al volo porzioni di codice .NET.

Facciamo subito un esempio pratico. Immaginiamo di avere un codice 3-layer con diversi componenti remoti che interagiscono tra di loro mediante protocolli più o meno complessi. Uno di questi componenti deve validare l’indirizzo mail che arriva in input da uno degli altri componenti. Il codice che validerà la mail è il seguente:

Regex.Match(emailAddress, @"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$");

Immaginiamo di voler testare questo codice. Come faresti?

Come verifichiamo il nostro codice? Vecchio stile…

In uno sviluppo classico (errato) si procede in questo modo:

  1. si scrive il codice fino a ottenere l’elaborato finale
  2. si testa il codice facendo girare tutti i vari componenti e incrociando le dita… se va tutto bene, bene… sennò si collega il debugger di VS e si passa per giorni e giorni di debugging…

Questo approccio ha tanti limiti tra cui: dipendenza da componenti esterni, tempi tecnici lunghi, non ripetibilità automatica del test.

In uno sviluppo più evoluto (TDD) si farebbe uso di unit test come segue:

  1. si scrive prima il metodo di test che verifica che a fronte di mail corrette non abbiamo errori e che viceversa a fronte di mail errate avremo eccezioni
    • il test dovrà essere isolato e atomico iniettando mock o, meglio, stub
  2. si scrive il minimo codice possibile per far compilare il codice
  3. si esegue il test, che deve fallire (il comportamento non è ancora implementato)
  4. si scrive l’implementazione vera e propria del test
  5. si riesegue il test, che stavolta dovrà andare bene

Questo approccio corregge i limiti sopra esposti consentendo una ripetibilità dei test e un isolamento dei componenti.

Gli unit test sono la risposta allora… Quale è il problema?

Gli unit test sono il modo di procedere corretto ma richiede una competenza di alto livello:

  • bisogna conoscere framework di dependency injection, unit test, mocking
  • bisogna conoscere bene i confini di un test: non bisogna testare né troppo né poco
  • gli input dei test devono essere significativi per verificare i “casi limite”
  • richiedono molto rigore: a ogni bug rilevato bisognerebbe creare il test corrispondente e fixarlo
  • bisogna saper isolare molto bene i test e rifattorizzarli nei punti variabili per evitare che una modifica nel codice comporti una modifica a cascata di tutti i test collegati

Oltre alle competenze richieste, i test di fatto aumentano comunque il lavoro complessivo:

  • bisogna scrivere test e mock per tutti gli input significativi
  • bisogna rifattorizzare i test e mantenerli nel tempo a fronte di cambiamenti anche strutturali

Non sto dicendo non bisogna fare unit test, anzi. Il problema è che una competenza simile è difficile trovarla ed è complicato trovare un progetto con un contesto culturale favorevole a un approccio di questo tipo.

Gli unit test sono troppo complessi…? Allora testiamo solo gli use case…

Allora era giusto il precedente approccio? Torniamo al debbugger con VS? Non credo sia corretto tornare nella propria zona di comfort, l’ideale sarebbe crearsi la competenza per perseguire gli unit test “puri”. Ma una via di mezzo potrebbe comunque esistere.

Si può semplificare e non scrivere 100 test in isolamento arrivando a una copertura del 100% del codice testato, bensì scrivere solo test “integrati” che vadano a verificare end-to-end il comportamento del codice integrato. Questo assomiglia più al BDD (Behavior-driven development) e presenta i seguenti vantaggi:

  • si verificano le porzioni di codice che effettivamente verranno eseguite nei vari casi d’uso
  • non richiede un’infrastruttura di stub/mock: si possono anche non conoscere framework di dependency injection e mocking

Il problema è che comunque i test devono essere atomici: l’esito non deve essere influenzato da altri test. Significa che siamo costretti a creare nel db e/o componenti dipendenti tutte le precondizioni che servono per avere una situazione “pulita” da testare.

Il BDD è ottimo per avere test che verifichino il giro completo del codice in modo ripetibile e quindi automatizzabile. Ma il BDD non è efficace per il nostro semplice caso di test di esempio. Se vogliamo solo testare se l’espressione regolare è valida per un’indirizzo email dovremmo porci in troppe precondizioni per poi fare semplici asserzioni.

 Gli use case sono troppo complessi…? Compilo ed eseguo al volo…

Un approccio estremamente più semplice e immediato per verificare il codice potrebbe essere quello di crearsi una Console Application, copiare/incollare il codice e testare il codice dentro la console.

Questo ha però dei tempi tecnici necessari come creare la solution, compilare e andare in debug. Questo comporta una risposta psicologica negativa: il test si fa solo quando serve veramente. Il vantaggio ci sarebbe ma per esperienza, nonostante sia il modo più immediato, nessuno lo fa: ci sarà o no un motivo…?

Un test al volo è troppo macchinoso…? Viene in aiuto LINQPad!

Siamo finalmente arrivati al nostro incredibile “silver bullet”. LINQPad, oltre a verificare le query LINQ generate, consente di ispezionare il risultato di un qualunque snippet di codice .NET compilandolo “al volo” tramite CSharpCodeProvider.

Lo screenshot seguente mostra, nello scenario di test presentato all’inizio, un test “al volo” della validazione della mail in questione:

Expression

Abbiamo quindi “cablato” il test verificando che con email “test@gmail.com” il metodo Regex.Match restituisce Success == true. Possiamo inoltre navigare il risultato: ad esempio possiamo ispezionare la collezione Groups, ottenendo i relativi gruppi in modo molto semplice:
Navigate

Volendo potremmo immergere il test in più input significativi creando una piccola procedura come segue:
Program

Se il codice che stiamo copiando o incollando fa uso di librerie esterne (create da noi o scaricate) possiamo includerle in modo da farle riconoscere dal compilatore.

Nell’esempio precedente si nota l’extension method Dump che consente di mostrare a video il contenuto di una qualunque struttura consentone una semplice navigazione tra strutture complesse. Prendiamo come esempio un Dictionary… in LINQPad tramite Dump lo visualizzereste in questo modo, direi piuttosto comodo, no…??
Dictionary

Uso di LINQPad

LINQPad si presta benissimo ai seguenti usi:

  • test al volo di nostro codice copiato/incollato da VS
  • test al volo di API .NET come LINQ, PLINQ, RX, …
  • test degli stati intermedi del chaining (qui un approfondimento)
  • apprendimento tramite esperimenti di librerie del framework .NET o di terze parti scaricate tramite NuGet
  • ispezione e navigazione di strutture e relazioni
  • navigazione del database senza passare per continue JOIN
  • analisi del database da un più alto livello di astrazione
    • grazie a ORM supportati come EF
    • grazie a provider supportati come MSCRM, Sharepoint, Azure, DataMarket, OData, StreamInsight, …
  • utility di uso comune tramite extension method (qui alcuni extension method di terze parti)
    • query LINQ che generano file CSV
    • query LINQ che generano SQL complessi da inviare via mail

Prossimi passi…??

Questi i prossimi passi per guadagnare la cintura marrone in LINQPad:

  1. Scarica LINQPad
  2. Scrivi il tuo codice normalmente in Visual Studio
  3. Appena terminato un metodo, anche semplice, copialo in LINQPad
    1. Se il tuo metodo fa uso di strutture esterne copiale direttamente o, se troppe, includi la dll
  4. Esegui su un input di esempio e ispeziona tramite Dump che tutto sia ok
    1. Se necessario verifica anche i tempi di esecuzione riportati
    2. Se necessario salva il codice per un futuro uso nella cartella “My Queries
  5. Rendila un’abitudine nel tuo lavoro quotidiano

Se veramente diventa un’abitudine eviterai il 90% degli errori, abbattendo ore noiose e degradanti di debugging…

Questi i passi invece per guadagnare la cintura nera in LINQPad:

  1. nella posizione dove di solito apri SQL Server Management Studio, rimpiazzalo con LINQPad
  2. apri sempre LINQPad al suo posto e fai le query solo utilizzando LINQ
  3. dopo un periodo di iniziale lentezza rispetto a SSMS scoprine i vantaggi
  4. non eseguire più join… limitati a seguire i link
  5. non ripetere più le stesse query… crea extension method riusabili
  6. non ipotizzare le query LINQ prodotte… verifica il SQL e prendine consapevolezza

Sperimenta nuove API con LINQPad. Pronti per lo step??

Posted in .net, test | No Comments »

Linq: Panoramica delle Funzionalità

Posted by Ricibald on 7th March 2008

Prima di leggere questo post consiglio a chi non ne fosse a conoscenza di leggere le novità del Framework 3.5 di .NET.

La più grande novità per lo sviluppatore inclusa nel .NET Framework 3.5 è senza dubbio LINQ. LINQ è l’acronimo per Language INtegrated Query.

Cosa è LINQ

LINQ non è altro che un’estensione del linguaggio che permette di eseguire query verso una determinata risorsa. La sintassi di query rimane la stessa e la risorsa può essere:

  • un file XML (LINQ To Xml): più semplice e veloce rispetto a utilizzare XPath
  • una collection di classi (LINQ To Objects): più semplice che ciclare gli elementi uno a uno
  • un database (LINQ To SQL): più sicuro e performante che invocare sql realizzate a run-time

La maggior parte delle funzioni di LINQ si basano sulle nuove caratteristiche del Framework. Soprattutto:

Di fatto la parte più interessante è il LINQ To SQL e rappresenta l’implementazione Microsoft della tecnica ORM.
Supporta transazioni, viste e stored procedure. Fornisce inoltre un semplice modo per integrare validazione dei dati e logica di business direttamente nel modello dati.

Come funziona LINQ

Come funziona? Semplice: Eseguo “Add -> New Item -> Linq To SQL Classes” e creo Universita.dbml.
Nel designer si possono trascinare tabelle e stored procedure e verranno automaticamente create:

  • classe UniversitaDataContext, che contiene tutti gli oggetti (Universitas, …) e metodi (stored procedure) del db, tipizzati fortemente
  • classi varie che rappresentano la versione tipizzata delle singole tabelle (Universita, Studente, …)

Realizza in questo modo un efficace ORM. Le classi sono fortemente tipizzate e le proprieta’ inserite devono essere quindi conformi al
tipo dichiarato nello schema del db, altrimenti verranno sollevati errori di compilazione (impossibile convertire da string a int…).
Il collegamento tra i controlli web e LINQ si ottiene tramite il nuovo LinqDataSource.

Un Esempio Pratico

Immaginiamo di avere un semplice db con due tabelle: studente e università, in cui studente ha un vincolo di integrità referenziale
verso università. Dopo aver trascinato le due tabelle nel designer e aver salvato il file Universita.dbml possiamo utilizzare le classi
generate nel seguente modo:

UniversitaDataContext db = new UniversitaDataContext();
Studente s = new Studente() { Matricola = "1234" };
Universita u = new Universita() { Name = "Roma Tre" };
u.Studenti.Add(s);
db.Universitas.Add(u);
db.SubmitChanges();

Questo creerà la corrispondente istruzione SQL trasferendo in modo atomico le modifiche apportate all’oggetto dall’ultimo submit:
mantiene quindi un sistema di versioning in modo automatico e un contesto di transazione.
Le classi generate sono parziali, e questo consente di apportare modifiche e/o aggiunte alla classe generata dal designer.

Personalizzazione del comportamento

Le proprieta’ (colonne) possono essere caricate su richiesta (lazy loading) impostando a true la proprieta’ Delay Loaded.

Le classi definiscono dei punti di estensibilità tramite metodi partial, che rappresentano una novità del framework 3.5. In tali punti si possono definire le azioni da eseguire prima e/o dopo aver settato una proprietà. Risultano utili per inserire validazione dei dati non verificabili dal db, come il check del formato email. I metodi parziali che vengono definiti sono:

partial void OnXXXChanging(YYY value);
partial void OnXXXChanged();

dove XXX è il nome della proprietà, e YYY il suo tipo.

In questo modo possiamo validare il formato dei dati, ma non la logica di inserimento. Se ad esempio vogliamo che la proprietà DataIscrizione
sia minore di DataLaurea allora dobbiamo eseguire tale controllo in un punto separato. Per questo viene messo a disposizione un ulteriore
metodo parziale per gestire questo differente tipo di logica di validazione:

partial void OnValidate(ChangeAction action);

In modo analogo, per definire una logica customizzata prima di un INSERT, UPDATE e DELETE, nella classe UniversitaDataContext
saranno disponibili i punti di estensione:

partial void InsertStudente(Studente instance);
partial void UpdateStudente(Studente instance);
partial void DeleteStudente(Studente instance);
partial void InsertUniversita(Universita instance);
partial void UpdateUniversita(Universita instance);
partial void DeleteUniversita(Universita instance);

Normalmente saranno utilizzate nel seguente modo:

public partial class UniversitaDataContext {
    partial void InsertStudente(Studente instance) {
        // TODO: custom insert validation logic
        this.ExecuteDynamicInsert(instance);
    }
}

Stored Procedure

Le stored procedure possono essere aggiunte semplicemente trascinandole nel designer. Se non restituiscono un tipo specifico
(Studente o Universita) non ha senso utilizzare quello automaticamente generato (che potrebbe cambiare in caso di conflitti).
Utilizzare var in questo caso. Un esempio pratico: trascino la stored procedure GetMatricoleStudenti nel designer e scrivo:

UniversitaDataContext db = new UniversitaDataContext();
foreach(Universita univ in db.Universitas) {
    var matricoleStudenti = db.GetMatricoleStudenti(univ.Id);
    foreach(var matricolaStudente in matricoleStudenti) {
        Console.WriteLine(matricolaStudente.Matricola);
    }
}

Se le stored procedure restituiscono un insieme di dati compatibile con una determinata tabella (ad es.Studente), allora si può trascinare la stored procedure
direttamente NELLA tabella e tale stored procedure restituirà quindi un risultato IEnumerable<Studente>.

Si possono anche gestire risultati con forme multiple (una stored procedure potrebbe restituire diversi record set a seconda
del flusso dell’operazione). In questo caso non possiamo trascinare la stored procedure nel modo usuale, ma richiamarla “a mano” via codice
(sempre nella classe UniversitaDataContext) dichiarando le possibili classi restituite tramite l’attributo ResultTypeAttribute.

Si possono anche definire in ogni tabella operazioni personalizzate di INSERT, DELETE, UPDATE in modo da collegarle
a una particolare stored procedure.

Conclusioni

Ricordate quando avevo detto che LINQ To SQL rappresenta l’implementazione Microsoft ORM? Non è completamente vero… Di fatto rappresenta un modo tipizzato per accedere alle proprietà del db. Osserviamo ad esempio l’analisi di Pietro Brambati. La relazione molti-a-molti autore-libro viene fatta corrispondere alle tre tabelle che il db rappresenta. Un’altra critica che è stata mossa è il fatto che le classi generate (Studente, Università, …) sono di fatto “sporcate” con tanti attributi e metodi che non si vorrebbero vedere nei
propri oggetti di dominio.

Per questo esiste il progetto LINQ to Entities: un’altra implementazione di LINQ fatta per parlare con l’ADO.NET Entity Framework (EF). Sia l’EF che LINQ to Entities sono attualmente in Beta 3. L’EF è un framework che consentirà agli sviluppatori di lavorare con un maggior livello di astrazione; cioè uno sviluppatore si concentrerà solo sul modello concettuale proprio del modello Entità-Relazione, in maniera indipendente dallo storage sottostante sia esso SQL Server o un altro database.

LINQ to Entities realizza un VERO ORM, supportando quindi relazioni molti-a-molti e generalizzazioni e separando il mapping da relazionale a oggetti in file xml separati, in modo da non inquinare l’interfaccia delle classi generate. Come detto, siamo in una versione non completamente matura e per questo è stato deciso di posticipare l’uscita di questa branca a circa sei mesi dopo l’uscita di Visual Studio 2008 e perciò l’infrastruttura attualmente presente potrebbe subire forti cambiamenti.

Maggiori informazioni sulle differenze tra LINQ To SQL e LINQ To Entities sono riportate nel post di Kevin Hoffman.

Posted in .net | 1 Comment »