<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>Architettura</title>
        <link>http://blogs.ugidotnet.org/matteomigliore/category/3168.aspx</link>
        <description>Architettura</description>
        <language>it-IT</language>
        <copyright>Matteo Migliore</copyright>
        <generator>Subtext Version 2.1.0.3</generator>
        <item>
            <title>Usare TDD ovunque, testare un servizio WCF - TDD everywhere, testing a WCF service</title>
            <link>http://blogs.ugidotnet.org/matteomigliore/archive/2009/11/28/usare-tdd-ovunque-testare-un-servizio-wcf-tdd-everywhere.aspx</link>
            <description>&lt;p&gt;Il Test Driven Development è un’altra delle metodologie secondo me vincenti, specialmente in alcuni contesti, in alcuni, perchè non è detto che siano sempre adatte. &lt;br /&gt;
&lt;br /&gt;
TDD o meglio Test Driven &lt;font color="#ff8000"&gt;Design&lt;/font&gt; è particolamente utile quando si scrive una nuova applicazione o nuove feature nella fase di design della soluzione, partire dal test permette di tradurre al meglio la User Story o la feature (&lt;a title="Wikipedia: Feature Driven Development" href="http://en.wikipedia.org/wiki/Feature_Driven_Development"&gt;Feature Driven Development&lt;/a&gt;) nel codice che la implementa, si rimane concentrati sul cosa e non sul come, si scrive lo stretto necessario senza over-ingegnerizzare =&amp;gt; “over-complicare”. &lt;br /&gt;
&lt;br /&gt;
Scrivendo prima il test si identificano le classi/membri esattamente nel momento in cui servono, inoltre con i test ovviamente… si hanno i test :), si possono verificare più use-case e rendere il codice più robusto. Infine grazie agli stub ed ai mock non è indispensabile lavorare sulle classi reali anzi meglio lavorare su fake con &lt;font color="#ff8000"&gt;Unit Test&lt;/font&gt;, invece che scrivere &lt;font color="#ff8000"&gt;Integration Test&lt;/font&gt;. Ovviamente sono utili anche gli Integration Test ed i &lt;font color="#ff8000"&gt;System Test&lt;/font&gt; per evitare &lt;span style="TEXT-DECORATION: underline"&gt;allo sviluppatore&lt;/span&gt; di eseguire continuamente l’applicazione. Nonstante questo gli &lt;a title="Wikipedia: Acceptance testing" href="http://en.wikipedia.org/wiki/Acceptance_testing"&gt;User Acceptance Test&lt;/a&gt; rimangono indispensabili, uno o più utenti devono testare l’applicazione e la UI specialmente (se esiste) perchè ovviamente è la parte maggiormente a contatto con il “ProductOwner” e probabilmente la più difficile da testare in automatico attualmente.&lt;/p&gt;
&lt;p&gt;Arriviamo al titolo del post :). In un progetto a cui lavoro ho avuto la necessità di creare una key per una entity che fosse in realtà un’insieme di valori eterogeneo, il motivo è che lo storage è più di uno ed ogni storage può definire differenti chiavi naturali (i loro progettisti, Topolino e Paperino, non conoscono le chiavi surrogate e i Guid :D). &lt;br /&gt;
&lt;img alt="Topolino e Paperino DB designers" width="349" height="190" src="http://dl.dropbox.com/u/1312798/Blog/2009/11/27/2/Disney.png" /&gt; &lt;br /&gt;
&lt;br /&gt;
Quindi partendo dal test:&lt;/p&gt;
&lt;div id="codeSnippetWrapper" class="csharpcode-wrapper"&gt;
&lt;div id="codeSnippet" class="csharpcode"&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum1" class="lnum"&gt;   1:&lt;/span&gt; &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; CreateAKeyExpectedCorrectNameAndCorrectValueAreSetted()&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum2" class="lnum"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum3" class="lnum"&gt;   3:&lt;/span&gt;     var concreteKey = &lt;span class="kwrd"&gt;new&lt;/span&gt; ConcreteKey(KnownKeys.Key);&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum4" class="lnum"&gt;   4:&lt;/span&gt;  &lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum5" class="lnum"&gt;   5:&lt;/span&gt;     concreteKey&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum6" class="lnum"&gt;   6:&lt;/span&gt;         .Id&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum7" class="lnum"&gt;   7:&lt;/span&gt;         .ShouldEqual(KnownKeys.Key, &lt;span class="str"&gt;"IdKey has not the expected value."&lt;/span&gt;);&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum8" class="lnum"&gt;   8:&lt;/span&gt; }&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;
Quindi la classe Key:&lt;/p&gt;
&lt;div id="codeSnippetWrapper" class="csharpcode-wrapper"&gt;
&lt;div id="codeSnippet" class="csharpcode"&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum1" class="lnum"&gt;   1:&lt;/span&gt; &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;abstract&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Key : IEnumerable&amp;lt;KeyValue&amp;gt;&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum2" class="lnum"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum3" class="lnum"&gt;   3:&lt;/span&gt;     &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; IEnumerable&amp;lt;KeyValue&amp;gt; keysDictionary;&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum4" class="lnum"&gt;   4:&lt;/span&gt;  &lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum5" class="lnum"&gt;   5:&lt;/span&gt;     &lt;span class="kwrd"&gt;protected&lt;/span&gt; Key(&lt;span class="kwrd"&gt;params&lt;/span&gt; KeyValue[] keyValues)&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum6" class="lnum"&gt;   6:&lt;/span&gt;     {&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum7" class="lnum"&gt;   7:&lt;/span&gt;         &lt;span class="kwrd"&gt;if&lt;/span&gt; ((keyValues == &lt;span class="kwrd"&gt;null&lt;/span&gt;) || (keyValues.Length == 0))&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum8" class="lnum"&gt;   8:&lt;/span&gt;         {&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum9" class="lnum"&gt;   9:&lt;/span&gt;             &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; ArgumentException(&lt;span class="str"&gt;"Must define at least a KeyValue."&lt;/span&gt;, &lt;span class="str"&gt;"keyValues"&lt;/span&gt;);&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum10" class="lnum"&gt;  10:&lt;/span&gt;         }&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum11" class="lnum"&gt;  11:&lt;/span&gt;  &lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum12" class="lnum"&gt;  12:&lt;/span&gt;         keysDictionary = keyValues;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum13" class="lnum"&gt;  13:&lt;/span&gt;     }&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum14" class="lnum"&gt;  14:&lt;/span&gt;  &lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum15" class="lnum"&gt;  15:&lt;/span&gt;     &lt;span class="kwrd"&gt;public&lt;/span&gt; IEnumerator&amp;lt;KeyValue&amp;gt; GetEnumerator()&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum16" class="lnum"&gt;  16:&lt;/span&gt;     {&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum17" class="lnum"&gt;  17:&lt;/span&gt;         &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum18" class="lnum"&gt;  18:&lt;/span&gt;             keysDictionary&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum19" class="lnum"&gt;  19:&lt;/span&gt;             .OrderBy(keyValue =&amp;gt; keyValue.Key)&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum20" class="lnum"&gt;  20:&lt;/span&gt;             .GetEnumerator();&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum21" class="lnum"&gt;  21:&lt;/span&gt;     }&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum22" class="lnum"&gt;  22:&lt;/span&gt;  &lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum23" class="lnum"&gt;  23:&lt;/span&gt;     IEnumerator IEnumerable.GetEnumerator()&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum24" class="lnum"&gt;  24:&lt;/span&gt;     {&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum25" class="lnum"&gt;  25:&lt;/span&gt;         &lt;span class="kwrd"&gt;return&lt;/span&gt; GetEnumerator();&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum26" class="lnum"&gt;  26:&lt;/span&gt;     }&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum27" class="lnum"&gt;  27:&lt;/span&gt;  &lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum28" class="lnum"&gt;  28:&lt;/span&gt;     &lt;span class="kwrd"&gt;protected&lt;/span&gt; T GetKeyValue&amp;lt;T&amp;gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt; keyName) &lt;span class="kwrd"&gt;where&lt;/span&gt; T : &lt;span class="kwrd"&gt;struct&lt;/span&gt;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum29" class="lnum"&gt;  29:&lt;/span&gt;     {&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum30" class="lnum"&gt;  30:&lt;/span&gt;         var &lt;span class="kwrd"&gt;value&lt;/span&gt; =&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum31" class="lnum"&gt;  31:&lt;/span&gt;             keysDictionary&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum32" class="lnum"&gt;  32:&lt;/span&gt;                 .Where(e =&amp;gt; e.Key == keyName)&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum33" class="lnum"&gt;  33:&lt;/span&gt;                 .First()&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum34" class="lnum"&gt;  34:&lt;/span&gt;                 .Value;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum35" class="lnum"&gt;  35:&lt;/span&gt;  &lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum36" class="lnum"&gt;  36:&lt;/span&gt;         &lt;span class="kwrd"&gt;return&lt;/span&gt; (T) &lt;span class="kwrd"&gt;value&lt;/span&gt;;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum37" class="lnum"&gt;  37:&lt;/span&gt;     }&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;
Ho quindi scritto un DTO per trasportare le entity attraverso WCF e qui nasce il problema, non volendo creare un servizio WCF fittizio solo per verificare che il design sia corretto ho cercato come hostare il servizio direttamente dal test, ed ecco la soluzione: &lt;a title="Testable WCF ServiceHost" href="http://blog.kellybrownsberger.com/archive/2009/03/17/43.aspx"&gt;Testable WCF ServiceHost&lt;/a&gt;. &lt;br /&gt;
&lt;br /&gt;
In sostanza grazie alla classe scritta dall’autore è possibile questo test:&lt;/p&gt;
&lt;div id="codeSnippetWrapper" class="csharpcode-wrapper"&gt;
&lt;div id="codeSnippet" class="csharpcode"&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum1" class="lnum"&gt;   1:&lt;/span&gt; [TestMethod]&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum2" class="lnum"&gt;   2:&lt;/span&gt; &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; CallGetAllOfWcfServiceExpectedWorksAndKeysAreSetted()&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum3" class="lnum"&gt;   3:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum4" class="lnum"&gt;   4:&lt;/span&gt;     &lt;span class="kwrd"&gt;using&lt;/span&gt; (var messageServiceHost = &lt;span class="kwrd"&gt;new&lt;/span&gt; WcfTestHost&amp;lt;Service, IService&amp;gt;())&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum5" class="lnum"&gt;   5:&lt;/span&gt;     {&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum6" class="lnum"&gt;   6:&lt;/span&gt;         var client = messageServiceHost.CreateProxy();&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum7" class="lnum"&gt;   7:&lt;/span&gt;         var dtoSet = client.GetAll().ToList();&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum8" class="lnum"&gt;   8:&lt;/span&gt;  &lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum9" class="lnum"&gt;   9:&lt;/span&gt;         var keyValue = dtoSet[0]&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum10" class="lnum"&gt;  10:&lt;/span&gt;             .Key&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum11" class="lnum"&gt;  11:&lt;/span&gt;             .First();&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum12" class="lnum"&gt;  12:&lt;/span&gt;  &lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum13" class="lnum"&gt;  13:&lt;/span&gt;         keyValue&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum14" class="lnum"&gt;  14:&lt;/span&gt;             .Key&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum15" class="lnum"&gt;  15:&lt;/span&gt;             .ShouldEqual(ConcreteKey.IdKeyName, &lt;span class="str"&gt;"Expected a key that is not present."&lt;/span&gt;);&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum16" class="lnum"&gt;  16:&lt;/span&gt;  &lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum17" class="lnum"&gt;  17:&lt;/span&gt;         ((&lt;span class="kwrd"&gt;int&lt;/span&gt;)&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum18" class="lnum"&gt;  18:&lt;/span&gt;         keyValue&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum19" class="lnum"&gt;  19:&lt;/span&gt;             .Value)&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum20" class="lnum"&gt;  20:&lt;/span&gt;             .ShouldEqual(KnownKeys.Key, &lt;span class="str"&gt;"Wrong key value."&lt;/span&gt;);&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum21" class="lnum"&gt;  21:&lt;/span&gt;     }&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum22" class="lnum"&gt;  22:&lt;/span&gt; }&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;
Un pezzo della classe WcfTestHost:&lt;/p&gt;
&lt;div id="codeSnippetWrapper" class="csharpcode-wrapper"&gt;
&lt;div id="codeSnippet" class="csharpcode"&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum1" class="lnum"&gt;   1:&lt;/span&gt; &lt;span class="kwrd"&gt;public&lt;/span&gt; WcfTestHost(Binding binding)&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum2" class="lnum"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum3" class="lnum"&gt;   3:&lt;/span&gt;     host = &lt;span class="kwrd"&gt;new&lt;/span&gt; ServiceHost(serviceImplType);&lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum4" class="lnum"&gt;   4:&lt;/span&gt;     &lt;span class="kwrd"&gt;this&lt;/span&gt;.binding = binding;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum5" class="lnum"&gt;   5:&lt;/span&gt;  &lt;/pre&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum6" class="lnum"&gt;   6:&lt;/span&gt;     url = &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;"{0}://localhost/{1}"&lt;/span&gt;, binding.Scheme, Guid.NewGuid());&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum7" class="lnum"&gt;   7:&lt;/span&gt;     host.AddServiceEndpoint(serviceIntType, binding, url);&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;
Nell’esempio allegato si trova il progetto della key e la classe per testare un servizio WCF completa, grazie a qualche email scambiata con l’autore, di error handling e trace che permette di intercettare qualsiasi exception scatenata “lato server”. &lt;br /&gt;
&lt;img alt="Solution TDD WCF" src="http://dl.dropbox.com/u/1312798/Blog/2009/11/28/TDD%20everywhere/Solution.png" /&gt;  &lt;br /&gt;
&lt;br /&gt;
Scarica &lt;a title="TDD Everywhere with .NET" href="http://dl.dropbox.com/u/1312798/Blog/2009/11/28/TDD%20everywhere/EyeOpen.Key.zip"&gt;qui&lt;/a&gt;. &lt;br /&gt;
&lt;br /&gt;
Matteo Migliore. &lt;br /&gt;
&lt;br /&gt;
&lt;/p&gt;
&lt;div style="PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; FLOAT: none; PADDING-TOP: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:48421de9-4b81-42f3-922d-16dae0695ff4" class="wlWriterEditableSmartContent"&gt;Technorati Tags: &lt;a rel="tag" href="http://technorati.com/tags/test+WCF+sercvice"&gt;test WCF sercvice&lt;/a&gt;,&lt;a rel="tag" href="http://technorati.com/tags/wcf"&gt;wcf&lt;/a&gt;,&lt;a rel="tag" href="http://technorati.com/tags/test"&gt;test&lt;/a&gt;,&lt;a rel="tag" href="http://technorati.com/tags/TDD"&gt;TDD&lt;/a&gt;&lt;/div&gt;&lt;img src="http://blogs.ugidotnet.org/matteomigliore/aggbug/97628.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Matteo Migliore</dc:creator>
            <guid>http://blogs.ugidotnet.org/matteomigliore/archive/2009/11/28/usare-tdd-ovunque-testare-un-servizio-wcf-tdd-everywhere.aspx</guid>
            <pubDate>Sat, 28 Nov 2009 20:42:01 GMT</pubDate>
            <wfw:comment>http://blogs.ugidotnet.org/matteomigliore/comments/97628.aspx</wfw:comment>
            <comments>http://blogs.ugidotnet.org/matteomigliore/archive/2009/11/28/usare-tdd-ovunque-testare-un-servizio-wcf-tdd-everywhere.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/matteomigliore/comments/commentRss/97628.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Le solite letture per l&amp;rsquo;estate</title>
            <link>http://blogs.ugidotnet.org/matteomigliore/archive/2009/07/30/le-solite-letture-per-lrsquoestate.aspx</link>
            <description>&lt;p&gt;Ordinati settimana scorsa e stamattina sono arrivati nuovi fiammanti: &lt;br /&gt;
