DDD http://blogs.ugidotnet.org/rgm/category/DDD.aspx DDD it-IT Gian Maria Ricci Subtext Version 2.6.0.0 Un pattern non &egrave; per sempre (o ovunque) http://blogs.ugidotnet.org/rgm/archive/2014/06/11/un-pattern-non-egrave-per-sempre-o-ovunque.aspx <p>Questa mia convinzione è valida in molte situazioni ed per molti progetti, dove spesso nel team esiste la convinzione che: <strong>le tecnologie usate in un software debbano per forza essere omogenee ed utilizzate dappertutto</strong>. Un palese esempio di questa sindrome si ha quando le obiezioni all’uso di Nhibernate o Entity Framework sono: “<em>cosa succede poi se una query non riusciamo a farla in LINQ o con HQL</em>?”, oppure “<em>non conviene perché poi sappiamo che per i report o per le operazioni massive un ORM non è adatto</em>”.</p> <p>Il problema alla base di queste obiezioni è principalmente questo: se si decide di usare un ORM, non significa che questo debba diventare l’unico modo di accedere al database. Sebbene sia chiaro che <strong>è preferibile limitare il numero di scelte tecnologiche adottate nei nostri progetti</strong>, per evitare codice immanutenibile, è possibile che si utilizzi un ORM per tutte le parti di business logic, ma per i report e per le operazioni massive si potrà utilizzare il un buon vecchio dataset e delle stored procedures. In questo caso sto limitando a due possibili scelte (ORM o Dataset) con delle chiare regole che mi fanno capire quando è meglio usare uno o usare l’altro. </p> <p>In sostanza vorrei evitare l’antipattern: <strong><em>Usiamo lo stesso pattern ovunque</em></strong></p> <p> <a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/rgm/Windows-Live-Writer/Un-pattern-non--per-sempre-o-ovunque_7F55/WP_000900_thumb3_2.jpg"><img title="WP_000900_thumb3" style="border: 0px currentcolor; display: inline; background-image: none;" border="0" alt="WP_000900_thumb3" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/rgm/Windows-Live-Writer/Un-pattern-non--per-sempre-o-ovunque_7F55/WP_000900_thumb3_thumb.jpg" width="253" height="337" /></a></p> <p>Immagine: <a href="http://ziobrando.blogspot.it/">© Alberto Brandolini</a> <img class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/rgm/Windows-Live-Writer/Un-pattern-non--per-sempre-o-ovunque_7F55/wlEmoticon-smile_2.png" /></p> <p>Questo è ancora più vero quando si parla di architetture nuove/complesse/strane/di_cui_non_si_ha_esperienza, come CQRS. La sindrome più ovvia è: non conosco bene CQRS ed Event Sourcing, però so che in alcuni punti del mio software queste tecnologie potrebbero portare grandissimi vantaggi, per cui <strong>inizio ad applicarlo nelle parti facili di progetto, cosi quando arrivo a quelle difficili, dove CQRS/ES mi da vantaggio ho già un po’ di confidenza</strong>.</p> <p>Questo spesso porta più danni che benefici, perché state utilizzando:</p> <ul> <li>una architettura di cui non siete padroni </li> <li>in una parte in cui non è necessaria</li> </ul> <p>La conclusione è: spendete un sacco di tempo e perdete produttività perché ad esempio state lavorando su una parte decisamente CRUD, con poche logiche di dominio, ma usando un Event Store e separazione tra logica e lettura. Il risultato? Più dolori che vantaggi, perché state adottando un pattern complesso per risolvere un problema semplice. </p> <p>Andando ad informarsi in rete, ad esempio con i post di Greg o Udi, emerge che probabilmente solo il 20% dei progetti beneficia realmente di CQRS; in questo caso io ho una chiave di lettura leggermente differente:<strong> CQRS va probabilmente usato solamente nel 10%/20% del proprio progetto, difficilmente potremmo applicarlo ovunque</strong>. In questo caso bisogna vincere la resistenza data dalla falsa convinzione che un pattern va adottato ovunque, ma sposare la realtà e capire che nelle proprie applicazioni, aree differenti potranno convivere con pattern differenti. In DDD è poi chiave il concetto di BOUNDED CONTEXT, per cui, dato che ogni BOUNDED CONTEXT comunica all’esterno con messaggi senza esporre logiche interne, è chiaramente possibile limitare l’uso di un pattern in un determinato BOUNDED CONTEXT. </p> <p>In questo scenario è fondamentale l’individuazione dei BOUNDED CONTEXT, perché se si sbaglia a tracciare la linea tra contesti il conto potrebbe essere salato, però questo indipendentemente dai pattern utilizzati.</p> <p>Gian Maria.</p><img src="http://blogs.ugidotnet.org/rgm/aggbug/101852.aspx" width="1" height="1" /> Gian Maria Ricci http://blogs.ugidotnet.org/rgm/archive/2014/06/11/un-pattern-non-egrave-per-sempre-o-ovunque.aspx Wed, 11 Jun 2014 10:03:18 GMT http://blogs.ugidotnet.org/rgm/archive/2014/06/11/un-pattern-non-egrave-per-sempre-o-ovunque.aspx#feedback 1 http://blogs.ugidotnet.org/rgm/comments/commentRss/101852.aspx http://blogs.ugidotnet.org/rgm/services/trackbacks/101852.aspx Che tipo di Id uso per l&rsquo;Aggregate Root http://blogs.ugidotnet.org/rgm/archive/2012/08/16/che-tipo-di-id-uso-per-lrsquoaggregate-root.aspx <p>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.</p> <p>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 <em>“motore di blog</em>” e come al solito, cambiando dominio, emergono alcune considerazioni che in altri casi non emergono.</p> <p>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 <em>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</em>. 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().</p> <p><strong>Ma anche no!!!</strong></p> <p>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. <em>CatManager_</em>NomeBlog). In questo modo quando arriva un comando per aggiungere la categoria XXX al blog YYY io <em>posso caricare l’AR CatManager_YYY</em> <em>e chiamare subito AddCategory().</em> 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.</p> <p>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.</p> <p>Happy DDD. </p> <p>Gian Maria.</p><img src="http://blogs.ugidotnet.org/rgm/aggbug/101157.aspx" width="1" height="1" /> Gian Maria Ricci http://blogs.ugidotnet.org/rgm/archive/2012/08/16/che-tipo-di-id-uso-per-lrsquoaggregate-root.aspx Thu, 16 Aug 2012 11:37:40 GMT http://blogs.ugidotnet.org/rgm/archive/2012/08/16/che-tipo-di-id-uso-per-lrsquoaggregate-root.aspx#feedback 4 http://blogs.ugidotnet.org/rgm/comments/commentRss/101157.aspx http://blogs.ugidotnet.org/rgm/services/trackbacks/101157.aspx Il vantaggio di ragionare ad Eventi http://blogs.ugidotnet.org/rgm/archive/2012/08/04/il-vantaggio-di-ragionare-ad-eventi.aspx <p>Sebbene sia possibile <a href="http://blogs.ugidotnet.org/rgm/archive/2012/07/26/sono-io-cqrs.aspx">adottare approcci CQRS su architetture classiche</a> è 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”.</p> <p>In questo <a href="https://github.com/andreabalducci/Prxm.Cqrs">piccolo esempio fatto su GitHub</a> su cui stiamo giocando io, <a href="http://www.primordialcode.com/">Alessandro</a> ed <a href="https://twitter.com/andreabalducci">Andrea</a> un esempio molto semplice e primitivo di gestione di querymodel viene fatto su una struttura basata su EventSourcing, dove lo storage è gestito dalla libreria <a href="https://github.com/joliver/EventStore/">EventStore</a> 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)</p> <p>Supponiamo questo scenario, lancio la mia applicazione client, e creo un paio di InventoryItem inviando un paio di comandi CreateInventoryItem command: </p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/rgm/Windows-Live-Writer/Il-vantaggio-di-ragionare-ad-Eventi_9282/image_2.png"><img style="border: 0px currentcolor; display: inline; background-image: none;" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/rgm/Windows-Live-Writer/Il-vantaggio-di-ragionare-ad-Eventi_9282/image_thumb.png" width="1014" height="301" /></a></p> <p>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.</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/rgm/Windows-Live-Writer/Il-vantaggio-di-ragionare-ad-Eventi_9282/image_4.png"><img style="border: 0px currentcolor; display: inline; background-image: none;" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/rgm/Windows-Live-Writer/Il-vantaggio-di-ragionare-ad-Eventi_9282/image_thumb_1.png" width="573" height="450" /></a></p> <p>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.</p> <p> 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.</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/rgm/Windows-Live-Writer/Il-vantaggio-di-ragionare-ad-Eventi_9282/image_6.png"><img style="border: 0px currentcolor; display: inline; background-image: none;" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/rgm/Windows-Live-Writer/Il-vantaggio-di-ragionare-ad-Eventi_9282/image_thumb_2.png" width="1048" height="346" /></a></p> <p>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. </p> <p>Il risultato è che abbiamo l’autogenerazione del nostro QueryModel.</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/rgm/Windows-Live-Writer/Il-vantaggio-di-ragionare-ad-Eventi_9282/image_10.png"><img style="border: 0px currentcolor; display: inline; background-image: none;" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/rgm/Windows-Live-Writer/Il-vantaggio-di-ragionare-ad-Eventi_9282/image_thumb_4.png" width="929" height="395" /></a></p> <p>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.</p> <p>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 ;)</p> <p>Gian Maria.</p><img src="http://blogs.ugidotnet.org/rgm/aggbug/101149.aspx" width="1" height="1" /> Gian Maria Ricci http://blogs.ugidotnet.org/rgm/archive/2012/08/04/il-vantaggio-di-ragionare-ad-eventi.aspx Sat, 04 Aug 2012 11:58:34 GMT http://blogs.ugidotnet.org/rgm/archive/2012/08/04/il-vantaggio-di-ragionare-ad-eventi.aspx#feedback http://blogs.ugidotnet.org/rgm/comments/commentRss/101149.aspx http://blogs.ugidotnet.org/rgm/services/trackbacks/101149.aspx CSDD&ndash;programming pornography http://blogs.ugidotnet.org/rgm/archive/2011/10/31/csddndashprogramming-pornography.aspx <p>In realtà la frase “programming pornography” la ho sentita da <a href="http://codebetter.com/gregyoung/">Greg Young</a> durante il DDD Day, ma si allinea ad uno degli altri importanti concetti che sono emersi durante il campus DDD. In questo caso Alberto ha sottolineato il fatto di come nelle discussioni nei gruppi DDD troppo spesso si parla di tecnicismi e nella maggioranza dei casi si parla quasi sempre di ORM.</p> <p>Il concetto in questo caso è che il vantaggio maggiore del DDD è il metodo di approcciare il problema, ovvero cercare di <em>sviscerare</em> le logiche ed individuare le <strong><em>Entità</em></strong> che possono meglio modellare le logiche del dominio reale. Naturalmente, dato che l’approccio è principalmente teso alla “scoperta”, il primo modello difficilmente sarà quello giusto, per cui è necessario per lo meno nelle fasi iniziali farne più di uno e scegliere quello che “ci soddisfa maggiormente”, capendo poi che molto probabilmente verrà comunque cambiato. Il vero valore quindi è nella stesura del modello e non nella sua implementazione, per cui bisognerebbe cercare di dedicare più tempo alla modellazione, cercando di non farci “traviare” dagli aspetti tecnici.</p> <p>Purtroppo questo accade perché la community DDD è giovane, non esiste ancora da nessuna parte una “reference implementation” e difficilmente ne esisterà mai una, per questo bisogna accettare che in realtà il vero valore è nel modello e la realizzazione tramite codice è “programming pornography”, che probabilmente verrà rifatta per ogni progetto. Debbo dire che io sono il primo che lamento la mancanza in rete di “codice di esempio”, che possa aiutare a parlare concretamente di DDD con del codice sottomano, ma negli ultimi tempi sto realizzando che la parte implementativa è sicuramente importantissima, ma troppo spesso diventa dominante, quando invece la parte dominante dovrebbe essere il modello e la parte implementativa un corollario.</p> <p>Questo coincide con un raffreddamento del mio entusiasmo sugli ORM, che inizio a considerare talvolta degli “antipattern” che troppo spesso spostano la nostra attenzione lontano dalla <em>ciccia. </em>Nondimeno avere in rete delle implementazioni concrete e funzionanti di Event Sourcing, Domain Events e quant’altro, sicuramente gioverebbe a tutto il movimento, perché permetterebbe di poter dire “ok mi concentro nel modello, dato che comunque un paio di implementazioni con cui iniziare ad implementare il modello ci sono”.</p> <p>Gian Maria.</p><img src="http://blogs.ugidotnet.org/rgm/aggbug/100484.aspx" width="1" height="1" /> Gian Maria Ricci http://blogs.ugidotnet.org/rgm/archive/2011/10/31/csddndashprogramming-pornography.aspx Mon, 31 Oct 2011 13:33:51 GMT http://blogs.ugidotnet.org/rgm/archive/2011/10/31/csddndashprogramming-pornography.aspx#feedback 4 http://blogs.ugidotnet.org/rgm/comments/commentRss/100484.aspx http://blogs.ugidotnet.org/rgm/services/trackbacks/100484.aspx CSDD&ndash;Aggregate root http://blogs.ugidotnet.org/rgm/archive/2011/10/18/csddndashaggregate-root.aspx <p>Dopo la prima lettura del libro di Evans (e vi assicuro che vale la pena di leggerlo almeno due volte), uno dei principi che maggiormente ho apprezzato è senza dubbio quello dell’<em><strong>AGGREGATE ROOT </strong>e degli <strong>AGGREGATES</strong></em> in generale.</p> <blockquote> <p>An aggregate is a cluster of associated objects that we treat as a unit for the purpose of data changes.</p> </blockquote>    <p>L’importanza di questo pattern è la stessa del <strong><em>BOUNDED CONTEXT</em></strong> perchè porta alla riduzione della complessità, limitando la possibilità di instaurare relazioni tra gli oggetti. Il livello di granularità di frazionamento di questo pattern è minore del <strong><em>BOUNDED CONTEXT </em></strong>e può costituire essenzialmente un ulteriore livello di suddivisione. Partiamo quindi dal problema che vogliamo evitare, che è essenzialmente lo stesso mostrato nel <a href="http://blogs.ugidotnet.org/rgm/archive/2011/09/20/isolare-il-problema-con-i-bounded-context-csddd-campus.aspx">post precedente</a>.</p> <p><img src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/rgm/Windows-Live-Writer/Divide-et-impera_7D50/image_thumb_2.png" /></p> <p>In domini complessi infatti, un singolo <strong><em>BOUNDED CONTEXT</em></strong> può essere molto complesso ed è deleterio permettere ad ogni oggetto di poter dialogare direttamente con qualsiasi altro oggetto nello stesso contesto, perchè si rischia di ricadere in un contesto cosi interconnesso che è poco gestibile. In pratica un <strong><em>AGGREGATE </em></strong>non è altro che un insieme di oggetti che rappresenta un’entità ben definita del dominio e l’<strong>AGGREGATE ROOT</strong> è l’oggetto che incapsula tutto il gruppo e ne costituisce la barriera di accesso. Non esiste una regola generale per individuare un <strong><em>AGGREGATE</em></strong>, ma in generale, se in un contesto abbiamo oggetti che da soli non hanno molto significato, ma acquistano significato presi assieme, questo potrebbe molto facilmente essere un aggregato.</p> <p>Se facciamo un esempio nel dominio di un ipotetico gioco di ruolo, potremmo dire che un <em>Guerriero</em> è composto da un insieme di oggetti come ad esempio le <em>caratteristiche (</em>forza, intelligenza, presenza, etc), dalle abilità (uso delle armi, salto, corsa, etc) e tutto questo insieme di oggetti costituisce la rappresentazione in questo <strong><em>BOUNDED CONTEXT</em></strong> dell’entità <em>Guerriero. </em>In questo caso infatti una caratteristica ad esempio non ha alcun senso se non associata al concetto di Guerriero e quindi ne costituisce una parte.</p> <p>Il primo vantaggio del’<strong><em>AGGREGATE</em></strong> è quello di presentare all’esterno un unico punto di contatto, chiamato <strong><em>AGGREGATE ROOT</em></strong>, in particolare esiste un principio che permette ad <em>un repository di gestire solamente gli aggregate root. </em>L’<strong><em>AGGREGATE ROOT</em></strong> diviene quindi un ulteriore astrazione che favorisce il concetto di <strong><em>incapsulamento.</em></strong> Cosi come una classe protegge il suo stato interno grazie ai metodi e fornisce una <strong>interfaccia </strong>o <strong>contratto</strong> che implementa la comunicazione con l’esterno, un’<strong><em>AGGREGATE ROOT</em></strong> incapsula una serie di oggetti che rappresentano l’aggregato..</p> <p>Grazie a questa astrazione è quindi possibile ridurre il numero di interconnessioni tra oggetti, perché queste ultime sono limitate agli <strong><em>AGGREGATE ROOT</em>.</strong></p> <p>L’aspetto del salvataggio è particolarmente importante, abbiamo infatti due assunti precisi</p> <p>1) Solo gli aggregate root possono essere gestiti tramite repository <br />2) Ogni aggregato ha il suo repository per la gestione della persistenza.</p> <p>Questo significa che se un particolare aggregato è cosi complesso che ci viene facile salvarlo su un NoSQL, possiamo farlo senza problemi, altri aggregati potrebbero per esempio salvarsi semplicemente serializzando su disco, oppure chiamando un servizio esterno che li persiste <em>on the cloud.</em> Questa affermazione solitamente scatena ogni sorta di obiezioni, primo tra tutti il dire “come faccio I report?”, quando in una interfaccia debbo mostrare dei dati che vengono da aggregati differenti che prestazioni avrò se debbo prendere I dati da sorgenti eterogenee e poi magari aggregare in memoria? Purtroppo come in molte aree del DDD non esiste un’unica risposta, e dobbiamo capire se il vantaggio che abbiamo magari usando un NoSQL non ci fa perdere da altre parti.</p> <p>Una soluzione possibile è CQRS + DOMAIN EVENTS, ogni cambiamento significativo di un <strong><em>AGGREGATE ROOT</em></strong> genererà infatti un evento di dominio, che dovrà essere gestito da un Handler apposito che terrà aggiornate le classiche viste readonly su cui fare le query. Alcuni db NoSQL come raven hanno dei plugin che permettono automaticamente di tenere sincronizzato un database SQL con alcune proprietà degli oggetti salvati. L’obiettivo è quello di cercare di racchiudere la complessità del problema nel dominio e non nell’infrastruttura che ci sta attorno (leggasi ORM). La morale è, se debbo fare carte false per persistere una gerarchia complessa con un ORM, solo perché “tutto il resto è persistito con un ORM”, probabilmente non abbiamo necessariamente preso la strada giusta e vale la pena di pensare se un <strong><em>AGGREGATE</em></strong> o un intero <strong><em>BOUNDED CONTEXT </em></strong>non possano usare strategie differenti di persistenza.</p> <p>alk.</p><img src="http://blogs.ugidotnet.org/rgm/aggbug/100459.aspx" width="1" height="1" /> Gian Maria Ricci http://blogs.ugidotnet.org/rgm/archive/2011/10/18/csddndashaggregate-root.aspx Tue, 18 Oct 2011 21:01:09 GMT http://blogs.ugidotnet.org/rgm/archive/2011/10/18/csddndashaggregate-root.aspx#feedback 3 http://blogs.ugidotnet.org/rgm/comments/commentRss/100459.aspx http://blogs.ugidotnet.org/rgm/services/trackbacks/100459.aspx Considerazioni sul campus #CSDDD http://blogs.ugidotnet.org/rgm/archive/2011/09/06/considerazioni-sul-campus-csddd.aspx <p>Questo fine settimana, il sottoscritto ed altre strane persone :), si sono chiuse in un agriturismo marchigiano e sotto la guida di <a href="http://albertobrandolini.wikidot.com/">ZioBrando</a> hanno passato tutto il fine settimana a parlare di DDD. (trovate alcune foto nel mio profilo facebook).</p> <p>L’esperienza è stata decisamente positiva, diciamo che mi sono convinto ancora di più che il DDD sia applicabile in molti più scenari di quello che pensavo. L’unica pecca è stata l’avere scritto poco codice e sostanzialmente ce ne siamo andati con ancora alcuni dubbi a livello “implementativo”, del tipo, come faccio cosa? Un handler di un domain event ha senso che sia in un aggregate?, e cosi via, ma comunque moltissime idee si sono chiarite.</p> <p>I concetti base sono che: è fondamentale avere tanta carta su cui tracciare le proprie idee e avere voglia di esplorare per capire il dominio. Nei prossimi giorni, tempo permettendo :), cercherò di enunciare quelli che per me sono i concetti più importanti che abbiamo appreso nel campus, che potete comunque vedere anche in questa foto, che rappresenta il nostro learning tree del campus.</p> <p><a href="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/rgm/Windows-Live-Writer/Considerazioni-sul-campus-CSDDD_A643/image_2.png"><img style="border: 0px currentcolor; display: inline; background-image: none;" title="image" border="0" alt="image" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/rgm/Windows-Live-Writer/Considerazioni-sul-campus-CSDDD_A643/image_thumb.png" width="600" height="450" /></a></p> <p>Stay tuned</p> <p>Gian Maria.</p><img src="http://blogs.ugidotnet.org/rgm/aggbug/100325.aspx" width="1" height="1" /> Gian Maria Ricci http://blogs.ugidotnet.org/rgm/archive/2011/09/06/considerazioni-sul-campus-csddd.aspx Tue, 06 Sep 2011 10:32:32 GMT http://blogs.ugidotnet.org/rgm/archive/2011/09/06/considerazioni-sul-campus-csddd.aspx#feedback http://blogs.ugidotnet.org/rgm/comments/commentRss/100325.aspx http://blogs.ugidotnet.org/rgm/services/trackbacks/100325.aspx Repository, altre considerazioni http://blogs.ugidotnet.org/rgm/archive/2007/09/28/88586.aspx <p>In un <a href="http://www.guisa.it/forums/1340/ShowThread.aspx">thread</a> su guisa si è un po parlato di costruttori e persistenza. Sempre continuando il discorso del <a href="http://blogs.ugidotnet.org/rgm/articles/88129.aspx">repository</a>, volevo dare la mia opinione su come i costruttori si legano al repository. Come anche <a href="http://martinfowler.com/eaaCatalog/repository.html">Fowler</a> dice, la costruzione di un oggetto non è pertinenza del repository, ma il repository ha il seguente scopo </p><p><em>Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects. </em></p><p>Per questa ragione il ciclo di vita di un oggetto è il seguente: chiamando uno dei costruttori o un metodo factory si crea una nuova istanza, questa nuova istanza è transiente per utilizzare la notazione di Nhibernate. A questo punto il <em>repository</em> entra in gioco perché presenta all'utente una interfaccia <em>collection-like, </em>ovvero si comporta come un contenitore in memoria, internamente il repository dialoga con il layer di persistenza e quindi lo stato dell'oggetto diventa persistente, ma per il chiamante tutto questo è completamente trasparente. Una delle convenienze dei repository è che si possono creare repository solamente per le root degli aggreati in modo da impedire all'utilizzatore di andare a ricostruire direttamente oggetti interni di un aggretago. Una discussione approfondita è comunque fatta nel libro di <a href="http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215/ref=pd_bbs_sr_1/102-4528641-0531317?ie=UTF8&amp;s=books&amp;qid=1190984167&amp;sr=8-1">Evans</a>. Personalmente però non amo l'utilizzo di costruttori o metodi factory per effettuare la <em>reconstitution</em> di un oggetto, ma preferisco accentrare il tutto nel repository. </p><p>Alk.</p><img src="http://blogs.ugidotnet.org/rgm/aggbug/88586.aspx" width="1" height="1" /> Gian Maria Ricci http://blogs.ugidotnet.org/rgm/archive/2007/09/28/88586.aspx Fri, 28 Sep 2007 16:00:07 GMT http://blogs.ugidotnet.org/rgm/archive/2007/09/28/88586.aspx#feedback http://blogs.ugidotnet.org/rgm/comments/commentRss/88586.aspx http://blogs.ugidotnet.org/rgm/services/trackbacks/88586.aspx Repository e LINQ http://blogs.ugidotnet.org/rgm/archive/2007/08/10/87724.aspx Premesso che sono alle prime armi con LINQ, in questo post faccio vedere una prima ipotesi di come il nostro repository possa dare funzionalità di query per LINQ grazie al progetto LINQ to NHIbernate. Alk.<img src="http://blogs.ugidotnet.org/rgm/aggbug/87724.aspx" width="1" height="1" /> Gian Maria Ricci http://blogs.ugidotnet.org/rgm/archive/2007/08/10/87724.aspx Fri, 10 Aug 2007 18:10:00 GMT http://blogs.ugidotnet.org/rgm/archive/2007/08/10/87724.aspx#feedback http://blogs.ugidotnet.org/rgm/comments/commentRss/87724.aspx http://blogs.ugidotnet.org/rgm/services/trackbacks/87724.aspx Repository – Fluent Query Interface http://blogs.ugidotnet.org/rgm/archive/2007/08/07/87510.aspx Quarta parte degli articoli sul repository.<img src="http://blogs.ugidotnet.org/rgm/aggbug/87510.aspx" width="1" height="1" /> Gian Maria Ricci http://blogs.ugidotnet.org/rgm/archive/2007/08/07/87510.aspx Tue, 07 Aug 2007 15:52:00 GMT http://blogs.ugidotnet.org/rgm/archive/2007/08/07/87510.aspx#feedback 1 http://blogs.ugidotnet.org/rgm/comments/commentRss/87510.aspx http://blogs.ugidotnet.org/rgm/services/trackbacks/87510.aspx Repository non generico http://blogs.ugidotnet.org/rgm/archive/2007/08/06/87453.aspx Terza parte della serie di post su come realizzare un repository pattern.<img src="http://blogs.ugidotnet.org/rgm/aggbug/87453.aspx" width="1" height="1" /> Gian Maria Ricci http://blogs.ugidotnet.org/rgm/archive/2007/08/06/87453.aspx Mon, 06 Aug 2007 18:47:00 GMT http://blogs.ugidotnet.org/rgm/archive/2007/08/06/87453.aspx#feedback 3 http://blogs.ugidotnet.org/rgm/comments/commentRss/87453.aspx http://blogs.ugidotnet.org/rgm/services/trackbacks/87453.aspx