Latest Posts
Il primo “giro” di Radical mi sembra di poter dire sia andato bene, ci sono un po’ di cose da affinare ma direi che non mi posso lamentare troppo, ovviamente grazie a tutti i partecipanti.
La registrazione e il materiale del primo incontro è disponibile per il download.
Come da richiesta stiamo organizzando il secondo round il cui scopo è affrontare una “semplice applicazione per editare delle anagrafiche”, gli argomenti che tratteremo sono:
- CRUD usando RavenDB Embedded allo scopo di tener bassissima la complessità, pensate a RavenDB (in questo caso) come un mero meccanismo di serializzazione su disco (è molto ma molto di più ma in questo scenario lo useremo solo come storage nudo e crudo);
- Validazione usando i sistemi built-in di Radical e il supporto out-of-the-box per le DataAnnotation;
- Memento perché in un editor di anagrafiche un undo/redo non si nega a nessuno;
- Windsor Installer(s) ovvero come inserirsi nella pipeline di configurazione del nostro motore di IoC preferito quando le convenzioni di Radical non soddisfano le nostre necessità;
- Perché no…come e che cosa possiamo sfruttare di async/await;
Come al solito ci sono un po’ di date (non troppe questa volta) disponibili, sotto con le votazioni: http://www.doodle.com/m5rpuudxt474ies7
.m
interessante articolo da leggere
link articolo
Ci vuole metodo!
Ma lo sapevate che metodo è una parola greca che significa "inseguire"?
Inseguire per arrivare allo scopo... e, soprattutto nel nostro lavoro, questo è molto importante.
Quando iniziamo a lavorare su qualcosa di nuovo, possiamo permetterci una fase esplorativa ma, subito dopo, occorre un metodo di lavoro. Questo ci permetterà in futuro di ottimizzare i procedimenti successivi simili e di rendere tali procedimenti accessibili a tutti (sempre nell'ipotesi di volerlo fare, dato che in alcune aziende alcuni pensano che l'oscurantismo sia sinonimo del mantenimento del posto di lavoro).
Se riusciamo a darci un metodo in ogni operazione che effettuiamo, piano piano, sapremo cosa fare in ogni situazione. Non escludo che l'insieme delle situazioni possa non essere finito, ma spesso potremo rientrare in casi precedentemente trattati.
In tutto ciò è molto importante capire che, se il metodo che utilizziamo è lo stesso di altri colleghi, può essere formalizzato e diventare ufficiale. In pratica si decide che una determinata operazione si effettua in un determinato modo. E questo porta anche alla descrizione di intere procedure che permetterebbero anche a un'azienda di certificarsi più facilmente.
E' importante sottolineare che il metodo deve partire dalla necessità e non essere imposto dall'alto, altrimenti non può funzionare.
Inoltre, il metodo non può essere rigido ma deve continuamente adattarsi alle situazioni e, per tale motivo, si evolve. Questo può sembrare un paradosso. Va comunque capito quando una variazione rientra nel metodo stesso e quando, invece, si applica il metodo base e poi una successiva aggiunta.
L'azione metodicizzata sarà maggiormente controllabile e darà sicurezza alla persona che la utilizza.
EF 5 aggiunge una importante opzione di configurazione riguardante la "traduzione" delle lambda con parametri NULL: UseCSharpNullComparisonBehavior.
Se impostata a true, il comportamento è simile al comportamento che noi Dev siamo abituati con il valore null di C#. Ma andiamo con ordine:
Tabella:
Id Name
1 Uno
2 NULL
3 NULL
4 due
5 tre
Codice:
result = db.NullableTables.Where(e => e.Name == null).Count();
Console.WriteLine("Entries where Name=null: {0}", result);
result = db.NullableTables.Where(e => e.Name != null).Count();
Console.WriteLine("Entries where Name!=null: {0}", result);
string name = null;
result = db.NullableTables.Where(e => e.Name == name).Count();
Console.WriteLine("Entries where Name==name & name=null: {0}", result);
Risultato standard:
"Entries where Name=null: 2" //corretto
"Entries where Name!=null: 3" //corretto
"Entries where Name=name & name=null: 0" //wrong?
Il problema dell'ultimo risultato riguarda il metodo utilizzato da EF per convertire la lamba expression "e=>e.Name=name" in TSQL: "Where Name=@p1, @p1=null". In SQL =NULL è sempre false, al contrario del primo esempio dove EF converte la lambda in "where Name IS NULL".
Come possiamo rendere la conversione più C# friendly? con la seguente istruzione (messa nel costruttore del nostro DbContext):
((IObjectContextAdapter)this).ObjectContext.ContextOptions.UseCSharpNullComparisonBehavior = true;
In questo caso, rieseguendo il codice precedente, otterremo il seguente risultato:
"Entries where Name=null: 2" //corretto
"Entries where Name!=null: 3" //corretto
"Entries where Name=name & name=null: 2" //corretto?
Da notare come questa opzione sia disabilitata di default(causa compatibilità).
Ok, spero innanzitutto che Oscar Wilde non si stia troppo lamentando per la citazione a sproposito presente nel titolo :-) Ciò premesso, questo tip appena pubblicato su UGIdotNET mi ha riportato alla mente un episodio che descrissi in questo post: più che sull’argomento in sè ho riflettuto sul fatto che nell’anno 2000, quando mi trovai a dover risolvere il problema citato nel post, spesi svariate giornate per giungere alla soluzione ivi descritta perchè per scoprire l’esistenza di quella modalità di scrittura “non logged” di SQL Server dovetti spulciare la documentazione di SQL Server ed altrettanta ne spulciai per capire come, utilizzando le estensioni custom del suo driver ODBC, trarre vantaggio da quella tecnica.
Per certi versi si trattò di un interessante esercizio speculativo che mi lasciò in dote qualche conoscenza in più in merito ad alcuni internals di SQL Server, ma con il senno di poi penso che i servizi offerti dalla classe SqlBulkCopy sono un ottimo esempio di cosa dovrebbe fare un framework, ossia offrire delle primitive ad un (ragionevole) livello di astrazione che permetta allo sviluppatore di dedicare il proprio tempo alla soluzione della parte “pregiata” (si ok, si scrive “pregiata” ma si legge “domain”…) di un problema potendo far affidamento su un substrato tecnologico che sia in grado di sfruttare la tecnologia/piattaforma sottostante.
In questo senso, nonostante l’ipertrofia che ormai lo caratterizza, penso a quanto valore ci sia nel .NET Framework che ormai diamo per scontato e quanto avrei preferito, mentre nel 2000 dovevo risolvere da solo il problema in oggetto, aver a disposizione SqlBulkCopy potendo dedicare meno tempo al lavoro e magari usare il tempo risparmiato per un Mojito in buona compagnia… :-)
Siamo quasi pronti :-) abbiamo due opzioni, di cui la seconda sarà usata come backup.
Office Live Meeting
La scelta principale è Office Live Meeting, offre più funzionalità per chi presenta, miglior gestione della conferenza e delle registrazioni, i dettagli del meeting pianificato sono i seguenti:
Accesso: https://www.livemeeting.com/cc/mvp/join?id=Radical1&role=attend
Meeting ID: Radical1
Il tutto sarà live dalle 21 di stasera, vi pregherei di connettervi il prima possibile per assicurarci che entro le 21.30 tutto sia pronto e testato.
è necessario aver installato il client di Live Meeting (installabile dalla pagina di cui sopra) oppure è disponibile il client via web (che ha qualche funzionalità in mento, rilevante solo per chi presenta il meeting)
Google Hangout
Siccome potremmo avere qualche problema di banda, la qualità della mia connettività è purtroppo quel che è, ho anche già preparato un evento pubblico usando un Google Hangout che trovate qui: https://plus.google.com/events/cvtsanp7b4i95afsibe7g2qfv48
Decidiamo all’ultimo momento se provare a cambiare provider.
Per qualsiasi cosa commentate su questo post o usate Twitter: @mauroservienti
.m
Potete leggere le novità del nuovo sprint deployato su TF Service direttamente su GetLatestVersion.
In questo caso la novità più succosa è avere più repository Git per singolo Team Project.
Gian Maria.
Uno degli elementi più controversi della User eXperience di Windows Phone è il tasto back, che per comportarsi “come l’utente si aspetta”, alle volte va gestito da programma.
Per spiegare meglio cosa intendo, utilizzerò un come esempio un’applicazione che richiede l’autenticazione dell’utente tramite Facebook la prima volta che viene utilizzata.
Un’implementazione (all’apparenza ben fatta) potrebbe essere la seguente:
1. All’avvio dell’app, viene mostrata la pagina principale. La logica di programma si accorge di non avere le credenziali dell’utente (dunque è il primo utilizzo) e mostra la pagina di autenticazione;
2. La pagina di autenticazione lancia l’autenticazione (utilizzando ad esempio Facebook SDK for .NET) che mostra la pagina web di Facebook.
3 L’utente immette i dati nella pagina web di Facebook, e si torna alla pagina iniziale dell’app.