&lt;img title="Architecture Books" alt="Architecture Books" src="http://files.getdropbox.com/u/1312798/Blog/2009/07/30/Architecture Books.png" /&gt; &lt;br /&gt;
&lt;br /&gt;
1. &lt;a title="Amazon: Patterns Of Enterprise Application Architecture" href="http://www.amazon.co.uk/dp/0321127420"&gt;Patterns Of Enterprise Application Architecture&lt;/a&gt; (datato ma sempre valido) -  510 pagine&lt;br /&gt;
2. &lt;a title="Amazon: Domain Driven Design" href="http://www.amazon.co.uk/dp/0321125215"&gt;Domain Driven Design&lt;/a&gt; - 509 pagine &lt;br /&gt;
3. &lt;a title="Amazon: Enterprise Integration Patterns" href="http://www.amazon.co.uk/dp/0321200683"&gt;Enterprise Integration Patterns&lt;/a&gt; - 648 pagine&lt;br /&gt;
&lt;br /&gt;
[Update]&lt;br /&gt;
Si aggiungono alla lista altre tre letture, anche se il libro di Andrea e Dino è piu' una formalita' :) :&lt;br /&gt;
4. &lt;span id="btAsinTitle"&gt;&lt;a title="Amazon: Microsoft® .NET: Architecting Applications for the Enterprise" href="http://www.amazon.co.uk/dp/073562609X"&gt;Microsoft® .NET: Architecting Applications for the Enterprise&lt;/a&gt; - 304 pagine&lt;/span&gt;&lt;br /&gt;
5. &lt;span id="btAsinTitle"&gt;&lt;a title="Amazon: Test-Driven Development in Microsoft® .NET" href="http://www.amazon.co.uk/dp/0735619484"&gt;Test-Driven Development in Microsoft® .NET&lt;/a&gt; - 304 pagine&lt;br /&gt;
6. &lt;span id="btAsinTitle"&gt;&lt;a continuous="" improving="" software="" quality="" and="" reducing="" href="http://www.amazon.co.uk/dp/0321336380"&gt;Continuous Integration: Improving Software Quality and Reducing Risk&lt;/a&gt; - 336 pagine&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Totale pagine da leggere dense di concetti: 1667 [Update: &lt;font face="Arial"&gt;2611&lt;/font&gt;]. C’è da divertirsi. &lt;br /&gt;
&lt;br /&gt;
Matteo Migliore.&lt;/p&gt;&lt;img src="http://blogs.ugidotnet.org/matteomigliore/aggbug/96796.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Matteo Migliore</dc:creator>
            <guid>http://blogs.ugidotnet.org/matteomigliore/archive/2009/07/30/le-solite-letture-per-lrsquoestate.aspx</guid>
            <pubDate>Thu, 30 Jul 2009 10:08:21 GMT</pubDate>
            <wfw:comment>http://blogs.ugidotnet.org/matteomigliore/comments/96796.aspx</wfw:comment>
            <comments>http://blogs.ugidotnet.org/matteomigliore/archive/2009/07/30/le-solite-letture-per-lrsquoestate.aspx#feedback</comments>
            <slash:comments>6</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/matteomigliore/comments/commentRss/96796.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Esempio di DependencyInjection per gestire la security di ASP.NET usando WCF e Unity</title>
            <link>http://blogs.ugidotnet.org/matteomigliore/archive/2009/03/26/esempio-di-dependencyinjection-per-gestire-la-security-di-asp.net-usando.aspx</link>
            <description>&lt;p&gt;Su CodePlex ho pubblicato un semplice esempio su come rendere l’applicazione “dipendente” dalle DipendencyInjection :-). Bel controsenso. Scherzi a parte l’applicazione (mantenuta come sempre il più semplice possibile) pone il fuoco su come adottare un framework di IoC, wrappandolo, e quindi rendendo trasparente anche quello, e su come risolvere uno dei tanti problemi delle applicazioni web, come ad esempio cambiare i Membership e Role provider. In questo caso ci sono due implementazioni, la più interessante è quella che sfrutta WCF per gestire le credenziali. Intanto la trovate qui. Appena ho un attimo di tempo scriverò un po’ di documentazione e magari ne sviluppo una seconda versione più “real-world”, sfruttando anche Silverlight e il porting Silverlight di Unity. &lt;br /&gt;
