DDD: i behavior prima di tutto

Molto spesso, come già detto, ci sembra di applicare DDD, ci autoconvinciamo della cosa (anche perché ultimamente se non fai DDD, non sei nessuno :-) ), ma siamo ben lontani dall’applicarlo.

Il primo, vero, campanello d’allarme, se di allarme vogliamo parlare, lo possiamo percepire da come è fatto il nostro dominio: se non abbiamo un domain model, non stiamo sicuramente facendo DDD. Avere un domain model, non significa che stiamo facendo DDD.
Riporto la definizione originale, a scanso di equivoci, di cosa un domain model dovrebbe essere:

An object model of the domain that incorporates both behavior and data. [Martin Fowler]

Ragazzi non ci si scappa: quel *both* è la parte più importante della definizione. E dato che sul *data* non ci piove (e non manca mai), è la parte *behavior* che fa la differenza, che è l’ago della bilancia che ci permette di asserire con un po’ più di certezza di aver intrapreso la strada giusta (ovviamente se la strada che vogliamo intraprendere è quella del DDD)

Dire: “ho un domain model anemico” è una frase senza senso. Un domain model senza comportamento, non è un domain model. Punto.
Un object model, come quello dell’immagine seguente, dove la parte *data* la fa da padrone, nel senso che di behavior non se ne vedono, non è DDD-style e non ci permette di gestire la complessità del business che dobbiamo modellare. Se la complessità non c’è, siamo a posto, ma se c’è logica, più o meno complessa, potrebbe essere l’inizio della fine.


Se poi pensiamo di delegare la consistenza di parti del nostro modello a layer differenti (per esempio il service layer) rispetto a quello del domain model, stiamo rischiando (è molto più di un rischio) di “rompere” uno dei principi caratterizzanti che guidano lo sviluppo in DDD: la definizione degli aggregati.

Se vogliamo applicare DDD, tutto parte da lì, dalla corretta definizione degli aggregati e dall’esposizione di behavior dall’aggregato.
Dato che questo è uno dei principi basilari, ma anche uno di quelli più difficili da “implementare”, quello che solitamente mi trovo a far fare a chi mi presenta un object model completamente anemico è: “togliamo tutte le proprietà pubbliche ed esponiamo funzionalità“…poi chiamo un medico, perché solitamente metà del team è svenuto :-)

Questa “prova di coraggio” tipicamente si scontra con il modus-operandi di gran parte dei team con cui mi trovo ad interagire. Indipendentemente dalla propensione al massiccio refactoring, gli scogli da superare sono comunque parecchi e toccano vari aspetti della nostra applicazione: la parte di persistenza, gli unit test, i tool da utilizzare…

Insomma c’è tanta carne al fuoco, nelle prossime puntate vedremo di dettagliare un po’ meglio e di entrare un po’ più nello specifico…se poi non vi ho annoiato troppo, rinnovo l’invito per il primo meeting organizzato da guisa: lì ne vedremo veramente delle belle.

Accorrete numerosi ;-)

DDD: sogno o realtà?

“DDD”…un acronimo, mille dubbi.

Se da una parte noto un sempre crescente interesse rispetto a questa “metodologia”, dall’altra mi accorgo che iniziano ad insinuarsi vari/parecchi dubbi sulla sua effettiva validità/efficacia tra le persone con cui mi confronto ultimamente.

Se ne parla tanto, da tempo, ma di esempi veri e propri ce ne sono sempre pochi, rischiando di confinarne i principi e le linee guida ai confini della leggenda: ma si può veramente fare? è sostenibile? ma come si fa?

Ultimamente, inizio addirittura a percepire i primi spifferi relativi ad una scarsa valenza del DDD nella fase implementativa di un progetto: “tante belle idee, ma stringi, stringi…”