Peccato che un’applicazione così farebbe drizzare i capelli anche a me che li ho persi da un bel pezzo, perché con quest’applicazione il tasto back si comporterebbe in un modo che l’utente giudicherebbe (eufemisticamente) non corretto.
E il motivo è presto detto:
Ogni volta che viene mostrata una pagina, la pagina precedente viene inserita nello stack “Navigation History”. Ogni volta che si preme il pulsante back, viene mostrata la pagina che sta in cima alla pila, e il riferimento a tale pagina viene rimosso dallo stack. Se lo stack è vuoto, il tasto back chiude l’applicazione.
Dunque nel nostro caso, dopo aver completato l’autenticazione ed essere tornati alla “Main Page”, il nostro stack conterrà i seguenti elementi:

Ora, dal punto di vista dell’utente, il tasto back dovrebbe farlo uscire dall’app. Infatti egli è entrato nell’app, ha svolto un lavoro, è tornato al punto di partenza (la “Main Page”) e col tasto back si aspetta di uscire dall’app. Poiché invece lo stack di Navigation History non è vuoto, la pressione del tasto back lo farà tornare nella “Facebook Page” dove gli verrebbe richiesto di nuovo di autenticarsi con Facebook! E peggio ancora, un’eventuale ulteriore pressione del tasto back lo farebbe tornare nella Login Page che automaticamente mostrerebbe la “Facebook Page”, entrando in un loop infinito:

Come si risolve il problema?
Utilizzando i vari metodi messi a disposizione dal NavigationService: GoBack() e/o RemoveBackEntry().
Per saperne di più:
- How to navigate using the back stack for Windows Phone
Happy coding!
Qualche giorno fa abbiamo accennato alla possibilità di fare una sessione introduttiva a Model View ViewModel con Radical: le adesioni sono per gestite con un doodle.
Sembra che la maggioranza abbia votato per domani (15/05) alle 21.30, e così sia la prima sessione la terremo domani, a breve posterò anche il link e lo modalità di erogazione. Se riusciamo la registro e magari la ripetiamo anche, o la evolviamo con una seconda puntata, se la cosa “ci” piace.
.m
Forse non tutti sanno che… OAuth non è un protocollo di autenticazione, ma bensì un protocollo di autorizzazione il cui scopo, nello specifico, è quello di delegare un terzo attore ad accedere ad una risorsa verso cui il delegante è autenticato e autorizzato.
Diciamo che questo, OAuth non è un protocollo di autenticazione, è uno dei buoni motivi per cui Twitter non è uno degli IdentityProvider supportati dell’ACS di Windows Azure.
Diciamo anche che avete questo scenario:
- State lavorando ad un progetto che tra le tante cose espone un’API che sarà pubblica;
- Avete bisogno che le applicazioni che in qualche modo vorranno consumare quell’API siano autorizzate, dall’utente che le sta usando, ad accedere ai dati dell’utente stesso in sua vece;
- Avete scelto di delegare tutta la gestione della sicurezza all’ACS di Windows Azure, in modo da poter supportare vari IdentityProvider tra cui ad esempio Google Account e Microsoft Account;
L’obiettivo quindi è di far si che:
- L’applicazione, tipicamente un “app” su un device mobile, che l’utente ha scelto di usare sia in grado di connettersi all’API pubblica;
- Al primo tentativo di connessione esegua il processo di login delegandolo all’IdentityProvider scelto dall’utente;
- Se l’app non si è mai presentata all’API pubblica parta il processo di autorizzazione in cui l’utente decide se vuole delegare l’app per l’accesso ai suoi dati;
- Se l’utente decide di autorizzare l’applicazione venga rilasciato un token, con una scadenza, che garantisca l’accesso;
OAuth ha esattamente questo scopo, nonostante le critiche e le idiosincrasie del protocollo se ci si mette di buzzo buono non è poi così difficile realizzare il tutto (alla fine sono un po’ di chiamate HTTP, nulla a che vedere con lo scambio di messaggi di WS-Federation).
Il flusso tipico con OAuth è il seguente:

