Extending the world

Sul mio in inglese ho iniziato a scrivere una serie sull'utilizzo di Linq dal punto di vista dell'approccio funzionale, ovvero per esprimere computazioni, espandendo il concetto di Linq come "mondo" da estendere attraverso le nostre implementazioni. Sono aspetti per me piuttosto nuovi ma interessanti, e anche per capirli meglio ho deciso di scrivere una mini serie. Se l'argomento vi interessa, vi aspetto qui :)

Parrots su CodeProject

Qualche giorno fa ho pubblicato su CodeProject un articolo sulla libreria di "record and replay" stub objects che sto scrivendo. L'articolo cerca di essere piuttosto esaustivo sulle idee che stanno alla base della libreria, quindi può essere interessante per chi fosse curioso sull'argomento. Può essere trovato qui.

Parrots, background

Ho notato dalle statistiche sugli accessi un interesse non trascurabile per il lavoro che sto facendo con Parrots. Per chi volesse maggiori dettagli su quali sono i concetti di fondo su cui il lavoro si basa, ho scritto 2 righe qui. Grazie.

Parrots

Per chi fosse interessato, sto lavorando a una libreria open-source in C# che si basa su un'idea che chiamo di "record and replay mocking". Maggiori dettagli qui.

Code Metrics [1]

Come annunciato qualche giorno fa, ho iniziato la scrittura di una libreria estendibile per calcolare "code metrics". Se qualcuno fosse interessato alle motivazioni le trova qui. Sono arrivato al punto in cui il motore comincia a produrre qualche numero

Analyzer az = new Analyzer();
az.AddAssemblyFile(root + @"A\bin\Debug\A.dll");
az.AddAssemblyFile(root + @"B\bin\Debug\B.dll");

Analysis a = az.Generate(
new InstabilityAssemblyDependenciesWalker());

AssemblyDescriptor ad = a.Scan.FindAssemblyDescriptor("[A]");
Assert.IsNotNull(ad);
double i = ad.DescriptorCounters["Instability"];
Assert.AreEqual(0.75, i);

ad = a.Scan.FindAssemblyDescriptor("[B]");
Assert.IsNotNull(ad);
i = ad.DescriptorCounters["Instability"];
Assert.AreEqual(1, i);

E' possibile scrivere dei "visitor" esterni che navigano i grafi generati dall'analisi ed effettuano i loro calcoli. Nell'esempietto il "walker" InstabilityAssemblyDependenciesWalker utilizza un paio di visitor per il calcolo della metrica afferent coupling (Ca) e di quella efferent coupling (Ce), da cui poi ricava la metrica instability. Le definizioni delle suddette metriche si possono trovare per esempio qui.

Quando avrò un paio di metriche sensate cercherò di scrivere un modulo consumatore in grado di generare reportistica xml, e poi metterò il tutto su Codeplex. Il nome non l'ho ancora deciso, ho qualche idea ma non sono ancora convinto

powered by IMHO 1.3

Analisi delle dipendenze e dintorni

Da 2-3 mesi ho un'idea che mi frulla per la testa relativamente all'analisi delle dipendenze tra assembly e tra tipi. In giro non c'è molto che faccia questo tipo di lavoro, fatta eccezione per NDepend che, quando pronto (ora è RC1), sarà un gran tool ma sarà anche a pagamento, costerà intorno ai 300$ a licenza. Sarebbero soldi assolutamente ben spesi, ma potrebbero esistere scenari dove un "motore" di analisi delle dipendenze e più in generale del codice IL potrebbe essere interessante anche per scopi non direttamente correlati alle metriche e al controllo della qualità del codice. Penso per esempio ad un "auto-wiki", un aggeggio in grado di analizzare un set di assembly e che possa da essi generare un wiki per documentare o monitorare iterazioni a partire da un grafo di navigazione "preconfezionato". In generale l'idea è che questo motore possa essere usato con facilità in ambienti dove si fa uso di continuous integration e non si ha un gran budget a disposizione...  come il mio 

Nelle ultime settimane ho iniziato a scrivere questo "motorino", con l'idea di avere un'architettura pluggabile a cui aggiungere moduli di analisi in modo semplice. Ad oggi la parte di analisi dell'IL si basa su un set di sorgenti C# che ho trovato qui, ma sto valutando di passare a Cecil. La parte di analisi e di costruzione dei "grafi" delle dipendenze è a buon punto, ora vorrei scrivere qualche plugin di analisi interessante, per esempio per calcolare metriche sulle dipendenze afferenti/efferenti, generare il grafico stability/abstractness, generare l'auto-wiki descritto sopra. Spero di arrivare presto (3-4 settimane) ad una versione considerabile "beta" e metterlo da qualche parte tipo CodePlex. Se qualcuno di voi volesse darmi una mano (ammesso che io riesca a scrivere qualcosa di decente ) o avesse delle idee faccia un fischio, ok?

Bon, ormai l'ho detto, adesso mi tocca anche farlo...  in realtà ho scritto questo post quasi per non avere più scuse, e per obbligarmi a trovare il tempo per andare avanti con...  con...  come lo chiamo???

