Programming Languages Hacks

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

  • Subscribe

  • Lettori

    I miei lettori abituali

  • Twitter

Analisi sull’Uso dei Generics

Posted by Ricibald on 19th May 2008

Mi va di trattare un argomento “banale”, su cui vi concedo 5 minuti di risposte possibili:

Quali sono gli usi dei generics?

Pensateci, pensateci e pensateci… Dopo che avete pensato a tutte le possibili risposte andate avanti a leggere…

Gli utilizzi dei generics possono essere i seguenti:

  • contenitori: i generics consentono di definire contenitori tipizzati. Possiamo quindi definire una collezione di oggetti Persona, in modo tale che non risulti possibile aggiungere oggetti che non siano di tipo Persona
  • funtori tipizzati: è possibile specificare un delegate generico, da utilizzare in funzioni di decorazione
  • decoratori: consente di aggiungere le funzionalità a un tipo. Immaginiamo di avere una classe Decorator<T>, che non fa altro che aggiungere una funzione Decorate() al tipo T, e consente di ottenere la proprietà avvolta di tipo T tramite il metodo GetValue(). Risulta molto utile questa funzionalità anche in contesti di metainformazioni: immaginiamo infatti di avere una classe Property<T> che rappresenta una proprietà: avremo metodi come GetValue(), SetValue(), IsReadOnly, IsRequired, IsEnabled, Description, … Attraverso questo utilizzo possiamo esprimere in modo fortemente tipizzato il concetto di proprietà (altrimenti saremmo stati costretti a richiedere tramite reflection le proprietà: un approccio fragile, poiché non solleva errori a tempo di compilazione in caso di proprietà inesistente)
  • proxy delle proprietà: come caso particolare dei decoratori, consente di controllare l’accesso a una certa proprietà secondo determinati vincoli di sicurezza. Consideriamo quindi una classe Proxy<T>: all’accesso di T verranno eseguiti controlli di sicurezza o inserimento in cache o altri tipi di controlli
  • vincoli di progettazione: si può pensare di introdurre delle classi a granularità architetturale, come ObjectModel<T>, DataObject<ObjectModel>, BusinessObject<DataObject>: consentono di definire il comportamento comune al bridge che lega le classi. Sappiamo infatti che il BusinessObject richiede al DataObject di creare un ObjectModel. Risulta utile creare delle classi che mettono in comune questo comportamento, in modo che sia scritto una volta per tutte. In generale, questo approccio consente di far rispettare dei vincoli di progettazione in un framework definito
  • scelta sottoclasse concreta a tempo di compilazione: design pattern come Strategy prevedono la definizione della strategia nell’ambito della classe Context, da valutare a runtime. La classe Context potrebbe essere generica: Context<IStrategy>, dove IStrategy rappresenta la strategia scelta. Questo approccio risulta molto utile per definire la classe concreta a tempo di compilazione e ottenere un guadagno prestazionale
  • specializzazione: in C# le proprietà statiche all’interno dei generics consentono di definire una primitiva forma di specializzazione. Queste verranno aggiornate solo con lo stesso tipo T utilizzato e consentono di tracciare informazioni statistiche sull’utilizzo di un certo T.

Posted in .net | No Comments »

Confronto dei Metodi in .NET per Generare Proxy verso Web Service

Posted by Ricibald on 10th January 2008

Per dialogare verso un Web Service si utilizza normalmente un proxy per generare la versione “ad oggetti” delle richieste e delle risposte che dovranno viaggiare nella rete.

Tale versione ad oggetti è un rappresentante (proxy) verso la reale richiesta SOAP. Spesso quindi si parla di “proxy verso il web service”, ma solo nel significato inglese di “rappresentante”, non come riferimento verso il design pattern Proxy. In realtà, quello che viene fatto è costruire il wrapping delle richieste, il ché coincide con il design pattern Adapter.

Esistono due strumenti in .NET che consentono di creare un proxy verso il web service:

  • in Visual Studio, selezionando “add web reference”: tale metodo crea automaticamente il proxy verso il web service dichiarato
  • con il comando wsdl.exe

Viene quindi naturale cercare di capire quale metodo utilizzare, partendo dal presupposto che il primo metodo è molto più semplice e immediato. In realtà grosse differenze non ce ne sono:

  • entrambe generano classi che non dovrebbero mai essere modificate: per questo utilizzare altri approcci, come classi partial
  • entrambe possono essere customizzate:
    • in “wsdl.exe” tramite argomenti documentati qui
    • in “add web reference” configurando proprietà di “Reference.map” o creando una classe condivisa che restituisce un’istanza del proxy opportunamente configurata