L’inghippo
in tutti gli esempi che trovate che parlano di OAuth si da per scontato che chi autorizza sia anche chi autentica, ma nel nostro caso vogliamo che il processo di autenticazione sia delegato all’ACS di Azure:

L’obiettivo è come al solito quello di delegare a chi lo sa fare bene tutta la gestione dell’infrastruttura di sicurezza.
Little gem
Una delle cose poco note è che l’ACS di Azure ha già tutto il supporto per:
- gestire l’elenco della applicazioni autorizzate;
- gestire l’elenco delle deleghe;
- gestire l’emissione dei token di accesso;
Questa funzionalità si chiama “Service Identities” e la trovate sul portale di amministrazione del namespace dell’ACS:

Una “Service Identity” rappresenta un’applicazione autorizzata a chiedervi la delega per accedere alle vostre risorse.
Contorto…una “Service Identity” è un’applicazione registrata da uno sviluppatore (un po’ come quando registrate una nuova applicazione su Facebook), ad una “Service Identity” corrispondono un “application id” e un “application secret” che sono username e password dell’applicazione, l’utente finale autorizzerà poi l’applicazione (identificata da app id e secret) ad accedere alle sue risorse, questa autorizzazione si chiama delega, anche la delega è completamente gestita da Azure, ma non è visibile dal portale, c’è invece un’API rest che vi consente di manipolare i contenuti delle deleghe di ogni applicazione in modo, ad esempio, da poter dare la possibilità all’utente finale di decidere se e come revocare ad un’applicazione la delega.
.m
Dopo aver installato Team Foundation Server 2012 Update 2 puo’ succedere che il Work Item Tracking Synchronization Service improvvisamente si blocchi, e che quindi non si vedano piu aree ed iterazioni aggiornate in Visual Studio, Web Access, Excel, etc.
Questi sono i sintomi…


Ovviamente per fare troubleshooting di questo bug, i log della pagina amministrativa _oi sono essenziali:
Vediamo che da un certo momento in poi, un certo numero di job Work Item Tracking Integration Synchronization falliscono…
…e nella Job History Details troviamo un System.NullReferenceException. Ecco il problema!
Nella RC del Team Foundation Server 2012 Update 3 troviamo una fix per questo, come dettagliato nel changelog (paragrafo Work Item Tracking nelle fix per Team Foundation Server).
mongod --journal --dbpath=
path_db --install --logpath=
path_log
dopo è necessario avviare il servizio creato con
net start mongodb
Con Team Foundation Server 2012 il licensing e’ stato estremamente semplificato, in modo da avere un percorso di adozione piu’ chiaro per le feature impattate. Un grande esempio di questo e’ il nuovo Web Access.
Il nuovo Team Web Access mette a disposizione tre livelli di accesso alle informazioni, dipendenti dalla CAL che si ha:

Questi tre livelli espongono un set di informazioni (e di feature) differenti per l’utente.

Un utente che accede al Web Access con un livello Limited avra’ piu’ o meno la stessa esperienza di utilizzo della vecchia modalita’ Work Item Only View in Team System Web Access. Questo utente accedera’ a tutti I work item che gli appartengono senza la necessita’ di una CAL.

