RadicalDa oggi una prima parte, il che presume che come minimo che ne sarà una seconda, del mio lavoro di questi ultimi anni diventa open source: http://radical.codeplex.com/, con licenza “Microsoft Public License (Ms-PL)
Radical ha la velleità, e pure un po’ la pretesa :-), di essere un framework di supporto per lo sviluppo di applicazioni desktop, quindi Windows Forms e Wpf, e sta pian piano strizzando l’occhiolino anche a Silverlight, che sta entrando di prepotenza nella sfera delle mie passioni.
E’ da giorni che sto scrivendo questo post… che fatica :-)
Che cosa offre Radical?
Una quantità industriale di cose :-) cerchèrò di riassumerle a mo di indice qui:
Assembly: Radical; In ordine strettamente alfabetico
  • Change Tracking Service: no ho già parlato ma da quel post molto codice è passato sotto la tastiera :-) sta di fatto che c’è un’implementazione completa funzionante, e pure in produzone, di un sistema di ChangeTracking per le vostre entità, o come preferisco io per i ViewModel che wrappano le entity;
  • Enumerations: attributi, anche con supporto per la localizzazione, per poter fare questo:
enum MyEnum
{
    [EnumItemDescription( "sample caption", "some description...", 1 )]
    ValueXYZ,

    [EnumItemDescription( "caption", "description of what?", 0 )]
    MyOtherValue,
}
e ove necessario estrarre questo:
var bindingData = EnumHelper.ExtractBindingData<MyEnum>();
foreach( var bd in bindingData )
{
    MyEnum value = bd.Value;
    String caption = bd.Caption;
}
Se non ricordo male c’è anche un converter per Wpf che data una enum fa tutto il giochetto e la “binda” con un ItemsControl come ad esempio un ComboBox.
  • Extensions: una quantità industriale di “entension method” per gli usi più disparati e per tutti i gusti, alcuni probabilmente spariranno perchè sono veramente inutili :-);
  • Helpers: una discreta qantità di classi helper per semplificare la vita dello sviluppatore: dall’uso della command line alla creazione on the fly di fast delegate via lambda expression;
  • Messaging: l’implementazione di un motore di message brokering;
  • Model:
    • Entity, EntityCollection, MementoEntity, MementoEntityCollection: un set di classi base da utilizzarsi ad esempio, quelle Memento*, per avere gratis il supporto al motore di ChangeTracking scrivendo pochissimo, o addirttura niente nel caso delle collection, codice; qui ci sarebbe probabilente da parlare a lungo :-)
    • EntityView: un’implementazione completa, e in produzione da tempo immemore, di IBindingListView e non solo, perchè ad esempio offre pieno supporto per le colonne calcolate, IEntityView, e la sua implementazione di base EntityView, fa una montagna di cose senza scrivere una virgola di codice, e offre inoltre la possibilità, ereditando, di customizzare il compotamento fin nei minimi dettagli, anche qui potremmo parlarne per giorni :-). Non ho idea se e come possa funzionare con Silverlight, studio :-);
    • Un’implementazione di Wrapper che se funzionasse anche in scenari complessi sarebbe la manna… ma a quanto pare il gioco non vale la candela;
  • Observers: un set di IMonitor per semplificare la gestione di scenari di interazione complessi e potenzialmente contorti;
  • Threading/AsyncWorker: un’implementazione fluent di un wrapper per semplificare la gestione di scenari asincroni: c’è sia la versione vecchia che quella nuova, funzionalmente sono identitche ergo non ha senso usare quella vecchia;
  • Validation: un piccolo, semplice e molto limitato framework per la validazione di entity, base ad esempio di un wapper per VAB di Enterprise Library;
  • Validation/Ensure: un semplice kit per fare validazione dei parametri in maniera fluent e snella;

Assembly: Radical.Windows;

  • Un po’ di facility per wpf, facility che pian piano migreranno anche verso Silverlight ove fattibili e supportabili:
    • Markup Extensions: un po’ di markup extensions per semplificare la vita durante le operazioni di binding;
    • Input: l’ennesima implementazione di un DelegateComand/RelayCommand;
    • Effects: un GrayScaleEffect (basato su DirectX) il cui scopo è quello di convertire on the fly le immagini in scala di grigi per, ad esempio, simulare l’effetto “disabilitato”;
    • Converters: un po’ di converter per gli usi più disparati;
    • Behaviors: un bel po’ di behavior/attached property per:
      • BusyStatusManager: gestire lo stato di busy/non busy di una porzione della UI durante l’esecuzione di operazioni asincrone;
      • CueBannerService: aggiunge il supporto per i CueBanner alle TextBox (e non solo);
      • EmptyPlaceHolderService: aggiunge la possibilità di visualizzare un “testo/content di cortesia” nel momento in cui un generico ItemsControl non contiene nessun elemento;
      • ListView Behaviors:
        • gestione del doppio click su un item della list view e binding con un command;
        • gestione del “key down”, e binding con un command, per ad esempio gestire il tasto “Canc” quando avete uno o più item selezionati;
        • un GridViewColumnManager per gestire, sempre via command sul ViewModel, il sort delle colone, questo in conbutta con IEntityView spacca alla grande; offre anche facility per gestire il dimensionamento (Stretch) dei column header;
        • La possibilità di mettere in binding (bidirezionale) i SelectedItems;
      • TextBox behaviors: un behavior per disabilitare il simpatico “undo manager” che nella 3.5 è un filino bacato :-), e un behavior per poter associare un command alla pressione di un tasto, ad esempio per invocare qualcosa alla pressione di “Enter” (è il default);
      • WindowControlBox: un behavior per disabilitare via “API” i bottoncini maximize e minimize di una Window, funziona alla perfezione su Vista/7 (sia x86 che x64, almeno dai miei test) fa un po’ le bizze su XP, nel senso che non sbomba ma non sempre fa quello che deve… misteri del…
      • Drag & Drop Behavior: un behavior per poter draggare un po’ quel che si vuole verso quel che si vuole… gestendo il tutto da ViewModel, è ancora embrionale e focalizzato sui contenuti, quindi sui dati, e non sugli elementi (UIElement) per i quali Thumb rulez :-);