Ma alcune differenze ci sono e, come è lecito aspettarsi, “wsdl.exe” è uno strumento leggermente più potente, anche se più complesso. Infatti, le seguenti personalizzazioni di wsdl.exe non trovano corrispondenza nella procedura di Visual Studio:

  • /sharetypes: consente di condividere tipi uguali utilizzati in servizi differenti (i quali altrimenti avrebbero un loro specifico proxy)
  • /server[interface]: consente di creare un servizio web service sulla base di un file wsdl. La procedura è opposta a quella utilizzata in Visual Studio, in cui quando creo un metodo si aggiorna il wsdl. L’approccio wsdl->codice è però preferibile in modo tale da mantenere l’interfaccia stabile verso i client
  • /parsableerrors: visualizza gli errori in un formato simile a quello dei compilatori
  • /order: genera identificatori di ordine espliciti

Le seguenti funzioni, viceversa, non trovano corrispondenza in “wsdl.exe”:

  • update dinamico: l’interfaccia può essere aggiornata tramite semplice click

A parte queste particolarità, i risultati prodotti sono equivalenti e quindi, a meno di esigenze specifiche come quelle elencate, consiglierei sempre di utilizzare la procedura di Visual Studio, molto più rapida.

Come al solito, non so se la mia analisi è corretta, se ci sono critiche scrivete così l’articolo verrà corretto (e imparerò dai miei errori…)

Posted in .net, web service | 31 Comments »

Virtual proxy: una trappola senza uscita?

Posted by Ricibald on 20th July 2007

I virtual proxy forniscono un rappresentante di un oggetto in modo da gestirne il caricamento su richiesta, anche noto come lazy initialization.

Se immaginiamo un file word di 500 pagine, con più di 1000 immagini, il caricamento dovrebbe impegnare molto tempo e molte risorse. In realtà quel che succede è che ogni immagine non viene caricata, ma solo “dichiarata”. Nel nostro file “PROVA.DOC” ci saranno informazioni utili come width/height dell’immagine in modo che la “dichiarazione” dell’immagine consenta la corretta impaginazione.

Fin qui tutto bene, ma ora immaginiamo di aver fatto scorrere tutte le 500 pagine e di aver visto tutte le 1000 immagini. Cosa succede? Semplice: tutte le immagini sono state effettivamente caricate e abbiamo consumato molta, molta RAM (aaarghhh!!) .

Il problema (quì molto romanzato…) sembra però più serio del previsto. Citiamo il pattern Proxy:

Il design pattern Proxy fornisce un surrogato o un segnaposto di un altro oggetto per controllare l’accesso a tale oggetto.

Il client che utilizza il Proxy ne è inconsapevole: sa solamente che il comportamento atteso della classe deve essere rispettato. L’indirezione introdotta dal Proxy deve quindi essere trasparente e l’utente non può intervenire su di essa. Il clean quindi non può (e non deve) essere gestito manualmente.

Abbiamo quindi il seguente schema:

  • una classe R reale
  • un virtual proxy V che gestisce il caricamento su richiesta di R
  • un client, che utilizza V ma che in realtà è convinto di utilizzare R

Dopo tanto patire, senza ulteriori preliminari, questa è la soluzione che mi sembra più corretta (vi apparirà forse scontata ora che la leggete, ma vi garantisco che cercando e ricercando su Google nessuno ne parla…). Il nuovo contesto è il seguente:

  • una classe R reale
  • un cache proxy C, che memorizza fino a n classi reali R
  • un virtual proxy V, che se necessario richiede a C di ottenere la classe reale R
    • C restituisce la cache entry se esiste, o crea il corrispondente R memorizzando il risultato in cache
    • se nella memorizzazione del nuovo cache entry viene superato il limite n di cache:
      • viene liberata la cache eliminando l’elemento meno richiesto (least frequently used)
      • vengono notificati tutti gli V che ne facevano uso, che impostano a null la classe reale R utilizzata richiamando funzioni di liberazione della memoria come la garbage collection. La notifica si deve basare su un protocollo condiviso tra V e C, utilizzando ad esempio il design pattern Observer.
  • un client, che utilizza V ma che in realtà è convinto di utilizzare R

Un modo semplice di implementare la tecnica “least frequently used” è la strategia “move-to-front” descritta in Pattern Oriented Software Architecture: a ogni richiesta di una cache entry l’elemento viene spostato alla testa di una lista. Quando è necessario liberare memoria possono essere eliminati gli elementi alla coda della lista. Questo può essere implementato (ad es. in Java) estendendo i metodi get() e put() di una Map.

Questa (da quanto ne so) è una soluzione “casalinga”, che non si basa su tecniche o pattern noti. Perciò qualunque suggerimento/critica sarà più che apprezzata…

Posted in pattern | 2 Comments »