Il problema non è il DDD, ma l’uso che se ne fa. Se poi ci mettiamo che i pochi (troppo) semplici esempi che abbiamo sotto gli occhi cercando in rete, molto spesso (IMHO) sono molto lontani dalla direzione in cui DDD/CQRS/ES ci spingono…chiudiamo il cerchio.
Molti (mi metto anch’io nel coro) credono di fare DDD, ma tante volte sono ben lontani da una sua, anche minima, parvenza. Presi dall’entusiasmo, cerchiamo di infilare aggregate, repository, bounded context (and so on) in qualsiasi progetto, quando, in fin dei conti, non ne avremmo bisogno, dimenticandoci “bellamente” del sottotitolo del libro da cui tutto ha preso origine: “Tackling complexity in the heart of software”.

Se non c’è complessità, perché introdurre tutto il cerimoniale che il DDD mi impone/propone? Ma quando la complessità c’è, è evidente o è percepibile, vi posso assicurare che i principi e le linee guida sviscerabili dal *libro*, con qualche aggiunta qua e là, hanno un valore aggiunto inestimabile, quel valore aggiunto che, con il crescere del progetto, ci permette di gestire veramente a basso sforzo la complessità.

Non ho risposte certe, non ci sono medaglie in palio :-) , ma se volete vedere e condividere la nostra visione e soprattutto una possibile implementazione vi aspetto al primo evento di Guisa che si terrà a Treviglio il 4 maggio.

Mi raccomando non mancate.

TDD: focalizza il problema

Prendo spunto da un post del socio, per dire la mia (non me ne voglia), in merito al TDD e soprattutto ad alcuni dei suoi vantaggi “intrinseci”.

Il ciclo “red-green-refactor”, ai più ormai noto, è, al primo impatto, molto semplice: parti da un test rosso e implementa il codice, il più velocemente possibile, per farlo diventare verde. Solo dopo procedi a colpi di refactoring, a migliorare ciò che hai scritto.
Questa frase porta con se alcuni “hidden-statements” che nascondono alcuni dei migliori side-effect del TDD. Uno di questi è la focalizzazione del problema.

L’utilizzo del TDD mi permette di definire, in modo chiaro ed inequivocabile, da dove parto e dove voglio arrivare, magari non seguendo, in prima battuta, la strada migliore. E quindi porre l’attenzione su uno specifico aspetto, senza far deragliare il mio cervello alla ricerca di soluzioni pseudo-alternative.

Il rischio di sovraingegnerazione è dietro l’angolo e divergere dall’obbiettivo preposto, è un costo che è difficile da ammortizzare. L’utilizzo del TDD è “pippa-free”: fai quel che serve alla tua applicazione, in prima battuta, nel modo più smart possibile. Nulla vieta, anzi è auspicato, in un secondo momento (la fase di refactoring, appunto), di affinarne l’implementazione.

Un altro di quegli aspetti che fanno del TDD una metodologia ad alto valore aggiunto è quello di perseguire la semplicità. L’utilizzo di questa metodologia porta con se una metrica molto importante: maggiore è il tempo di “latenza” in cui un test rimane rosso è un sintomo, abbastanza preciso, di alta complessità.
Avere un feedback molto rapidamente sul fatto che la strada intrapresa è troppo tortuosa e quindi difficilmente perseguibile, è un indicatore da non sottovalutare e che permettere di farci intestardire in soluzioni “senza futuro”.

Insomma…va bene il design, va bene la batteria di test implicita che andiamo via via a creare…ma anche il contorno (o forse soprattutto quello), fanno del TDD uno “strumento” sempre più indispensabile nel mio lavoro.

 

 

CommunityDays: che esperienza!!!

Giovedì e venerdì scorso, come ormai tutti sanno, si sono tenuti presso il nuovo innovation campus di Microsoft, i community days.

Non ho parole per descrivere questo evento: fe-no-me-na-le!!!!
Veramente tutto oltre le più rosee aspettative: l’organizzazione, la location, la partecipazione,  gli argomenti delle varie sessioni, lo spirito community.
Un grazie di cuore agli organizzatori, Andrea e Daniele (in rigoroso ordine alfabetico) e a tutto lo staff in generale, per l’impegno e la massima disponibilità per rendere questa conferenza veramente unica.