powered by IMHO 1.3

[OT] Taggato...

Essendo stato multi-taggato da Roberto e Simone, mi tocca... :)

1) Ho iniziato a programmare su un C64 nell'84, in BASIC, ma era più che altro uno scherzo, facevo strani esperimenti che non portavano a niente, e che nemmeno io capivo completamente... comprai anche un manuale sull'assembler del 6502 e provai a leggerlo, non capivo un tubo ma mi affascinava da morire :) Il vero inizio si può dire che sia stato 3 anni più tardi, al Poli, Pascal su PC, poi in C, e poi il resto...

2) Sono nato e vissuto in un paesino, per cui pur piacendomi molti sport alla fine ne ho praticato uno solo, l'unico per cui ci fosse una seppur minimale struttura, il calcio. Ho giocato regolarmente per una quindicina d'anni, penso di essere uno dei più piccoli portieri (167cm) ad aver mai giocato in seconda categoria :) La rottura di un legamento crociato ha posto fine ad una brillante carriera...

3) Tifosissimo Granata e anni fa frequentatore assiduo della curva Maratona, ora soffro a distanza :)

4) Sono felicemente sposato dal 2000, e il nostro è forse uno dei primi matrimoni "figli di Internet": mia moglie è paraguayana e l'ho conosciuta nel 97 su ICQ, nel 99 ho fatto il mio primo viaggio in Paraguay e nel 2000 l'ho portata qui :)

5) Il mio "nick" Wasp me lo affibbiò il mio prof d'inglese nell'82, e da allora mi è rimasto addosso, sono sicuro di avere più amici che mi chiamano così di quanti non ne abbia che mi chiamano col mio nome di battesimo, sarà divertente (toccando ferro) sentirsi chiamare così a 70 anni :)

 

 

...e adesso?? mmmm... Felice, Mitch, Alessio, Daniele... Beppe... :)

Chat sui Design Patterns

Questa sera ho partecipato alla chat sui Design Patterns organizzata da Emanuele. E' stata molto interessante, un esperimento da ripetere, la discussione era piuttosto fluida e le opinioni dei partecipanti molto interessanti.

Ne approfitto per rettificare una mia affermazione su Vlissides e il pattern Singleton: non era lui a proporne la rimozione dal liblro della GoF, o quantomeno non ho più trovato sue affermazioni in merito nonostante ci siano suoi scritti critici in merito, la mia convinzione veniva da un'errata associazione di idee con un vecchio post di Fowler sul suo blog (commento all'OOPSLA2004, http://www.martinfowler.com/bliki/OOPSLA2004.html), che riporto, dal quale si evince che Singleton è in generale considerato da molti come un pattern da rimuovere tra la lista di quelli "buoni":

 

Before the beginning of the conference proper I attended a workshop on reappraising the GoF book, ten years after it came out. ...

We did a number of discussions around the what next theme, perhaps the most interesting one to report was an exercise in considering some to 'vote off the island'. People voted on the patterns to indicate which ones they felt needed deletion in the current form.

Four patterns were voted off. Factory Method (due to the confusion over what it means - the pattern is different to the more common usage of the term), Bridge, Flyweight, and Interpreter. Two patterns, Singleton and Chain of Responsibility, were split decisions.

I found the votes and discussions interesting. Of course it's hard to really consider this without looking at alternatives. I was surprised that Singleton got away with a split decision, considering how unpopular it's become amongst my friends. Most of the others were voted off because people felt they were sufficiently uncommon and that other patterns would probably take their place, sadly we didn't have time to consider new members.

 

 

powered by IMHO 1.3

La specie "programmatore" e la selezione naturale, meccanismi di autodifesa

Riflessioni:

Più un programmatore è anche un bravo OO designer, più è un valore aggiunto per l'azienda in cui lavora... e più è sostituibile! Essì, perchè avrà fatto un buon lavoro, scrivendo codice pulito, manutenibile, estendibile, riusabile, che sarà facile far passare di mano. Per cui se lo si vuol cacciare lo si caccia, no?

Quando un programmatore lavora da solo su una cosa di importanza vitale, e magari ci lavora da solo, e dal punto di vista dell'OOD fa un lavoro da cani, se se ne va è una perdita enorme per l'azianda nonostante abbia lavorato male! Perchè il suo lavoro risulterà incomprensibile ed ingestibile per chi lo erediterà...  Quindi, futuro assicurato!

Paradossale...  se lavoro bene mi possono mandare via, se lavoro male no...  

Ovviamente non è così (forse..), ma il paradosso è interessante... Mi sembra di essere tornato ai tempi dei sofisti greci...

 

powered by IMHO 1.3

WCF e DIP, farneticazioni post-corso