&lt;br /&gt;
Eccola qui, &lt;a title="DependencyInjection sample to build a security system using-WCF, Unity, ASP.NET" href="http://wcfunitysecurity.codeplex.com/"&gt;DependencyInjection sample to build a security system using-WCF, Unity, ASP.NET&lt;/a&gt;. &lt;br /&gt;
&lt;a title="CodePlex: WcfUnitySecurity - DependencyInjection" href="http://wcfunitysecurity.codeplex.com"&gt;&lt;img alt="" src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=wcfunitysecurity&amp;amp;DownloadId=63248" /&gt;&lt;/a&gt; &lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;Se avete domande sparate pure. &lt;br /&gt;
&lt;br /&gt;
Matteo Migliore.&lt;/p&gt;&lt;img src="http://blogs.ugidotnet.org/matteomigliore/aggbug/95804.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Matteo Migliore</dc:creator>
            <guid>http://blogs.ugidotnet.org/matteomigliore/archive/2009/03/26/esempio-di-dependencyinjection-per-gestire-la-security-di-asp.net-usando.aspx</guid>
            <pubDate>Thu, 26 Mar 2009 15:46:27 GMT</pubDate>
            <wfw:comment>http://blogs.ugidotnet.org/matteomigliore/comments/95804.aspx</wfw:comment>
            <comments>http://blogs.ugidotnet.org/matteomigliore/archive/2009/03/26/esempio-di-dependencyinjection-per-gestire-la-security-di-asp.net-usando.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/matteomigliore/comments/commentRss/95804.aspx</wfw:commentRss>
        </item>
        <item>
            <title>[Architecture] DataSet vs Entity e il LazyLoading</title>
            <link>http://blogs.ugidotnet.org/matteomigliore/archive/2008/03/08/architecture-dataset-vs-entity-e-il-lazyloading.aspx</link>
            <description>Come sempre il NG è fonte di ispirazione... L'argomento DataSet vs Entity è ormai trito e ritrito, ma per chi è agli inizi non è banale. Prima di tutto voglio chiarire, secondo me, in quale scenario i DataSet possono essere utili: i DataSet sono la rappresentazione in memory del DB, quindi "sono dei rettangoli" (cit. &lt;a title="Blog: Andrea Saltarello" href="http://blogs.ugidotnet.org/pape"&gt;Andrea&lt;/a&gt;) e sono stati creati per rappresentare fedelmente i DB (non uno storage qualsiasi), pertanto sono presenti righe, colonne, relation etc..., ma niente di più. Se è necessario fare un travaso di dati, eventualmente elaborarli e poi aggiornare il DB, possono essere utili, non avrebbe molto senso perdere tempo a scrivere un Domain Model e rispettivo Data Layer per fare un'operazione di questo tipo. I DataSet possono anche essere utili in "applicazioni che non vedranno mai la versione 2.0" (cit. &lt;a title="Blog: Raffaele Rialdi" href="http://blogs.ugidotnet.org/raffaele"&gt;Raffaele&lt;/a&gt;), anche se in questo caso il beneficio mi sembra minimo, considerando che l'unica cosa che si evita è di scrivere il DAL, perchè anche le &lt;a title="MSDN: Class Designer" href="http://msdn2.microsoft.com/en-us/library/aa288743.aspx"&gt;classi hanno un designer&lt;/a&gt;! &lt;br /&gt;