Il livello Standard e’ per chi ha un Visual Studio 2012 Professional, ed aggiunge tutte le funzionalita’ standard del Web Access oltre alle Board agili introdotte con la versione 2012.

Infine il livello Full e’ per chi ha un Visual Studio 2012 Premium o superior, ed abilita tutte le feature del Web Access, quindi anche il Backlog Management, il Feedback Management e – con l’Update 2 – il Web Test Case Management.
Se qualcuno fosse interessato la cosa si sta concretizzando: http://www.doodle.com/fvdb3zgtd2zi2wkv
Gli argomenti saranno:
- Model View ViewModel (WPF e Windows App principalmente, ma anche Windows Phone);
- Come sfruttare al massimo Radical per ottenere il massimo con MVVM;
Obiettivo è una chiacchierata/discussione e non una sessione formativa.
La partecipazione è libera, ovviamente ben accetta, nella speranza che la mia connessione domestica sia all’altezza ;-)
.m
In questo articolo su GetLatestVersion parlo di come sia possibile gestire in maniera più efficace il branching in TFS quando si hanno molte branch nel server, utilizzando una opzione del get a riga di comando poco conosciuta.
Buona lettura.
Potete trovare nella pagina dei power tools, l’ultima versione aggiornata, pienamente compatibile con l’Update 2. Come sempre per chi utilzza TFS, è un must download, sia nelle macchine dove è installato TFS, sia in tutte le macchine client.
Buon lavoro.
Nel Blog di Brian è stato pubblicato il link alla CTP del Quarterly Update 3 di Visual Studio e TFS. La Go-Live significa che il pacchetto può essere installato in produzione, è infatti installato nelle macchine di produzione di Microsoft ed infatti Brian assicura che il pacchetto è installato nelle loro macchine.
Il QU3 sarà primariamente un Bugfix. In particolare se avete specifici problemi in questa pagina potrete trovare I dettagli su tutti i bugfix in essa contenuti.
Buon Lavoro.
Gian Maria.
Tutte le volte che mi capita di parlare con qualcuno di CQRS o di sentire qualcuno parlare di CQRS ho la sensazione che ci si concentri troppo su quella che a mio modo di vedere è la parte meno importante tra le due componenti: i comandi; portare l’architettura verso un modello basato su comandi è fondamentale, sia chiaro, perché ci aiuta a modellare in maniera estremamente più semplice il modello mentale dell’utente, cosa che ci consente di fare un balzo in avanti eccezionale, ma i comandi sono anche la novità del momento e la “C” di CQRS sta oscurando quella che è una parte importantissima di CQRS: Query Responsibility Segregation.
Leggere, leggere e ancora leggere
Anche a scuola ci hanno insegnato che è importantissimo leggere ;-)
Quello che quasi certamente facciamo tutti i giorni, e anche le nostre applicazioni fanno, è nella maggior parte dei casi leggere dei dati, cercare dei dati e analizzare dei dati tutte operazione di lettura che si basano sulla possibilità di avere a disposizione quei dati.
Ma, parafrasando, la domanda è: Quando avete voglia di leggere, a casa vostra, che cosa fate?
Immagino che prendiate un unico gigantesco libro, in cui ci sono mischiate insieme le pagine di tutti i libri della vostra biblioteca, e cominciate a leggere saltando qua e la cercando di capire se la pagina che state leggendo ha attinenza con quella che avete appena finito di leggere…
Assurdo non trovate?
Allora la seconda domanda è: perché lo facciamo fare alle nostre applicazioni cercando di districarci in questo?