Sono reduce da un corso su .NET 3.0 tenuto come al solito in modo impeccabile dai ragazzi di DevLeap. Le 2 ore di viaggio di ritorno verso casa sono state un momento di riflessione sui contenuti del corso, soprattutto su WCF (spiegato magistralmente da Paolo ) e sulle sue implicazioni, a mente "calda" e quindi probabilmente con un po' di confusione in testa. Lentamente, ho iniziato a farneticare...

DIP, Dependency Inversion Principle: Abstractions should not depend upon details. Details should depend upon abstractions. (cit. Robert C. Martin)

Supponiamo di seguire questo principio. Siamo in un contesto object oriented, e disegneremo per esempio un servizio di gestione ordini. Siccome vogliamo applicare il suddetto principio, definiamo interfacce opportune, per esempio:

public interface IOrder
{
    
string Id { get; }
    
string CustomerId { get; } 
    
//...
}

public interface IOrderService
{
    IOrder GetOrder(
string id);
    
//...
}

Ora potremo creare le opportune implementazioni delle due interfacce. Potremo con semplicità avere differenti implementazioni del servizio, differenti non solo dal punto di vista funzionale ma soprattutto infrastrutturale, avendo magari opportuni adapter dietro la stessa interfaccia che ci consentano di avere il servizio reale in process, piuttosto che remoto via remoting, o ancora sotto COM+...  e anche in WCF, no?

Forse no, almeno non in modo "naturale"... Il problema nasce da lontano, credo, ed è simile al più discusso problema di "impedenza" tra il mondo object-oriented e quello entity-relationship ben conosciuto da chi dibatte intorno agli ORM. WCF == SOA, e SOA != OO. Ma anche, WCF == .NET, e .NET == OO. Per proprietà transitiva otteniamo un bel WCF != WCF . Bel problema...

In WCF il codice precedente potrebbe diventare così (chiedo scusa per eventuali imprecisioni, vado a memoria... )

public class Order
{
    
public string Id;
    
public string 
CustomerId;
    
//...
}

[ServiceContract]
public interface IOrderService
{
    [OperationContract]
    Order GetOrder(
string id);
    
//...
}

Supponendo un modello di servizio WCF di tipo RPC (col modello "data contract" dal punto di vista che cerco di illustrare forse è anche peggio...), ecco che abbiamo 2 particolarità:

  1. non possiamo più avere un interfaccia (IOrder) come valore di ritorno, ma dobbiamo avere qualcosa di serializzabile (Order), quindi una classe concreta: il DIP va un po' a farsi benedire, faccio dipendere un'astrazione da una classe concreta, per di più di dominio e quindi potenzialmente instabile (= soggetta a cambiamenti), a meno che io non la crei ad hoc per quest'unico scopo, quindi come puro contenitore di campi senza logiche applicative, fattibile ma magari non bellissimo; e comunque la cosa mi costringerebbe probabilmente ad istanziare oggetti ad hoc al solo scopo di trasferire dati, quando magari io i miei dati potrei già averli in una forma adatta ad essere "nascosta" dietro un'interfaccia
  2. abbiamo gli attributi ServiceContract ed OperationContract sulla definizione dell'interfaccia del servizio: se quest'interfaccia dovesse essere la stessa dietro cui implemento anche versioni "non WCF" del servizio, essa sarebbe "sporcata" da dettagli concreti, non astratti, dipendenti dal framework applicativo in uso (WCF); di nuovo, un'astrazione che dipende da dettagli concreti, per mantenere la situazione pulita ed allo stesso tempo usare WCF dovrei avere due set paralleli di interfacce di servizio, e di nuovo adattatori in mezzo...

Come dicevo prima, in realtà tutto credo nasca dal fatto che ragionare SOA non è ragionare OO, ma che usiamo OO per implementare SOA. Un'interfaccia OO non è un contratto SOA, ma la facciamo lavorare come se lo fosse.

Nulla di nuovo, va bene tutto, in fondo basta saperlo e gestirlo, no? Ma allora il dubbio è: quando Microsoft dice che WCF unifica ASMX, WSE, COM+ e Remoting, in realtà ci sta un po' sviando... io con Remoting posso avere il servizio remoto usando il primo modello di interfacce, quello "ideale", con WCF no, quindi WCF rimpiazza Remoting ma con i costi visti sopra, che non è detto che siano sempre accettabili. Se poi l'esigenza non è interoperare, bensì remotizzare servizi (.NET su .NET) rimanendo su una metafora d'uso che renda "trasparente" la posizione reale del servizio, allora in definitiva WCF, che ha un milione di cose che vorrei poter usare, non riesco ad usarlo se non attraverso "accrocchi", come due set di interfacce ed un ulteriore livello di indirezione e quindi di serializzazione da creare per ogni singolo servizio. Una situazione con application server fatto con IIS e servizi ospitati via Remoting, è ovviamente realizzabile anche con WCF, ma a mio avviso non ha la stessa "pulizia" se il cardine del problema è la trasparenza della posizione del servizio rispetto al client.

Insomma, a questo punto, viva WCF ma...  lunga vita anche a Remoting!   Perchè Remoting vivrà ancora a lungo, vero?? ...vero????? 

powered by IMHO 1.3