&lt;br /&gt;
In tutti gli altri casi è necessario scrivere un &lt;a title="Martin Fowler: Domain Model" href="http://www.martinfowler.com/eaaCatalog/domainModel.html"&gt;Domain Model&lt;/a&gt; (le entity e le loro relazioni), un &lt;a title="Wikipedia: Data Access Layer" href="http://en.wikipedia.org/wiki/Data_access_layer"&gt;Data Access Layer&lt;/a&gt; (possibilmente astratto, vedi &lt;a title="CodePlex: Northwind Starter Kit" href="http://www.codeplex.com/NSK"&gt;NSK&lt;/a&gt;), un &lt;a title="Martin Fowler: Service Layer" href="http://www.martinfowler.com/eaaCatalog/serviceLayer.html"&gt;Service Layer&lt;/a&gt; che contiene l'application logic (regole di business, validazione, security etc...) ed eventualmente il Presentation (in varie tecnologie: Windows, Web, Web + &lt;a title="Blog: Scott Guthrie - First Look at Silverlight 2" href="http://weblogs.asp.net/scottgu/archive/2008/02/22/first-look-at-silverlight-2.aspx"&gt;Silverlight&lt;/a&gt;, Mobile). Un'applicazione monolitica è difficilmente aggiornabile e non risponde all'esigenze del mercato, che richiede reattività e versatilità. &lt;br /&gt;
&lt;p style="align: center" align="left"&gt;&lt;strong&gt;&lt;br /&gt;
Domain Model&lt;/strong&gt;&lt;/p&gt;
&lt;p align="left"&gt;&lt;img alt="Domain Model" src="http://dganba.blu.livefilestore.com/y1pAIhthE_oan96MwcqKd801P-_uy9CD_M1VV77xkkA0LsOm54NKz2uGzZWpXPhaodCpCIXiAnL6Xmr8DQMoVUpiA/DomainModel_Dark.png" /&gt;&lt;/p&gt;
Creare un Domain Model con classi e custom collection produce dei grossi vantaggi rispetto ai DataSet: &lt;br /&gt;
- è possibile sfruttare pienamente il paradigma &lt;a title="Wikipedia: Object Oriented Programming" href="http://en.wikipedia.org/wiki/Object-oriented_programming"&gt;OOP&lt;/a&gt; &lt;br /&gt;
- le classi rappresentano &lt;a title="Martin Fowler: Anemic Domain Model" href="http://martinfowler.com/bliki/AnemicDomainModel.html"&gt;data &amp;amp; behavior&lt;/a&gt;, i DataSet molto difficilmente &lt;br /&gt;
- le performance migliorano notevolmente (si possono creare dei &lt;a title="Martin Fowler: Data Transfer Object" href="http://www.martinfowler.com/eaaCatalog/dataTransferObject.html"&gt;DTO&lt;/a&gt; ad-hoc, per ogni &lt;a title="Microsoft: Windows Communication Foundation" href="http://msdn2.microsoft.com/en-us/netframework/aa663324.aspx"&gt;servizio esposto&lt;/a&gt; dall'application server) &lt;br /&gt;
- il Data Access Layer può creare delle classi proxy (NHibernate lo può fare anche &lt;a title="NHibernate: Mapping Dynamic Proxy" href="http://www.hibernate.org/339.html"&gt;dinamicamente&lt;/a&gt;) che consentono di caricare i dati in modo lazy, cioè solo quando necessario (e.g. nel "get" di una property pesante, come un'immagine, non alla crezione dell'oggetto) 
&lt;p style="align: center" align="left"&gt;&lt;br /&gt;
&lt;strong&gt;Layering&lt;/strong&gt;&lt;/p&gt;
&lt;p align="left"&gt;&lt;img alt="" src="http://dganba.blu.livefilestore.com/y1pAIhthE_oan9DJYHhwp-RgR0jYCrhyMeXMbtObQ0oO_7RI98hZEH-i0SbJ0k4fQjEWDLHo2FztpbxQD0ESBM1uw/Layering_Dark.png" /&gt;&lt;/p&gt;
&lt;p align="left"&gt;E' necessario stratificare correttamente i blocchi funzionali dell'applicazione, e renderli indipendenti fra di loro, perchè l'applicazione sia versatile e si riescano a riflettere i cambiamenti alle logiche in modo tempestivo, e per rendere scalabile quanti più blocchi possibili, in modo che all'aumentare delle richieste sia possibile migliorare le performance aggiungendo risorse. &lt;br /&gt;
&lt;br /&gt;
In questo scenario ad esempio il Data Access Layer, il livello che si occupa della persistenza dei dati (su DB, file-system o servizi esterni), può essere sostituito a seconda dello storage sul quale si vuole andare, senza modificare nessun altro blocco dell'applicazione, che non conosce assolutamente i dettagli implementativi, ma solo i contratti che ha a disposizione per persistere i dati. &lt;br /&gt;
&lt;br /&gt;
Altra cosa importante è non implementare tutta la logica applicativa nel Business Layer perchè è possibile che più applicazioni lavorino sugli stessi dati, ma con logiche differenti, oppure che anche la stessa applicazione lavori sullo stesso dato ma con vincoli e logiche differenti a seconda del contesto. &lt;br /&gt;
&lt;br /&gt;
Esempio. &lt;br /&gt;
Un portale consente la registrazione degli utenti in due modalità: &lt;br /&gt;
- light: viene richiesto solamente l'indirizzo email per l'invio della news letter &lt;br /&gt;
- full: sono richiesti dati di fatturazione, per l'acquisto di beni/servizi &lt;br /&gt;
&lt;br /&gt;
La classe Person viene utilizzata in entrambi i contesti ma ovviamente le logiche di validazione sono differenti. Se queste fossero cablate in un ipotetico metodo IsValid all'interno della classe stessa, sarebbe difficile (&lt;a title="CodePlex: ValidationInverse" href="http://www.codeplex.com/ValidationInverse"&gt;non impossibile&lt;/a&gt;) soddisfare. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;/p&gt;
&lt;div style="align: center"&gt;
&lt;div style="align: center"&gt;&lt;img alt="That's All Falks" src="http://dganba.blu.livefilestore.com/y1pAIhthE_oan_qLQFkc1i8fqqv8zW3ndKogYk6YH6iZDQq150ObQVLQldWlxditQ7JglajnI1avGlIOrPPvH6rKw/Thats-All-Falks_Dark.png" /&gt;  &lt;br /&gt;
&lt;br /&gt;
Matteo Migliore.&lt;/div&gt;
&lt;/div&gt;&lt;img src="http://blogs.ugidotnet.org/matteomigliore/aggbug/91587.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Matteo Migliore</dc:creator>
            <guid>http://blogs.ugidotnet.org/matteomigliore/archive/2008/03/08/architecture-dataset-vs-entity-e-il-lazyloading.aspx</guid>
            <pubDate>Sat, 08 Mar 2008 19:45:43 GMT</pubDate>
            <wfw:comment>http://blogs.ugidotnet.org/matteomigliore/comments/91587.aspx</wfw:comment>
            <comments>http://blogs.ugidotnet.org/matteomigliore/archive/2008/03/08/architecture-dataset-vs-entity-e-il-lazyloading.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/matteomigliore/comments/commentRss/91587.aspx</wfw:commentRss>
        </item>
        <item>
            <title>[Architecture] Aforismi per l'architettura</title>
            <link>http://blogs.ugidotnet.org/matteomigliore/archive/2008/03/03/architecture-aforismi-per-larchitettura.aspx</link>
            <description>&lt;p&gt;A mio modo di vedere (confermato dagli infiniti post a riguardo) l'architettura e le metodologie software possono essere riassunte nella testa di un buon architetto con cinque o sei aforismi fondamentali, &lt;a title="Martin Fowler" href="http://www.martinfowler.com"&gt;Fowler&lt;/a&gt; stesso sforna in continuazione "aforismi" per riassumere al meglio i suoi preziosi consigli. Chi è un buon architetto? La sua astrazione non è banale, i punti di vista sono molti, ma se è vero che una delle definizioni di intelligenza è "la capacità di adattare a proprio vantaggio il mondo circostante", forse, un buon architetto software è colui che riesce ad "ottenere la soluzione più vantaggiosa dati: il progetto, le tecnologie e il team a disposizione". In quest'ottica il project manager e l'architetto tendono ad una sfumatura di ruolo. La frase che mi ha colpito, e che purtroppo tengo troppo poco come faro nella nebbia è: "&lt;strong&gt;è più facile unire le stupidità che far collaborare le intelligenze&lt;/strong&gt;". Pensandoci, questo aforisma è vero in molti casi, nei team in cui lavoro, specialmente nella fase iniziale, si tendono a produrre molte "collisioni" su chi si deve occupare di cosa e a stabilire quale sia la soluzione più intelligente, tendendo spesso a voler far vincere la propria. Lo sforzo maggiore invece si dovrebbe investire nel capire come orchestrare al meglio il cervello di tutti per produrre una sinfonia di capacità che diano il massimo nella risoluzione del problema centrale: il progetto. Come sempre, tutte queste riflessioni, anche banali, sono espresse modestamente, senza alcuna pretesa, forse sono più un memorandum per me che le scrivo, per ricordarle la prossima volta che mi affaccerò ad un nuovo scenario, ad una nuova sfida :-). &lt;br /&gt;
&lt;br /&gt;
Matteo Migliore.&lt;/p&gt;&lt;img src="http://blogs.ugidotnet.org/matteomigliore/aggbug/91478.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Matteo Migliore</dc:creator>
            <guid>http://blogs.ugidotnet.org/matteomigliore/archive/2008/03/03/architecture-aforismi-per-larchitettura.aspx</guid>
            <pubDate>Mon, 03 Mar 2008 16:46:54 GMT</pubDate>
            <wfw:comment>http://blogs.ugidotnet.org/matteomigliore/comments/91478.aspx</wfw:comment>
            <comments>http://blogs.ugidotnet.org/matteomigliore/archive/2008/03/03/architecture-aforismi-per-larchitettura.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/matteomigliore/comments/commentRss/91478.aspx</wfw:commentRss>
        </item>
        <item>
            <title>[Tip] Versioning degli Assembly di una stessa solution</title>
            <link>http://blogs.ugidotnet.org/matteomigliore/archive/2008/01/12/tip-versioning-degli-assembly-di-una-stessa-solution.aspx</link>
            <description>&lt;p&gt;Un semplice tip che mi ha consigliato &lt;a title="Blog: Mauro Servienti" href="http://blogs.ugidotnet.org/topics/"&gt;Mauro&lt;/a&gt; per il versioning degli assembly a cui non avevo pensato, ma utile per avere un repository comunue delle informazioni relative alla società, nome e versione del prodotto e altre informazioni. In pratica anzichè definire un file AssemblyInfo.cs (o .vb) per ogni progetto, si crea un file condiviso in tutta la soluzione (o più soluzioni) e lo si referenzia in ogni project come link.&lt;br /&gt;
&lt;br /&gt;
In questo modo tutti gli assembly avranno associate le stesse informazioni, potendo ovviamente redefinire quelle specifiche e legate al project.&lt;br /&gt;
&lt;br /&gt;
Qui trovate come fare:&lt;br /&gt;
&lt;a title="Versioning Groups of Assemblies in sync on Loren Halvorson Blog" href="http://weblogs.asp.net/lorenh/archive/2004/09/20/232200.aspx"&gt;http://weblogs.asp.net/lorenh/archive/2004/09/20/232200.aspx&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
La condivisione delle informazioni è utile specialmente se utilizzata nella metodologia del &lt;a title="Continuous Integration on Wikipedia" href="http://en.wikipedia.org/wiki/Continuous_integration"&gt;Continuous Integration&lt;/a&gt;, uno dei pilastri dell'&lt;a title="Extreme Programming on Wikipedia" href="http://en.wikipedia.org/wiki/Extreme_Programming"&gt;Extreme Programming&lt;/a&gt;. Uno dei sostenitori? Il mitico &lt;a title="Continuous Integration by Martin Fowler" href="http://www.martinfowler.com/articles/continuousIntegration.html"&gt;Martin Fowler&lt;/a&gt;, amato da &lt;a title="Blog: Andrea Saltarello" href="http://blogs.ugidotnet.org/pape"&gt;Andrea&lt;/a&gt; (anche se lui dice di no &lt;img alt="" src="/Providers/BlogEntryEditor/FCKeditor/editor/images/smiley/msn/teeth_smile.gif" /&gt;).&lt;br /&gt;
&lt;br /&gt;
Un tool che assiste la pratica del Continuos Integration è &lt;a title="Cruise Control .NET" href="http://ccnet.thoughtworks.com/"&gt;Cruise Control .NET&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Matteo Migliore.&lt;/p&gt;&lt;img src="http://blogs.ugidotnet.org/matteomigliore/aggbug/90671.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Matteo Migliore</dc:creator>
            <guid>http://blogs.ugidotnet.org/matteomigliore/archive/2008/01/12/tip-versioning-degli-assembly-di-una-stessa-solution.aspx</guid>
            <pubDate>Sat, 12 Jan 2008 21:43:42 GMT</pubDate>
            <wfw:comment>http://blogs.ugidotnet.org/matteomigliore/comments/90671.aspx</wfw:comment>
            <comments>http://blogs.ugidotnet.org/matteomigliore/archive/2008/01/12/tip-versioning-degli-assembly-di-una-stessa-solution.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/matteomigliore/comments/commentRss/90671.aspx</wfw:commentRss>
        </item>
    </channel>
</rss>