Assembly: Radical.Design;

Assembly: Radical.VisualStudio.UnitTesting;

  • Un set di “extension method” da usare negli unit test, lo so ci sono una pletora di “robi” la fuori ma nell’ottica “Luke, keep it simple” a me basta e avanza poter scrivere:
[TestMethod]
public void changeArgs_generic_ctor_normal_should_correctly_set_values()
{
    var entity = new Object();
    var cachedValue = new GenericParameterHelper();
    var iChange = MockRepository.GenerateStub<IChange>();

    var target = this.CreateMock<GenericParameterHelper>( entity, cachedValue, iChange );

    target.Entity.ShouldBeEqualTo( entity );
    target.CachedValue.ShouldBeEqualTo( cachedValue );
    target.Source.ShouldBeEqualTo( iChange );
}

Ho preso un test a caso in cui uso uno degli extension method: ShouldBeEqualTo( T expected ), in questo caso. Nulla di trascendentale ma semplicemente comodo :-)

Assembly: Radical.Model.NHibernate;

  • Ho paralto spesso di quanto mi piace lo specification pattern: in Radical.dll (namespace Topics.Radical.ComponentModel.QueryModel) trovate una gerarchia di “interface” che implementano lo specification pattern, in questo assembly c’è un’implementazione completa e funzionante (e pure in produzione) di quel set di contratti fatta ad hoc per NHibernate;

Assembly: Radical.Validation.VAB;

  • in Radical.dll (namespace Topics.Radical.ComponentModel.Validation) trovate una semplice astrazione del concetto di validazione di un grafo, VAB è una semplicissima, e probabilmente povera, implementazione per il Validation Application Block di Enterprise Library, funziona e soddisfa i miei requisiti, ergo… :-);

Assembly: Radical.Extensions.Castle;

Ho elencato le cose degne di nota e probabilmente ne ho tralasciate parecchie.

Note:

  • Alcune cose meriterebbero un massiccio refactoring sopratutto l’organizzazione dei namespace che negli anni è diventata un po’ troppo cervellotica per i mie gusti :-), lo farò…
  • per compilare i sorgenti è ncessario avere installato il DircetX 9.0 SDK e accertarsi di aver definito (lo dovrebbe fare il setup) la variabile d’ambiente “$(DXSDK_DIR)”, il tutto per ora serve solo per il GrayScaleEffect quind se non vi interessa compilare quello nelle pre-build-action del progetto Radical.Windows potete disabilitare la compilazione;
  • Tutte le library da cui il framework dipende “dovrebbero” essere nella cartella lib, se mai qualcuno lo usasse e avesse problemi mi faccia un fischio;
  • Ci sono un set di “post-build-action” che altro non fanno che copiare l’output della build in una folder “build” al livello della solution, sul source control c’è anche la struttura di folder che le post-build-action si aspettano di trovare, non ho idea di come si comporti codeplex con le folder vuote quindi nel caso la struttura è:
    • build
      • Desktop
        • debug
          • it-IT
        • release
          • it-IT
      • Silverlight
        • debug
          • it-IT
        • release
          • it-IT

le pos-build-action sono comunque abbastanza smart da controllare che la destinazione esista prima di eseguire l’azione in questo modo se la struttura di folder non c’è la post-build-action semplicemente non viene eseguita e la compilazione non fallisce per una stupidaggine :-)

  • Documentazione: c’è tanta documentazione xml, non tutta ma tanta, non c’è nessuna conceptual documentation, un lavoro immane che vorrei fare;
  • Samples: c’è un progetto con dei sample e vorrei, prima della documentazione concettuale, mettere in pista quello;
  • Unit Tests: ce sono parecchi, che coprono una piccola, a mio modo di vedere, parte del framework, alcune cose hanno un Code Coverage quasi del 100% altre dello 0% :-/ purtroppo…, molte cose sono ereditate dai tempi del framework 1.0 e probabilmente potrebbero essere falciate o massicciamente rifattorizzate al fine di essere facilmente testabili;
  • …ma quanto “perdindirindina” è lento CodePlex… se poi ci mettiamo “fulminino” Team Explorer diventa un delirio… :-)

.m