in

DotNetMarche

.NET Framework User Group delle Marche

This Blog

Syndication

ExternalBlogs

August 2012 - Posts

  • Disponibile per il download l'SDK per lo sviluppo di App SharePoint 2013 ed Office 2013

    Da pochi giorni è disponibile per il download pubblico l'SDK per lo sviluppo di App su SharePoint 2013 ed Office 2013. Per la precisione, lo potete scaricare direttamente da questo indirizzo: - http://www.microsoft.com/en-us/download/details.aspx...
  • Il nuovo App-Model di SharePoint 2013 - Parte 3

    Dopo i primi due post introduttivi sul nuovo modello "App-oriented" introdotto in SharePoint 2013 ( parte 1 e parte 2 ), volevo condividere con voi un po' di considerazioni. E' da un bel po' di tempo ormai che ho a che fare con questo...
  • Telecom campioni di CQRS ed asincronicità

    Ho il conto online, e sono oramai vari mesi che, quando viene emessa la fattura, mi sveglio e vedo la mail che mi indica che il conto è disponibile online, posso vederlo etc etc ma quando vado sul p@goonline mi dice che non ci sono conti da saldare. Solitamente si impiega almeno una giornata prima che la fattura che è già disponibile nell’area clienti sia pagabile online con il sistema di pago online, anche in questo caso il sistema è asincrono e per l’utente non è un grande problema.

    Oramai ci sono cosi abituato che quando arriva la mail non provo nemmeno a pagare e mi metto un promemoria direttamente il gg dopo. Smile

    Gian Maria.

  • Che tipo di Id uso per l’Aggregate Root

    In CQRS ma in generale in DDD è buona norma identificare il concetto di AggregateRoot con una classe specifica, e se fate EVENT SOURCING è una funzionalità praticamente obbligatoria, perchè l’AR si occupa anche di gestire il dispatch dei DOMAIN EVENTS sia agli eventy Applyer, sia anche al mondo esterno.

    In questo caso molto spesso si tende a dotare la classe base astratta AggregateRoot di un Id che solitamente è di tipo GUID, oppure di tipizzarla con un generics su T in modo che T identifichi il tipo di dato usato per l’id. In questi gg sto “giocando” un po su questi concetti su un dominio “motore di blog” e come al solito, cambiando dominio, emergono alcune considerazioni che in altri casi non emergono.

    In questo caso io ho il seguente scenario: ogni blog ha un nome ed ogni blog ragionevolmente avrà un AR che ne gestisce le categorie e questo AR sarà univoco per ogni blog. In questo caso se la mia AR ha un id di tipo GUID si potrebbe risolvere il tutto con un semplice listener che è in ascolto sull’evento BLOG CREATED, e crea un QueryModel che associa al nome del blog l’Id dell’AR che ne gestisce le categorie. Questo viene fatto perchè dalle MetaWeblogAPI tutte le chiamate non hanno guid, ma hanno il nome del blog, per cui se debbo aggiungere una categoria ad un blog parto dal nome del blog, leggo il queryModel che mi dice l’id dell’AR del category manager, carico l’AR dal suo id Guid e chiamo AddCategory().

    Ma anche no!!!

    La soluzione più semplice è quella di ammettere che l’AR del Category Manager abbia un Id stringa, e che, dato il nome del blog, l’id venga generato per convenzione (Es. CatManager_NomeBlog). In questo modo quando arriva un comando per aggiungere la categoria XXX al blog YYY io posso caricare l’AR CatManager_YYY e chiamare subito AddCategory(). A questo punto posso estendere il tutto dicendo che la classe AggregateRoot base ha un id di tipo stringa, in questo modo se voglio posso sempre usare un Id Guid convertendolo a stringa, ma posso risolvere situazioni più specifiche, come gli unique constraint in maniera decisamente semplice.

    Anche in questo caso l’esperienza che se ne trae è: per ogni Dominio, le regole sono differenti e l’implementazione, che costituisce l’implementazione di tali regole, è differente. Motivo per il quale è praticamente impossibile se non improbabile pensare di creare librerie o architetture base per DDD, che sicuramente non potranno soddisfare esigenze specifiche del proprio dominio.

    Happy DDD.

    Gian Maria.

  • Il vantaggio di ragionare ad Eventi

    Sebbene sia possibile adottare approcci CQRS su architetture classiche è indubbio che il paradigma CQRS va a braccetto con il concetto di DOMAIN EVENT, questo perché è possibile costruire i QueryModel direttamente elaborando lo stream di eventi del dominio, azzerando di fatto ogni dipendenza dello storage e soprattutto applicando logiche di generazione del QueryModel (Denormalizzatori) su eventi del “passato”.

    In questo piccolo esempio fatto su GitHub su cui stiamo giocando io, Alessandro ed Andrea un esempio molto semplice e primitivo di gestione di querymodel viene fatto su una struttura basata su EventSourcing, dove lo storage è gestito dalla libreria EventStore di joliver. In questa struttura gli eventi di cambio stato vengono persistiti su MONGO, ma se si vuole gestire il QueryModel su database SQL non vi è problema alcuno, visto che l’unico punto di contatto sono gli eventi, nessuno obbliga ad usare le stesse tecnologie per risolvere problemi radicalmente differenti (persistenza eventi e interrogazione)

    Supponiamo questo scenario, lancio la mia applicazione client, e creo un paio di InventoryItem inviando un paio di comandi CreateInventoryItem command:

    image

    questo scatena la creazione di due aggregate root nel BOUNDED CONTEXT del magazzino, ed essendo tutto gestito con EVENT SOURCING in realtà io ho solamente dei commit fatti sul database di storage degli eventi, nel mio caso Mongo.

    image

    In questo caso come potete vedere ho un evento InventoryItemCreated, ma la domanda ora sorge spontanea, come faccio a mostrare all’utente la lista degli InventoryItem a magazzzino con la relativa quantità? Questo richiede un QueryModel ad hoc che contenga i campi che vogliamo far vedere all’utente e per comodità li vorrei in un database SQL acceduto con NHibernate, perchè mi rende molto facile la gestione e mi permette di scrivere poco codice. Inoltre NH ha un provider LINQ decente, per cui mi viene semplice scrivere codice per le query.

    La soluzione è semplicemente scrivere un componente che si registra agli eventi di interesse per costruire il QueryModel (nel nostro caso l’InventoryItemCreated e l’InventoryItemStocked) per creare questa view. Una volta costruito l’assembly, basta metterlo nella stessa cartella del server, aggiungere il file di configurazione di NHibernate e far ripartire il server.

    image

    Quello che accade è che l’infrastruttura rileva un nuovo handler, e durante la configurazione viene richiesto il replay degli eventi, perchè l’inizializzatore dell’handler verifica che il database è in uno stato “obsoleto”, dato che è vuoto, non contenendo nemmeno una tabella. L’infrastruttura base pertanto non fa altro che verificare che l’handler gestisce due eventi, per cui preleva dall’event store tutti gli eventi di quel tipo ed effettua il replay.

    Il risultato è che abbiamo l’autogenerazione del nostro QueryModel.

    image

    La comodità di questo approccio è che se per qualche ragione il QueryModel deve cambiare di formato, è sufficiente andare ad aggiornare il denormalizzatore, cambiare il numero di versione e questo scatenerà al successivo riavvio un replay degli eventi :) ed il gioco è fatto. Inoltre come potete vedere ci sono molti InventoryItem di test, non solamente i due che ho creato prima di aggiungere il denormalizzatore. Gli altri InventoryItem erano stati creati nel passato e come potete vedere sono presenti nel QueryModel.

    Se siete interessati ai dettagli il codice è online, nei prossimi giorni se il tempo ed il caldo mi permetteranno XD, descriverò in breve dettaglio alcune soluzioni adottate, ricordando che questo progetto è comunque un playground su cui stiamo “sperimentando”, ma i cui concetti andranno in produzione prossimamente ;)

    Gian Maria.

  • Il nuovo App-Model di SharePoint 2013 - Parte 2

    Bene, fatta questa breve premessa , vediamo come si presenta questo nuovo modello e quali sono le tipologie di App che possiamo sviluppare all'interno di SharePoint 2013: SharePoint-hosted Apps : applicazioni che vengono installate fisicamente su...
Powered by Community Server (Commercial Edition), by Telligent Systems