marzo 2007 Entries
[OT] E anche il Crad entra nella next-gen

Già, da ieri sono felice possessore di una Xbox 360 nuova fiammante. Meglio tardi che mai! Non avendo ancora un televisore HD-Ready, ho comprato il cavo VGA e l'ho collegata al monitor 19" del PC. Che dire... Gears of War è semplicemente qualcosa di mai visto, oltre che super divertente.

Ora devo trovare il tempo di far fuori un centinaio di locuste. E comprare anche NBA 2K7 e Call of Duty 3 smile_shades

3 Comments Filed Under [ Off topic ]
Lettera aperta a ScottGu

Parlando e lavorando con gli sviluppatori che giornalmente lavorano con i vostri prodotti, ho percepito confusione e preoccupazione sulla vostra relazione con la community open source che si è sviluppata attorno alla tecnologia .Net. Mentre Sun, IBM, altri fornitori di piattaforme, e ISV riconoscono la comunità open source come una base di codice complementare ai propri prodotti, Microsoft ha la tendenza a usare il brillante lavoro della comunità come una feature map per .Net.

Scritta da Hamett e ribadita da Ayende. Il testo completo è qui. D'accordo praticamente su tutto.

7 Comments Filed Under [ Misc ]
Forse un problemino in OracleClient?

E' sicuramente una best practice quella di chiudere un datareader quando questo è stato utilizzato. Consideriamo però il seguente snippet di codice:

DBConnection connection; using (connection = factory.CreateConnection()) { DBCommand cmd = connection.CreateCommand(); // some code DBDataReader dr = cmd.ExecuteReader(); // some code } Console.WriteLine(connection.State);

Il cursore non viene esplicitamente chiuso, questo è vero, ma viene comunque invocata la dispose della connection verso il DB.

Con SqlClient questo snippet funziona come previsto, stesso dicasi per OleDbClient e per Oracle.DataAccess: lo snippet stampa "Closed" sulla console e, se si disabilita il connection pool, si può notare come all'esterno del blocco using non ci sia alcuna connessione attiva presso il DB Server.

Con System.Data.OracleClient, invece, si verifica un comportamento anomalo: nonostante la connection risulti comunque chiusa, fisicamente al termine dello snippet si può verificare come rimanga una connessione appesa e quindi non riutilizzabile neanche dal connection pool. Questo non accade chiudendo esplicitamente il datareader, con una leggera variante allo snippet di prima:

DBConnection connection; using (connection = factory.CreateConnection()) { DBCommand cmd = connection.CreateCommand(); // some code using (DBDataReader dr = cmd.ExecuteReader()) { // some code } } Console.WriteLine(connection.State);

Ovviamente me ne sono accorto in produzione :-(

Add Comment Filed Under [ .Net 2.0 ]
Per quelli che... "l'architettura è solo frizzi e lazzi"

In questi giorni, insieme al mio team, ci stiamo cimentando nella realizzazione di un progetto piuttosto complesso in tempi (quando mai) a dir poco strettissimi. Si tratta di una condizione piuttosto estrema, tant'è che non è stato affatto facile far digerire a tutti l'idea di pensare ad un'architettura ben fatta, di separare i compiti tra i vari layer e di scrivere gli unit test.

Alla fine per fortuna il buon senso ha prevalso, e la nostra applicazione, ora come ora

  1. ha il suo bel domain model
  2. è suddivisa in layer, tutti disaccoppiati ed esposti solo tramite interfacce
  3. fa uso di inversion of control, dependency injection e aspect oriented programming

Quali vantaggi *PRATICI* e quale *RISPARMIO* (in termini di fatica e tempo) ci ha portato l'evitare di buttar giù la testa e mettersi a scrivere codice?

Sul punto 1 non mi soffermo, è oramai piuttosto noto come il modello tabellare mal si adatti a variazioni dell'informazione da trattare, cose che capitano spesso, soprattutto nelle fasi iniziali di un progetto, in cui i requisiti non sono ancora perfettamente definiti.

Passiamo al punto 2. La suddivisione in layer ha consentito di dividere il nostro team in diversi gruppi, che si sono concentrati separatamente nello sviluppo delle rispettive librerie.

Il team del DAL ha lavorato a stretto contatto con il responsabile dello sviluppo su DB Oracle.

Il team del BL, proprio grazie al fatto che il DAL è esposto tramite interfacce, ha potuto sviluppare la libreria di propria competenza senza che il DAL esistesse, facendo uso di Test Driven Development e di mocking.

Idem dicasi per il team che si è dedicato al presentation layer.

Prima conclusione: creare interazioni loosely-coupled consente di parallelizzare il processo di sviluppo. Con librerie fortemente accoppiate, sarebbe stato un dannato incubo.

Punto 3. Lo scenario di deploy sarà sicuramente distribuito: il database non sarà direttamente esposto al web server su cui girerà la nostra applicazione, che dovrà pertanto interagirvi tramite web service. Ottimo. Peccato che attualmente

  1. Non c'è tempo per realizzarli
  2. Ancora non è chiaro quale tecnologia utilizzare (WCF? WSE? ASP.NET?)

Ma a noi cosa ci frega? I layer comunicano esclusivamente tramite interfacce, quindi posso usare tutta la inversion of control che voglio: al momento, in cui non ci sono risorse da dedicare allo sviluppo dei web service, espongo direttamente le librerie che connettono i vari strati; domani, quando ci sarà più calma, realizzerò lo strato di trasporto, che esporrò tramite le stesse interfacce ed in maniera del tutto trasparente ai layer utilizzatori: ma se oggi per caricare un utente scrivo

IUserServices userServices = ServicesRepository.Get<IUserServices>(); User currentUser = userServices.LoadById(userId);

domani, quando dentro quello IUserServices ci sarà un proxy che si collegherà ad un web service, il mio codice continuerà ad essere perfettamente valido e funzionante. Senza una buona architettura, avrei dovuto realizzare un qualcosa che in seguito avrei dovuto smontare completamente e ricreare da zero.

Ma ancora... il fatto di disaccoppiare gli strati applicativi mi consente di iniettare logica in maniera assolutamente pervasiva: fino ad oggi, leggere una entity da DB comportava la lettura di tutti gli oggetti associati. So che non è bello, è sicuramente uno spreco di risorse leggere informazioni che probabilmente non saranno mai utilizzate. Ma sono convinto che, dal momento in cui si decide di utilizzare un domain model, bisogna *garantirne* la navigabilità: lo  sviluppatore, dopo aver caricato l'oggetto User, deve poterne esplorare le dipendenze quando e come vuole. Ma allora? siamo alle solite... una buona architettura mi ha consentito, con un pizzico di AOP, di implementare un LazyLoad che fa perfettamente al nostro caso e che, meraviglia delle meraviglie, fa il paio con l'inversion of control del paragrafo sopra, funzionando senza incertezze sia con lo strato di servizi "in presa diretta" che con nello scenario distribuito che oggi non c'è ma che domani si dovrà necessariamente realizzare (perché è da specifiche). Prossimamente, riuscirò ad introdurre un sistema di log automatico, quantomeno per chiamate ai servizi e errori, e una cache.

Seconda conclusione: l'uso di IoC, DI e AOP ci consente di impostare il lavoro di progettazione e sviluppo su "ciò che sappiamo che un giorno ci sarà", senza badare a quel poco che c'è oggi. Le funzionalità aggiuntive potranno essere realizzate in maniera del tutto indipendente, man mano che si libereranno risorse, e poi introdotte a costo quasi nullo all'interno di quanto già esistente.

Ecco perché, da un paio d'anni a questa parte, la mia passione per questi argomenti è andata via via crescendo e perché sono assolutamente convinto, a dispetto di ciò che molti possono pensare, che una buona ingegnerizzazione del software consente di risparmiare *DA SUBITO* (e non dalla fantomatica versione 2.0 che probabilmente non vedrà mai la luce) tempo, fatica e risorse umane, producendo un risultato qualitativamente con pochi eguali.

 

Technorati tags:
8 Comments Filed Under [ Architettura ]
[WCF] Attenzione alle Using

In Windows Communication Foundation, il proxy creato da svcutil eredita dalla classe ClientBase<T>, che a sua volta implementa l'interfaccia IDisposable. Conseguenza di questo fatto è che viene naturale invocare il nostro bel servizio scrivendo:

using (MyServiceClient client = new MyServiceClient()) { // more code goes here... }

Ma se l'invocazione genera un errore, cosa accade? L'utilizzo del blocco using ci garantisce che venga chiamato il metodo Dispose() di MyServiceClient, che, Reflector alla mano, non fa altro che invocarne il metodo Close().

Attenzione però all'eccezione rilanciata se lo stato del client è Faulted (accade ogni volta che si verifica un errore non recuperabile, ad es. il server ha chiuso la connessione): in questo caso, infatti, al posto di Close andrebbe invocato il metodo Abort. L'uso di Close determina il sollevarsi di una CommunicationObjectFaultedException che oscura completamente l'errore verificatosi all'interno del blocco using.

Per ovviare a questo problema, ho costruito una classe helper che chiude il client in maniera un po' più furba:

public class SafeClose: IDisposable { private ICommunicationObject communicationObject; public SafeClose(ICommunicationObject co) { communicationObject = co; } public void Dispose() { try { if (communicationObject.State != CommunicationState.Faulted) communicationObject.Close(); } catch { communicationObject.Abort(); } } }

La sintassi di utilizzo è solo di poco più prolissa:

MyServiceClient client; using (new SafeClose(client = new MyServiceClient())) { Console.WriteLine(client.MyMethod()); }

HTH.

Ciao smile_wink

Add Comment Filed Under [ .Net 3.0 ]
Altro che .NET Pizza...

Tsk tsk... gli uomini duri preferiscono la .NET Super Bisteccazza Capitolina (TM)!! Eheheheheh!! A parte gli scherzi, grazie mille a Lorenzo "Marco sei un cogl..." Barbieri e Stefano Mostarda per la bellissima cena di ieri sera, grazie alla tipa con le calze fucsia, l'unica in grado di interrompere le nostre chiacchiere .nettare e non, e grazie anche a chi ha inventato la fiorentina!

E ora dormo! :D

7 Comments Filed Under [ Off topic ]