Tra le altre cose ho avuto anche la possibilità e l’onore di partecipare in qualità di speaker, con una sessione “particolare”.
In questa sessione abbiamo cercato di vedere come evolvere da un domain model anemico (ma può esistere un domain model anemico? se è un domain model non credo possa essere anche anemico, boh?!?!?), ad un domain model con aggregate e bounded context ben definiti. Abbiamo visto come un database documentale, come  MongoDb, possa rendere fiction-less la parte di persistenza, permettendoci di concentrarci sulla “ciccia”, ovvero sulla parte di behavior del nostro dominio.

La cosa che più mi ha fatto piacere è vedere l’estremo interesse dei partecipanti e l’entusiasmo che queste tematiche hanno suscitato nella platea.

DDD è un argomento caldo, se ne parla (troppo) da tempo è ora di vedere anche un po’ di codice :-)
State sintonizzati su questo blog e soprattutto non dimenticatevi di iscrivervi al primo evento che stiamo organizzando con guisa…anche lì ne vedremo delle belle!!!

Prism: il bootstrapper

Il punto di ingresso di ogni applicazione che si basa su Prism è il bootstrapper.

Il bootstrapper deve contenere tutto quel codice di setup che permetterà alla nostra applicazione di funzionare. Questo è l’unico punto della nostra applicazione in cui mi concedo di mettere un po’ di “sporcizia”: non pongo molta attenzione alla pulizia del codice in questo contesto. Ma è proprio questo contesto che mi permette di gestire, successivamente, in modo “pulito” la parte infrastrutturale della mia applicazione: logging, container di IoC…

Prism utilizza nativamente Unity (o MEF) come container di IoC. Qualora si decida di non utilizzare altro tipo di container, metà dell’opera è già “archiviata”. E quindi partiamo così, scegliendo Unity :-)

Un ottimo punto di partenza è, quindi, quello di sfruttare la classe UnityBootstrapper e customizzare solo gli aspetti che “deviano” dal tradizionale. Creiamoci quindi il nostro bootstrapper, andando a ridefinire solo lo stretto indispensabile:

public class LittleJohnBootstrapper : UnityBootstrapper     
{
    protected override DependencyObject CreateShell()
    {
        return new Shell();
    }
 
    protected override void InitializeShell()
    {
        //base.InitializeShell();
 
        Application.Current.MainWindow = (Window) Shell;
        Application.Current.MainWindow.ShowDialog();
     }
}

…e inizializzando la nostra applicazione affinché utilizzi il bootstrapper per “setuppare” l’infrastruttura su cui si baserà il resto:

public partial class App     
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
 
        var bootstrapper = new LittleJohnBootstrapper();
        bootstrapper.Run();
     }
}

Il setup minimale prevede di istruire il nostro bootstrapper su come creare ed inizializzare la shell, ovvero l’involucro della nostra applicazione. Fatto questo, il resto del setup è già compreso nella classe UnityBootstrapper.

Andiamo,però, a sbirciare il dietro le quinte di questa classe, giusto per capire cosa “combina”, nel caso volessimo customizzarla un po’ o prevederne una basata, per esempio, su un container differente.
Il punto che da l’avvio a tutta la procedura di setup del bootstrapper e, quindi, dell’applicazione stessa è il metodo Run. Nell’ordine vengono eseguite le seguenti operazioni:

  • Creazione del logger: di default prism utilizza un TextLogger per eseguire le operazioni di logging. Tutte le informazioni vengono “streammate” di default sulla console.
  • Creazione e configurazione del module catalog: contiene le informazioni relative ai moduli che sono utilizzabili dall’applicazione. Prism contiene diverse implementazioni che permettono diverse sorgenti per il caricamento dei moduli (le vedremo in seguito)
  • Creazione e configurazione del container: il container viene configurato con tutti i servizi trasversali all’applicazione (logger, module catalog, module initializer, module manager, region manager, event aggregator e altro)
  • Creazione e configurazione della shell (invocando i metodi che abbiamo ridefinito nel nostro bootstrapper, visti in precedenza)
  • Inizializzazione degli eventuali moduli dell’applicazione

Una cosa molto importante, che non dobbiamo dimenticarci di eseguire qualora decidessimo di crearci un nostro bootstrapper da zero (non utilizzando UnityBoostrapper, ma partendo direttamente da Bootstrapper), è quella di associare la nostra Shell al RegionManager di default, garantendoci tutte le inizializzazioni necessarie per sfruttare il meccanismo, che vedremo in seguito, dell’iniezione delle viste nelle regioni.