Pigrizia
Ammetto che l’unica buona motivazione che riesco a trovare è la pigrizia, abbiamo in nostro ORM di turno, mappiamo le classi del dominio modello a oggetti (fate un favore a voi stessi e siate onesti: non chiamate il robo la sopra dominio) e lo usiamo con il fidato linq:
var query = from order in session.Orders
from item in order.Items
where item.Product.Price > price
&& item.Quantity < qty
&& order.Customer.ShippingAddress.PostalCode == postalCode
select new
{
order.Customer.Name,
order.TotalPrice,
};
poi lo mettiamo in produzione, casualmente in produzione abbiamo un po’ di dati, sempre casualmente qualcuno si lamenta che è lento e stavolta per puro caso attacchiamo il profiler del nostro RDBMS di fiducia e inorridiamo (non tanto casualmente).
Questione di concetti
Il problema non è la query linq, che per inciso non so neanche se sia formalmente corretta, e neanche la tecnologia scelta per l’ORM e men che meno il database relazionale di turno, il problema è che stiamo cercando di usare un modello pensato per gli ordini per materializzare un modello pensato per le statistiche. Stiamo cioè mischiando quello che in DDD si chiamano Bounded Context e proprio perché sono “bounded” sono isolati e non possono essere mischiati.
La soluzione, al problema di cui sopra, è:
var query = from orderStat in session.OrderStats
where orderStat.ProductPrice > price
&& orderStat.ItemQuantity < qty
&& orderStat.ShippingAddress.PostalCode == postalCode
select orderStat;
Passiamo cioè da una join in cui materializziamo una proiezione ad una banale query, come questo venga tecnicamente risolto è un problema che non ci riguarda al momento, quello che è certo è che il “nostro mondo”, la nostra applicazione si è drammaticamente semplificata, aprendoci inoltre ad una pletora di possibili soluzione tecniche per risolvere la query espressa qui sopra, soluzioni che vanno dal mappare la query su una vista nel database e quindi fare tutto sempre con il nostro amato ORM a soluzione estremamente evolute basate su Event Sourcing e le de-normalizzazioni asincrone.
“molto piccoli e molto tanti” è la conclusione di quel post, riferendosi al fatto che se modelliamo il nostro mondo in tanti componenti molto piccoli otteniamo un modello complesso in cui i componenti semplici e piccoli collaborano per risolvere la complessità.
Il “Query Responsibility Segregation principle” ha lo stesso obiettivo: ridurre all’osso la complessità di ogni singola query facendo si che il modello dati prodotto da ogni singola query sia già nella forma giusta per lo scenario in cui deve essere usato.
La cosa bella è che è molto più semplice di quello che pensiamo, si tratta solo di scrivere un po’ di codice, cosa che del resto è il nostro pane quotidiano, l’altra cosa bella è che nella sua semplicità migliora drasticamente la qualità del nostro prodotto.
.m
Spesso ho bisogno di unire due liste di oggetti (ad esempio ricavati da sorgenti dati diverse) eliminando i duplicati (definiti secondo una qualche logica), quindi non il più facile “union all”. 
Mi ero stancato di riempire il programma di cicli for-each e select LINQ e ho cercato una soluzione “definitiva”.
L’ho trovata (come molte altre risposte) su StackOverflow. 
Innanzitutto definiamo una classe “InlineComparer” generica che ci permetterà di confrontare i nostri oggetti.
public class InlineComparer<T> : IEqualityComparer<T>
{
private readonly Func<T, T, bool> getEquals;
private readonly Func<T, int> getHashCode;
public InlineComparer(Func<T, T, bool> equals, Func<T, int> hashCode)
{
getEquals = equals;
getHashCode = hashCode;
}
public bool Equals(T x, T y)
{
return getEquals(x, y);
}
public int GetHashCode(T obj)
{
return getHashCode(obj);
}
}
Ora se ad esempio ho una classe “PalletDto” così definita…
public class PalletDto
{
public string PalletCode { get; set; }
public string LotCode { get; set; }
}
e voglio unire due liste (palletList1 e palletList2) eliminando i lotti della palletList2 dove il LotCode esiste già nella palletList1… dovrò “solo” scrivere:
var dupComparer = new InlineComparer<PalletDto>((l1, l2) => l1.LotCode == l2.LotCode, l => l.LotCode.GetHashCode());
var unionList = palletList1.Union(palletList2, dupComparer);
Happy coding <cit.>
Tag di Technorati:
LINQ,
Union
in questi giorni sto lavorando su di un "progettino" nel quale ho deciso di utilizzare sqllite, ho trovato un semplice e gratuito tool per la gestione di tale database :
http://www.sqliteexpert.com