Il dado è tratto… :-)
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;
-
Entity, EntityCollection
-
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;
- Argomento complesso per essere trattato qui, ma ne ho scritto parecchio :-), un po’ di storia a riguardo:
- L’implementazione attuale è quella dell’ultimo post, non ho idea se la stessa cosa si possa fare con Silverlight, devo provare;
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;
- per ora una ed una sola facility per Castle Windsor per automatizzare le “subscription” del message broker in fase di setup del container… quante parlacce :-D… insomma questo: http://milestone.topics.it/blog/post/ui-composition-imessagebroker-castle-windsor-e-le-facility
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
-
debug
-
Silverlight
-
debug
- it-IT
-
release
- it-IT
-
debug
-
Desktop
-
build
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