Il codice incriminato è molto semplice, ma indispensabile. Eccolo, copiato “as-is” dalla classe UnityBootstrapper:

this.Shell = this.CreateShell();      
if (this.Shell != null)
{
    // tolto il log per evitare inutile rumore
    RegionManager.SetRegionManager(
        this.Shell, 
        UnityContainerExtensions.Resolve<IRegionManager>(
            this.Container, 
            new ResolverOverride[0]));
    // tolto il log per evitare inutile rumore        
    RegionManager.UpdateRegions();
 
    // tolto il log per evitare inutile rumore        
    this.InitializeShell();
}

Be, per ora un po’ di carne al fuoco ne abbiamo messa, ma…siamo solo agli inizi.

Prism: introduzione

Ok, ci riprovo: per un progetto che sta partendo abbiamo deciso di utilizzare Prism. Tempo fa ci avevamo già provato (è vero, le competenze su WPF/MVVM non erano al livello di quelle attuali), ma l’utilizzo di Prism aveva introdotto una complessità tale da farci andare “fuori giri”: ogni piccola modifica o funzionalità “fuori dal coro” era un costo non indifferente e l’amalgama complessivo non era per nulla soddisfacente.

Ma perchè allora ritentare? Essenzialmente perchè ci servono Regions/RegionManager e la gestione dei Moduli e non ci va assolutamente di reinventare la ruota. Purtroppo, che io sappia, con mvvmlight, che era fino ad oggi il nostro framework di supporto per lo sviluppo di app WPF, tutto questo non c’è…

Questo post fungerà da sommario di tutte le “puntate”, in modo da avere un punto univoco da cui accedere ai vari post:

  • L’entry point di un’applicazione basata su prism: il bootstrapper

NuGet e la debug-experience

Che cosa sia NuGet è ormai noto a tutti, ma non tutte le sue potenzialità sono conosciute.

Una cosa di cui sento parlare troppo poco (eufemismo per dire *mai*) è la possibilità, con pochi semplici comandi, di “pushare”, oltre al tradizionale pacchetto di nuget, anche i simboli di debug delle dll corrispondenti, rendendo la debug-experience degli utenti del package di un livello superiore.

Vediamo i semplici passi da seguire:

Creiamo un progetto di tipo ‘class library’ e chiamamolo StringUtils. Aggiungiamo un extension method per la classe string (giusto per avere del semplice codice da pacchettizzare con nuget)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static class StringExtensionMethods
{
    public static String ToCamelCase(this String current)
    {
        if (String.IsNullOrEmpty(current)) return current;
 
	var result = new StringBuilder();
	for (var i=0; i<current.Length; i++)
	{
	    if (i % 2 == 0)
	        result.Append(current[i].ToString().ToUpper());
	    else
		result.Append(current[i].ToString().ToLower());
	}
	return result.ToString();
    }
}

Passiamo ora alla console e creiamo per prima cosa i metadati da associare al pacchetto di nuget con il comando:

nuget spec

Se il precedente comando è eseguito nella stessa directory in cui è presente il file di progetto (*.csproj), nuget predispone i matadati, leggendo alcune informazioni dal file AssemblyInfo.cs del progetto stesso.
La precedente operazioni dovrebbe avere generato un file StringUtils.nuspec simile a questo (da completare manualmente in alcune sue voci):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0"?>
<package >
  <metadata>
    <id>StringUtils</id>
    <version>1.4</version>
    <title>StringUtils</title>
    <authors>melkio</authors>
    <owners>CodicePlastico srl</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>
        Semplice classe di utility per le stringhe
    </description>
    <releaseNotes></releaseNotes>
    <copyright>Copyright ©CodicePlastico srl  2012</copyright>
    <tags>Utils</tags>
  </metadata>
</package>

Perfetto! Ora siamo pronti a generare il package vero e proprio:

nuget pack StringUtils.csproj -Symbol
 
Attempting to build package from 'StringUtils.csproj'.
Packing files from '...\StringUtils\bin\Debug'.
Using 'StringUtils.nuspec' for metadata.
Successfully created package '...\StringUtils.1.4.nupkg'.
 
Attempting to build symbols package for 'StringUtils.csproj'.
Packing files from '...\StringUtils\bin\Debug'.
Using 'StringUtils.nuspec' for metadata.
Successfully created package '...\StringUtils.1.4.symbols.nupkg'.

Notiamo nel comando precedente due cose essenziali:
1) il package è creato a partire dal file di progetto (*.csproj) e non da quello con i metadati (*.nuspec)
2) è stata aggiunta l’opzione ‘Symbol’, che istruisce nuget alla creazione anche di un package con i simboli di debug

Se tutto è andato a buon fine dovremmo trovare due package: StringUtils.1.4.nupkg e StringUtils.1.4.symbols.nupkg

E’ arrivato il momento di “pushare” i package sui rispettivi repository. Niente di più facile!
Per prima cosa, se ancora non l’abbiamo fatto, impostiamo l’apikey associata al nostro utente nuget, tramite il comando:

nuget setApiKey AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEE
 
The API Key 'AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEE' was saved 
for the NuGet gallery (https://www.nuget.org) and the symbol 
server (http://nuget.gw.symbolsource.org/Public/NuGet).

…e poi…”push”

nuget push StringUtils.1.4.nupkg
 
Pushing StringUtils 1.4 to the NuGet gallery (https://www.nuget.org)...
Your package was pushed.
Pushing StringUtils 1.4 to the symbol server (http://nuget.gw.symbolsource.org/Public/NuGet)...
Your package was pushed.

L’applicazione console di nuget si accorge della presenza di un symbols-package e, oltre all’upload del tradizionale package sul repository di nuget, si occupa dell’upload del package con i simboli sul repository pubblico di symbolsource.

Come possiamo notare, non abbiamo dovuto fare nulla per abilitare la scrittura sul repository dei simboli. Questo perché, tramite l’apikey impostata in precedenza, symbolsource determina l’ownership del package e ne conferma o meno l’upload.

NOTA: A causa di un problema con la nuova versione dell’applicazione console di nuget (versione 1.6) della gallery di NuGet potrebbero verificarsi problemi nella verifica della ownership del package, impedendo l’upload sul repository dei simboli, generando un errore simile al seguente:

“Failed to process request. ‘Failed to verify permissions for upload: Project NuGet/StringUtils not found or inaccessible for Public/melkio. See http://www.symbolsource.org/Public/Home/Help for possible reasons. Fiddler may help diagnosing
this error if your client discards attached detailed information.’.
The remote server returned an error: (418) Failed to verify permissions for upload: Project NuGet/StringUtils not found or inaccessible for Public/melkio. See
http://www.symbolsource.org/Public/Home/Help for possible reasons. Fiddler may help diagnosing this error if your client discards attached detailed information.”

Il problema è documentato qui e l’unico modo che, per ora, ho trovato per bypassare il problema è stato quello di scrivere sul forum di symbolsource, richiedendo l’abilitazione manuale della ownership.

A questo punto, chi utilizza il nostro package, configurando opportunamente VisualStudio come descritto qui avrà la possibilità di sfruttare anche i simboli di debug e, quindi, la possibilità di navigare nel nostro codice.

E allora, come direbbe il “mitico” Marzullo, la domanda sorge spontanea: perché se il “costo” di tale feature è praticamente nullo (fa tutto la console di nuget), non tutti i package presenti sul repository ufficiale di nuget, non hanno il loro corrispettivo in symbolsource e rendono la mia (e la vostra) debug-experience molto complicata, se non impossibile?

community.StartNewYear()

Come molti di voi sapranno il prossimo anno inizia con i botti: due grandi conferenze nei primissimi mesi (gennaio e febbraio) dell’anno. Di cosa sto parlando?
No #uan12? No #cdays12? ahí ahí ahí

Quest’anno avrò l’onore, oltre che il piacere, di partecipare in qualità di speaker. Ecco di cosa parleremo:

Roslyn: un compilatore per amico
Fino a prima dell’avvento di Roslyn, il compilatore era una black box alla quale guardavamo con sconsolata ammirazione. Ora le “porte” si aprono e le possibilità si sprecano. In questa sessione cercheremo di capire di che si tratta e come sfruttare le potenzialità del compiler-as-a-service

NoSQL: persistere il Domain Model con MongoDB
In questa sessione cercheremo di evolvere un dominio anemico in un dominio con “data and behavior” enfatizzando il lato writable di CQRS e utilizzando MongoDb per la persistenza.

Due eventi gratuiti, tre importantissime giornate di formazione: un ottimo investimento per il nostro lavoro. E se tanto mi da tanto credo proprio che le community italiane non si fermeranno qui…

Mi raccomando non mancate!!!!
Ci vediamo lì

ITWPC2011.IsOver = true

wpc2011

Come molti di voi sapranno, oggi si è conclusa WPC, una tre giorni a tutta tecnologia che si è tenuta in quel di Assago.

Innanzitutto complimenti a tutto il team di Overnet, nessuno escluso: per organizzare un evento del genere ci vuole uno sforzo non indifferente e quando tutto fila per il verso giusto significa che è stato fatto proprio un ottimo lavoro. Bravi ;-)

Oltre che sotto il punto di vista prettamente tecnologico, queste conferenze sono, per me, un ottimo modo per incontrare vecchi amici che durante l’anno ho poche occasioni di frequentare, per la distanza che ci separa e/o per il poco tempo a disposizione. Le nuove conoscenze poi si sprecano…

Quest’anno ho presentato una sessione su WPF e come analizzarne ed ottimizzarne le performance, argomento un po’ particolare, ma che ha suscitato particolare interesse nella platea, accorsa più numerosa di quanto pensassi.
La sessione è andata bene, a parte la macchina virtuale con le demo che ha pensato bene di riavviarsi a metà dell’opera per installare gli aggiornamenti del sistema operativo…ma si sa, Murphy è sempre dietro l’angolo.

Ci si vede l’anno prossimo a #ITWPC12

NuGet, le dll e il source control (2)

Nel post precedente, abbiamo visto come sfruttare NuGet per evitare di committare tutti i packages (leggi dll) sul source control e integrarne il download da uno o più repository nel processo di build della nostra solution.
Per far funzionare tutto il processo, anche se non menzionato nel post, è necessario che NuGet.exe sia registrato nel path, in modo che sia facilmente accessibile dai nostri pre-build events.

Chiacchierando con andrea, una soluzione alternativa potrebbe essere quella di creare una cartella “tools” per ogni solution, nella quale inserire l’eseguibile di nuget e far puntare a quell’eseguibile i pre-build events. In questo modo l’ingresso di un nuovo componente nel team o la messa in opera di un build server ha un impatto ancora minore: nessun presetting da soddisfare, un update dal source control, una build et voilà…tutto funziona.

Se il processo così descritto ci soddisfa, c’è una soluzione pronta all’uso, ancora più integrata e a minore impatto (grazie a roberto per la segnalazione): i NuGetPowerTools.

Questo package è composto da soli script di powershell che automatizzano le nostre esigenze…installiamolo con NuGet.

Il package arricchisce la nostra console PowerShell con alcuni nuovi comandi. Quello che fa al caso nostro è il comando

Enable-PackageRestore

Viene quindi creata, a livello di solution, una folder .nuget che contiene l’eseguibile NuGet.exe e un file nuget.targets contenente l’integrazione per/con msbuild.

A questo punto, ricordandosi di committare la folder .nuget, ad ogni rebuild della solution, ogni package necessario alla compilazione viene, ovviamente se necessario, downloadato e installato nel/i progetto/i.

Ottima soluzione, niente pre-build events e pronta all’uso.

Vi dirò però che dover committare la folder .nuget e l’eseguibile NuGet.exe non mi soddisfa appieno: risolve un problema (commit delle dll) per “crearne” un altro (commit dell’eseguibile). Ricordiamoci infatti che l’eseguibile di NuGet è passibile di aggiornamenti che, all’occorrenza, verrebbero commitatti integrando la “history” del file sul source control.

Buon nugetting a tutti!!!