naighes.NET - il blog di Nicola Baldi http://blogs.ugidotnet.org/naighes/Default.aspx ILazyTopic&lt;T&gt; where T : IDotNet it-IT Nicola Baldi Subtext Version 2.6.0.0 naighes.NET - il blog di Nicola Baldi http://blogs.ugidotnet.org/images/RSS2Image.gif http://blogs.ugidotnet.org/naighes/Default.aspx 77 60 DotNetToscana e i buoni propositi per quest'anno http://blogs.ugidotnet.org/naighes/archive/2012/03/12/dotnettoscana-e-i-buoni-propositi-per-questanno.aspx <p>Con i ragazzi di <a href="http://www.dotnettoscana.org">DotNetToscana</a> abbiamo definito l'agenda (ambiziosa) per quest'anno e devo ammettere che le prospettive sono assolutamente incoraggianti. <br /> Gli eventi che abbiamo organizzato nell'anno precedente sono risultati, a nostro avviso, decisamente ben riusciti; alcuni di essi potrei definirli addirittura "coraggiosi"... </p> <p> Il 17 Marzo toccherà al <a href="http://www.dotnettoscana.org/wp7-3d-lab.aspx">WP7 3D Game Lab</a>, mentre il 19 di Aprile sarà la volta di <a href="http://www.dotnettoscana.org/start-something-tour-windows-8-e-windows-phone-75.aspx">Start Something! Tour – Windows 8 e Windows Phone 7.5</a>, quest'ultimo con la gentilissima partecipazione di <a href="http://www.geniodelmale.info/">Lorenzo</a>. </p> <p> Come sempre, trattandosi di "laboratori", i posti sono piuttosto limitati. Chi è interessato farebbe quindi meglio ad iscriversi il prima possibile.</p> <p> A ruota seguiranno altre interessanti iniziative, ma al momento non me la sento di anticipare niente!</p><img src="http://blogs.ugidotnet.org/naighes/aggbug/100856.aspx" width="1" height="1" /> Nicola Baldi http://blogs.ugidotnet.org/naighes/archive/2012/03/12/dotnettoscana-e-i-buoni-propositi-per-questanno.aspx Mon, 12 Mar 2012 01:03:16 GMT http://blogs.ugidotnet.org/naighes/archive/2012/03/12/dotnettoscana-e-i-buoni-propositi-per-questanno.aspx#feedback 6 http://blogs.ugidotnet.org/naighes/comments/commentRss/100856.aspx http://blogs.ugidotnet.org/naighes/services/trackbacks/100856.aspx C# operator constraints http://blogs.ugidotnet.org/naighes/archive/2011/12/09/c-operator-constraints.aspx <!-- code formatted by http://manoli.net/csharpformat/ --> <style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: Consolas, "Courier New", Courier, Monospace; background-color: #ffffff; } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } ]]></style> <p>Avevo questo post in cantiere da qualche tempo, da quando un paio di miei colleghi mi hanno esternato le loro perplessità su un particolare behavior di C# compiler. <br /> Partiamo dal primo snippet:</p> <div class="csharpcode"> <pre><span class="lnum"> 1: </span>Boolean AreEqual&lt;T&gt;(T a, T b)</pre> <pre><span class="lnum"> 2: </span>{</pre> <pre><span class="lnum"> 3: </span> <span class="kwrd">return</span> a == b;</pre> <pre><span class="lnum"> 4: </span>}</pre> </div> <p>Si noterà subito che il codice in oggetto non compila. <br /> Limitandosi ad aggiungere il constraint "class", la compilazione va a buon fine.</p> <div class="csharpcode"> <pre><span class="lnum"> 1: </span>Boolean AreEqual&lt;T&gt;(T a, T b) <span class="kwrd">where</span> T : <span class="kwrd">class</span></pre> <pre><span class="lnum"> 2: </span>{</pre> <pre><span class="lnum"> 3: </span> <span class="kwrd">return</span> a == b;</pre> <pre><span class="lnum"> 4: </span>}</pre> </div> <p>Il motivo per il quale il primo snippet non viene compilato lo si può appurare consultando la <a href="http://msdn.microsoft.com/en-us/library/53k8ybth.aspx">documentazione MSDN</a> e, nello specifico: <br /> <em>"For predefined value types, the equality operator (==) returns true if the values of its operands are equal, false otherwise. For reference types other than string, == returns true if its two operands refer to the same object. For the string type, == compares the values of the strings"</em>.</p> <p>L'elemento sul quale dobbiamo spostare la nostra attenzione è ciò che la documentazione definisce come "predefined value type". <br /> Personalmente, trovo che qualche Unit Test rappresenti la soluzione migliore per chiarirsi e fissarsi questi concetti. Vediamo quindi di condurre qualche test con la struttura Int32.</p> <div class="csharpcode"> <pre><span class="lnum"> 1: </span>[TestMethod]</pre> <pre><span class="lnum"> 2: </span><span class="kwrd">public</span> Int32Equality()</pre> <pre><span class="lnum"> 3: </span>{</pre> <pre><span class="lnum"> 4: </span> var int1 = 2;</pre> <pre><span class="lnum"> 5: </span> var int2 = 2;</pre> <pre><span class="lnum"> 6: </span> Assert.AreEqual(int1, int2);</pre> <pre><span class="lnum"> 7: </span> Assert.IsTrue(int1 == int2);</pre> <pre><span class="lnum"> 8: </span>}</pre> </div> <p>Il test compila e passa e la domanda, a questo punto, è legittima, soprattutto se si osserva la struttura System.Int32 con uno strumento quale "Reflector". Si può notare, infatti, che la medesima non offre gli overload per l'operatore Equals. Nella sua "bibbia", Jeffrey Ritcher aggiunge una breve nota su tale questione: <br /> <em>Note If you examine the core numeric types (Int32, Int64, UInt32, and so on) in the Framework Class Library (FCL), you’ll see that they don’t define any operator overload methods. The reason they don’t is that compilers look specifically for operations on these primitive types and emit IL instructions that directly manipulate instances of these types. If the types were to offer methods and if compilers were to emit code to call these methods, a run-time performance cost would be associated with the method call. Plus, the method would ultimately have to execute some IL instructions to perform the expected operation anyway. This is the reason why the core FCL types don’t define any operator overload methods. Here’s what this means to you: If the programming language you’re using doesn’t support one of the core FCL types, you won’t be able to perform any operations on instances of that type</em>.</p> <p>Giusto per esercizio, cerchiamo conferma di tutto ciò definendo uno "User-defined value type", analizzandolo nel medesimo contesto.</p> <div class="csharpcode"> <pre><span class="lnum"> 1: </span><span class="kwrd">struct</span> NonPredefinedValueType : IEquatable&lt;NonPredefinedValueType&gt;</pre> <pre><span class="lnum"> 2: </span>{</pre> <pre><span class="lnum"> 3: </span> <span class="kwrd">public</span> Int32 SomeValue;</pre> <pre><span class="lnum"> 4: </span> </pre> <pre><span class="lnum"> 5: </span> <span class="kwrd">public</span> <span class="kwrd">override</span> Boolean Equals(Object obj)</pre> <pre><span class="lnum"> 6: </span> {</pre> <pre><span class="lnum"> 7: </span> <span class="kwrd">return</span> obj <span class="kwrd">is</span> NonPredefinedValueType</pre> <pre><span class="lnum"> 8: </span> ? Equals((NonPredefinedValueType) obj)</pre> <pre><span class="lnum"> 9: </span> : <span class="kwrd">base</span>.Equals(obj);</pre> <pre><span class="lnum"> 10: </span> }</pre> <pre><span class="lnum"> 11: </span> </pre> <pre><span class="lnum"> 12: </span> <span class="kwrd">public</span> Boolean Equals(NonPredefinedValueType other)</pre> <pre><span class="lnum"> 13: </span> {</pre> <pre><span class="lnum"> 14: </span> <span class="kwrd">return</span> other.SomeValue == SomeValue;</pre> <pre><span class="lnum"> 15: </span> }</pre> <pre><span class="lnum"> 16: </span> </pre> <pre><span class="lnum"> 17: </span> <span class="kwrd">public</span> <span class="kwrd">override</span> Int32 GetHashCode()</pre> <pre><span class="lnum"> 18: </span> {</pre> <pre><span class="lnum"> 19: </span> <span class="kwrd">return</span> SomeValue;</pre> <pre><span class="lnum"> 20: </span> }</pre> <pre><span class="lnum"> 21: </span>}</pre> </div> <p>Scriviamo dunque il test:</p> <div class="csharpcode"> <pre><span class="lnum"> 1: </span>[TestMethod]</pre> <pre><span class="lnum"> 2: </span><span class="kwrd">public</span> NonPredefinedValueTypeEquality()</pre> <pre><span class="lnum"> 3: </span>{</pre> <pre><span class="lnum"> 4: </span> var value1 = <span class="kwrd">new</span> NonPredefinedValueType { SomeValue = 2 };</pre> <pre><span class="lnum"> 5: </span> var value2 = <span class="kwrd">new</span> NonPredefinedValueType { SomeValue = 2 };</pre> <pre><span class="lnum"> 6: </span> Assert.AreEqual(value1, value2);</pre> <pre><span class="lnum"> 7: </span> Assert.IsTrue(value1 == value2);</pre> <pre><span class="lnum"> 8: </span>}</pre> </div> <p>Come si può notare, l'ultimo statement non compila, indicando che non è possibile applicare l'operatore "==" tra i due operandi. Alla luce di quanto emerso in precedenza, questo errore non dovrebbe coglierci di sorpresa. Difatti, stiamo operando con una struttura non-primitiva e, come si è visto, non abbiamo a disposizione alcun overload di operatore "preconfezionato". <br /> Proviamo quindi ad aggiungere alla nostra struttura l'overload per l'operatore "==":</p> <div class="csharpcode"> <pre><span class="lnum"> 1: </span><span class="kwrd">struct</span> NonPredefinedValueType : IEquatable&lt;NonPredefinedValueType&gt;</pre> <pre><span class="lnum"> 2: </span>{</pre> <pre><span class="lnum"> 3: </span> <span class="kwrd">public</span> Int32 SomeValue;</pre> <pre><span class="lnum"> 4: </span> </pre> <pre><span class="lnum"> 5: </span> <span class="kwrd">public</span> <span class="kwrd">override</span> Boolean Equals(Object obj)</pre> <pre><span class="lnum"> 6: </span> {</pre> <pre><span class="lnum"> 7: </span> <span class="kwrd">return</span> obj <span class="kwrd">is</span> NonPredefinedValueType</pre> <pre><span class="lnum"> 8: </span> ? Equals((NonPredefinedValueType) obj)</pre> <pre><span class="lnum"> 9: </span> : <span class="kwrd">base</span>.Equals(obj);</pre> <pre><span class="lnum"> 10: </span> }</pre> <pre><span class="lnum"> 11: </span> </pre> <pre><span class="lnum"> 12: </span> <span class="kwrd">public</span> Boolean Equals(NonPredefinedValueType other)</pre> <pre><span class="lnum"> 13: </span> {</pre> <pre><span class="lnum"> 14: </span> <span class="kwrd">return</span> other.SomeValue == SomeValue;</pre> <pre><span class="lnum"> 15: </span> }</pre> <pre><span class="lnum"> 16: </span> </pre> <pre><span class="lnum"> 17: </span> <span class="kwrd">public</span> <span class="kwrd">override</span> Int32 GetHashCode()</pre> <pre><span class="lnum"> 18: </span> {</pre> <pre><span class="lnum"> 19: </span> <span class="kwrd">return</span> SomeValue;</pre> <pre><span class="lnum"> 20: </span> }</pre> <pre><span class="lnum"> 21: </span> </pre> <pre><span class="lnum"> 22: </span> <span class="kwrd">public</span> <span class="kwrd">static</span> Boolean <span class="kwrd">operator</span> ==(NonPredefinedValueType a, NonPredefinedValueType b)</pre> <pre><span class="lnum"> 23: </span> {</pre> <pre><span class="lnum"> 24: </span> <span class="kwrd">return</span> a.Equals(b);</pre> <pre><span class="lnum"> 25: </span> }</pre> <pre><span class="lnum"> 26: </span> </pre> <pre><span class="lnum"> 27: </span> <span class="kwrd">public</span> <span class="kwrd">static</span> Boolean <span class="kwrd">operator</span> !=(NonPredefinedValueType a, NonPredefinedValueType b)</pre> <pre><span class="lnum"> 28: </span> {</pre> <pre><span class="lnum"> 29: </span> <span class="kwrd">return</span> !(a == b);</pre> <pre><span class="lnum"> 30: </span> }</pre> <pre><span class="lnum"> 31: </span>}</pre> </div> <p>Come si può notare, il test questa volta compila e passa.</p> <div class="csharpcode"> <pre><span class="lnum"> 1: </span>[TestMethod]</pre> <pre><span class="lnum"> 2: </span><span class="kwrd">public</span> <span class="kwrd">void</span> NonPredefinedValueTypeEquality()</pre> <pre><span class="lnum"> 3: </span>{</pre> <pre><span class="lnum"> 4: </span> var value1 = <span class="kwrd">new</span> NonPredefinedValueType { SomeValue = 2 };</pre> <pre><span class="lnum"> 5: </span> var value2 = <span class="kwrd">new</span> NonPredefinedValueType { SomeValue = 2 };</pre> <pre><span class="lnum"> 6: </span> var value3 = <span class="kwrd">new</span> NonPredefinedValueType { SomeValue = 3 };</pre> <pre><span class="lnum"> 7: </span> Assert.AreEqual(value1, value2);</pre> <pre><span class="lnum"> 8: </span> Assert.AreNotEqual(value1, value3);</pre> <pre><span class="lnum"> 9: </span> Assert.IsTrue(value1 == value2);</pre> <pre><span class="lnum"> 10: </span> Assert.IsTrue(value1 != value3);</pre> <pre><span class="lnum"> 11: </span>}</pre> </div> <p>Ok, niente di così trascendentale, ma eseguiamo una callback al primo snippet e chiediamoci se è possibile, in qualche modo, evitare il constraint a "class" senza rinunciare ai generics. Beh, la prima idea che ti può venire in mente è che il ricorso a DLR "sposti" il problema dalla fase di compilazione a quella di runtime. In sostanza:</p> <div class="csharpcode"> <pre><span class="lnum"> 1: </span>Boolean AreEqual&lt;T&gt;(T a, T b)</pre> <pre><span class="lnum"> 2: </span>{</pre> <pre><span class="lnum"> 3: </span> <span class="kwrd">return</span> (dynamic)a == b;</pre> <pre><span class="lnum"> 4: </span>}</pre> </div> <p>Ne ho discusso con i miei amici di <a href="http://www.dotnettoscana.org/">DotNetToscana</a> e i pareri sono piuttosto discordanti. Personalmente, trovo che il prezzo che si paga per garantire un maggior grado di astrazione in qualche contesto possa essere accettabile. Ma sono curioso di sentire altri pareri! :-)</p> <p> <strong>UPDATE:</strong> <br /> <a href="http://blogs.ugidotnet.org/spaccabit">Spaccabit</a> aggiunge un interessante elemento che ci porta ad ampliare ulteriormente la discussione. <br /> Sostanzialmente, a.Equals(b) va <u>sempre</u> a chiamare il metodo con la firma "Boolean Equals(Object obj)". Quindi, indipendentemente dal fatto che il tipo del parametro generico T implementi o meno IEquitable&lt;T&gt;, la chiamata va sempre al metodo in oggetto. <br /> A questo punto, c'è da dire che se il tipo è disegnato "male" ciò può rappresentare un problema piuttosto serio. <br /> Al contrario, "EqualityComparer&lt;T&gt;.Default.Equals(a, b)" verifica in prima istanza che T implementi IEquitable&lt;T&gt;. In tal caso, esegue l'implementazione di IEquitable&lt;T&gt;. <br /> Mi viene da dire, quindi, che "EqualityComparer&lt;T&gt;.Default.Equals(a, b)" possa fungere un pò da "salvagente", come giustamente fa notare <a href="http://blogs.ugidotnet.org/spaccabit">Spaccabit</a>. <br /> Quello che volevo aggiungere è che: </p><ul> <li>Se si vuole essere scrupolosissimi, EqualityComparer&lt;T&gt;.Default potremmo considerarla una dipendenza. Anche se, così su due piedi, direi proprio che si tratta proprio di cercare "il pelo nell'uovo".</li> <li> Il discorso che volevo fare aveva uno spettro leggermente pò più ampio. <br /> Ad esempio: <div class="csharpcode"> <pre><span class="lnum"> 1: </span><span class="kwrd">static</span> T Sum&lt;T&gt;(T a, T b)</pre> <pre><span class="lnum"> 2: </span>{</pre> <pre><span class="lnum"> 3: </span> <span class="kwrd">return</span> a + b;</pre> <pre><span class="lnum"> 4: </span>}</pre> </div></li> </ul><img src="http://blogs.ugidotnet.org/naighes/aggbug/100610.aspx" width="1" height="1" /> Nicola Baldi http://blogs.ugidotnet.org/naighes/archive/2011/12/09/c-operator-constraints.aspx Fri, 09 Dec 2011 11:59:19 GMT http://blogs.ugidotnet.org/naighes/archive/2011/12/09/c-operator-constraints.aspx#feedback 9 http://blogs.ugidotnet.org/naighes/comments/commentRss/100610.aspx http://blogs.ugidotnet.org/naighes/services/trackbacks/100610.aspx What's the state of object oriented programming? http://blogs.ugidotnet.org/naighes/archive/2011/11/18/whats-the-state-of-object-oriented-programming.aspx <p> Riprendo il <a href="http://blogs.ugidotnet.org/rgm/archive/2011/11/16/sono-realmente-object-oriented.aspx">post</a> di <a href="http://blogs.ugidotnet.org/rgm/">Gian Maria</a> per aggiungere qualche risorsa interessante. <br /> La prima, che mi ha segnalato <a href="http://blogs.ugidotnet.org/bmatte/Default.aspx">Matteo</a>, è un breve, ma significativo, contributo di Robert C. Martn. </p><ul> <li><em>Java, c++, c# are just <strong>interpretations</strong> of OO [...]</em></li> <li><em>I'm thinking <strong>dynamic polymorphism</strong>, that's really what OO is all about [...]</em></li> </ul> Ed ecco il link: <br /> <a href="http://cleancoder.posterous.com/oh-oh-what-is-it">Oh oh! What is it?</a> <p> C'è poi il contributo di Alan Kay: <br /> <a href="http://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay_oop_en">Dr. Alan Kay on the Meaning of "Object-Oriented Programming"</a> <br /> <em> OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things. <strong>It can be done in Smalltalk and in LISP</strong>. There are possibly other systems in which this is possible, but I'm not aware of them. </em> </p> <p> Infine, è la volta di <a href="http://www.davethomas.net/">Dave Thomas</a>: <br /> <a href="http://channel9.msdn.com/Blogs/Charles/SPLASH-2011-Dave-Thomas-On-Modern-Application-Development">Dave Thomas - On Modern Application Development</a> <br /> <em>What's the state of object oriented programming? Commercially imensely succesful but <strong>practical is a disaster</strong> since it is difficult for people to do abstractions</em> </p> <hr /> <p> <strong>Comunicazione di servizio</strong> <br /> I ragazzi di <a href="http://www.dotnettoscana.org/&quot;">dotnettoscana</a>, del cui staff ho l'onore di fare parte, non stanno certo dormendo sugli allori! <br /> Continua, difatti, la nostra "sperimentazione", che trova il suo naturale proseguimento con il <a href="http://www.dotnettoscana.org/1-coding-day.aspx">prossimo evento</a>. <br /> So già che avremo molto di cui discutere e... molto codice da scrivere! :-) </p><img src="http://blogs.ugidotnet.org/naighes/aggbug/100533.aspx" width="1" height="1" /> Nicola Baldi http://blogs.ugidotnet.org/naighes/archive/2011/11/18/whats-the-state-of-object-oriented-programming.aspx Fri, 18 Nov 2011 10:43:46 GMT http://blogs.ugidotnet.org/naighes/archive/2011/11/18/whats-the-state-of-object-oriented-programming.aspx#feedback 6 http://blogs.ugidotnet.org/naighes/comments/commentRss/100533.aspx http://blogs.ugidotnet.org/naighes/services/trackbacks/100533.aspx Cross-cutting concerns and Microsoft guidelines http://blogs.ugidotnet.org/naighes/archive/2011/07/08/cross-cutting-concerns-and-microsoft-guidelines.aspx "MSDN Architecture Center"... un nome, una garanzia.<br /> Volevo solo segnalare che il solito <a href="http://ayende.com/blog">Ayende</a> ha pubblicato una serie di post su quelle che, secondo Microsoft, sono le best pratices nello sviluppo di una "Domain Oriented N-Layered App".<br /> I più coraggiosi, possono avventurarsi nella minuziosa review del celebre blogger.<br /> Per quello che mi riguarda, vi segnalo solo il passaggio sui Cross-cutting concerns, perchè davvero merita:<br /> <a href="http://ayende.com/blog/30721/review-microsoft-n-layer-app-sample-part-vndash-cross-cutting-is-a-fine-line">Cross Cutting is a fine line</a><br /> <br /> Vi lascio con una citazione dalla pagina principale di codeplex:<br /> <br /> <em>[...]Also, this sample <strong>goes along with our Architecture Guidance</strong>, and there are aspects in the guidance that are not covered by this sample, and viceversa.[...]</em> <br /> <br /> Che dite, ci dobbiamo preoccupare?<img src="http://blogs.ugidotnet.org/naighes/aggbug/100204.aspx" width="1" height="1" /> Nicola Baldi http://blogs.ugidotnet.org/naighes/archive/2011/07/08/cross-cutting-concerns-and-microsoft-guidelines.aspx Fri, 08 Jul 2011 00:05:12 GMT http://blogs.ugidotnet.org/naighes/archive/2011/07/08/cross-cutting-concerns-and-microsoft-guidelines.aspx#feedback 20 http://blogs.ugidotnet.org/naighes/comments/commentRss/100204.aspx http://blogs.ugidotnet.org/naighes/services/trackbacks/100204.aspx Microsoft compra Skype? http://blogs.ugidotnet.org/naighes/archive/2011/05/10/microsoft-compra-skype.aspx I rumors, a questo punto, sono sempre più assordanti.<br /> Per noi sviluppatori che dedichiamo risorse ad una piattaforma come Windows Phone 7, questa manovra potrebbe rappresentare un'autentica manna dal cielo.<br /> E' un pò quello di cui discutevo recentemente con i miei "colleghi" di <a href="http://www.dotnettoscana.org/">dotnettoscana</a>, ovvero che a WP7 serviva un "plus" che ne "giustificasse" l'acquisto. Ovviamente, gli sviluppatori Microsoft già da tempo si lasciano "cullare" dagli ozi della piattaforma di sviluppo basata su Silverlight/XNA, ma questo non era sufficiente a garantire la diffusione che questo dispositivo, a mio avviso, merita (gli ultimi dati di vendita sono piuttosto imbarazzanti).<br /> Ecco, questa operazione potrebbe davvero rappresentare il definitivo "colpo di reni".<br /> <br /> A quanto sembra, dovrebbero ufficializzare la notizia entro un paio di giorni.<br /> Mi auguro che vada tutto in porto.<img src="http://blogs.ugidotnet.org/naighes/aggbug/100029.aspx" width="1" height="1" /> Nicola Baldi http://blogs.ugidotnet.org/naighes/archive/2011/05/10/microsoft-compra-skype.aspx Tue, 10 May 2011 15:10:09 GMT http://blogs.ugidotnet.org/naighes/archive/2011/05/10/microsoft-compra-skype.aspx#feedback 5 http://blogs.ugidotnet.org/naighes/comments/commentRss/100029.aspx http://blogs.ugidotnet.org/naighes/services/trackbacks/100029.aspx MVVM: is it always the right way? http://blogs.ugidotnet.org/naighes/archive/2011/04/07/mvvm-is-it-always-the-right-way.aspx In azienda abbiamo deciso di realizzare la nuova applicazione che ci hanno "committato" avvalendoci del pattern architetturale MVVM (o Presentation Model, o come diamine vogliate chiamarlo).<br /> Da tantissimo tempo, oramai, sviluppo le applicazioni web con MVC.<br /> Pensavo quindi che passare a MVVM sarebbe stato quasi "automatico".<br /> Ebbene, mi sbagliavo.<br /> Dopo una settimana trascorsa a discutere i dettagli con il mio collega Bruno ("come dici tu, non funzionerà mai..." ndBuyer :-P), siamo arrivati a manifestare i primi sintomi derivanti da frustrazione (insonnia, sguardo fisso nel vuoto, ecc).<br /> <br /> Insomma, la mia esperienza, seppur breve, è piuttosto negativa.<br /> Attenzione, non voglio dire che si tratti di un approccio non valido. Tutt'altro...<br /> Sono fermamente convinto che sia la strada giusta da percorrere, ma ci sono ancora, sempre a mio avviso, degli aspetti oscuri, da valutare con attenzione.<br /> <br /> Proprio ieri sera, mi è capitata sottomano una dicsussione risalente ad un pò di tempo fa.<br /> <br /> <a href="http://forums.silverlight.net/forums/t/127825.aspx">MVVM, an Overcomplication or Incorrectly Used?</a><br /> <br /> E' piuttosto lunga, ma vi assicuro che vale la pena leggerla.<br /> Credo di aver maturato qualche certezza in più.<br /> Nel corso della progettazione e dello sviluppo, ho intenzione di scrivere qualche post che descriva quello che è stato il nostro approccio alle problematiche che si ponevano di fronte a noi.<br /> <br /> Alla prossima.<img src="http://blogs.ugidotnet.org/naighes/aggbug/99920.aspx" width="1" height="1" /> Nicola Baldi http://blogs.ugidotnet.org/naighes/archive/2011/04/07/mvvm-is-it-always-the-right-way.aspx Thu, 07 Apr 2011 12:42:55 GMT http://blogs.ugidotnet.org/naighes/archive/2011/04/07/mvvm-is-it-always-the-right-way.aspx#feedback 21 http://blogs.ugidotnet.org/naighes/comments/commentRss/99920.aspx http://blogs.ugidotnet.org/naighes/services/trackbacks/99920.aspx EL5: una dipendenza inutile http://blogs.ugidotnet.org/naighes/archive/2011/03/23/el5-una-dipendenza-inutile.aspx Ok, visto che sono quì, non vedo perchè dovrei privarmi del piacere di bloggare ancora per un pò.<br /> A dire il vero, mi piacerebbe scrivere qualcosa su MEF, che ho cominciato a scoprire da poco e del quale mi sonosubito innamorato. In realtà, per motivi di tempo, mi voglio limitare a segnalare quella che, a mio avviso, è una piccola anomalia che ho riscontrato in Enterprise Library.<br /> Sto seguendo un progetto piuttosto interessante e diciamo pure che ho accolto da subito con entusiasmo la sfida che mi è stata proposta.<br /> Il problema è che mi trovo a che fare con dei database legacy della peggior specie. Anzi, devo chiaramente dire che è la peggior infrastruttura con la quale abbia mai avuto a che fare.<br /> Sono innegabilmente un fan di NHibernate e la mia prima idea è stata quella di avvalermi di tale strumento per cercare di rendermi la vita un pò più semplice.<br /> Niente da fare. E' probabile che ciò sia in qualche modo frutto della mia scarsa esperienza con il software legacy, ma applicare anche una primitiva forma di O/R Mapping a ciò che ho fra le mani è, secondo la mia modestissima opinione, una "Mission Impossible" per chiunque.<br /> Mi sono quindi chiesto se non fosse il caso di utilizzare il Data Access Block di EL, giusto per alleviare un pò il dolore. E devo dire che l'impresa è riuscita egregiamente.<br /> Mentre eseguivo i test, però, mi sono trovato a che fare con un'eccezione all'interno della quale mi veniva segnalato che, sostanzialmente, il componente in oggetto necessitava dell'assembly "Microsoft.Practices.Unity".<br /> E perchè mai dovrei aggiungere un riferimento ad un componente come "Unity" se, ad esempio, risolvo le mie dipendenze con Castle Windsor?<br /> Mi è sembrato tutto molto illogico.<br /> L'analisi dello stack chiamava chiaramente in causa il costruttore di Microsoft.Practices.EnterpriseLibrary.Data.RefCountingDataReader.<br /> Ecco cosa viene fuori dai sorgenti: <br /> <br /> <!-- code formatted by http://manoli.net/csharpformat/ --> <pre class="csharpcode"><span class="kwrd">public</span> RefCountingDataReader(DatabaseConnectionWrapper connection, IDataReader innerReader) : <span class="kwrd">base</span>(innerReader)<br />{<br /> Guard.ArgumentNotNull(connection, <span class="str">"connection"</span>);<br /> Guard.ArgumentNotNull(innerReader, <span class="str">"innerReader"</span>);<br /> <span class="kwrd">this</span>.connectionWrapper = connection;<br /> <span class="kwrd">this</span>.connectionWrapper.AddRef();<br />}</pre> <br /> <br /> Ebbene, Guard è una classe (tra l'altro, pubblica) definita all'interno dell'assembly "Microsoft.Practices.Unity".<br /> Perchè è stata compiuta questa scelta?<br /> Non potevano, ad esempio, definirla all'interno di un assembly come, non so, "Microsoft.Practices.EnterpriseLibrary.Common"?<br /> Insomma, stiamo parlando di una classe statica buttata nel mezzo senza il benchè minimo criterio.<br /> C'è forse qualcuno che conviene con il sottoscritto?<img src="http://blogs.ugidotnet.org/naighes/aggbug/99862.aspx" width="1" height="1" /> Nicola Baldi http://blogs.ugidotnet.org/naighes/archive/2011/03/23/el5-una-dipendenza-inutile.aspx Wed, 23 Mar 2011 00:10:56 GMT http://blogs.ugidotnet.org/naighes/archive/2011/03/23/el5-una-dipendenza-inutile.aspx#feedback 7 http://blogs.ugidotnet.org/naighes/comments/commentRss/99862.aspx http://blogs.ugidotnet.org/naighes/services/trackbacks/99862.aspx RG .NET Reflector http://blogs.ugidotnet.org/naighes/archive/2011/03/21/rg-.net-reflector.aspx Come vedete, non ho molto tempo per bloggare.<br /> Oggi, però, un'eccezione devo pur concedermela.<br /> Sono infatti venuto a conoscenza che .NET Reflector non è più uno strumento gratuito.<br /> L'annuncio lo trovate <a href="http://reflector.red-gate.com/download.aspx?TreatAsUpdate=1">quì</a>.<br /> <br /> Onestamente, ci sono rimasto male e la natura del mio malessere non deriva certo da quei 35 dollari.<br /> Io  a colpi di reflector ci sono cresciuto, e ammetto di dover molto a questo strumento.<br /> Proprio per questo motivo mi chiedo se non vi fossero effettivamente altre strade da percorrere.<br /> Insomma, a mio avviso non è stata una mossa molto trasparente.<br /> <br /> Ovviamente, è subito pronta l'alternativa (<a href="http://wiki.sharpdevelop.net/ilspy.ashx">ILSpy</a>).<img src="http://blogs.ugidotnet.org/naighes/aggbug/99858.aspx" width="1" height="1" /> Nicola Baldi http://blogs.ugidotnet.org/naighes/archive/2011/03/21/rg-.net-reflector.aspx Mon, 21 Mar 2011 16:14:33 GMT http://blogs.ugidotnet.org/naighes/archive/2011/03/21/rg-.net-reflector.aspx#feedback 12 http://blogs.ugidotnet.org/naighes/comments/commentRss/99858.aspx http://blogs.ugidotnet.org/naighes/services/trackbacks/99858.aspx Considerazioni su XNA 4.0 http://blogs.ugidotnet.org/naighes/archive/2010/10/21/considerazioni-su-xna-4.0.aspx A tempo perso, o meglio, nei pochi attimi di tempo libero che ho a disposizione, mi diverto con XNA.<br /> Saranno un paio di anni che tento di portare a termine un piccolo progettino e che spero vedrà la luce entro la fine dell'anno. Il punto è che nel corso di questo lasso di tempo si sono succeduti due rilasci per la piattaforma in questione e, ciascuno dei quali, diciamo pure che ha avuto un certo impatto. L'ultimo, poi, è stato semplicemente devastante.<br /> Tanto per essere chiari, compilare un vecchio progetto XNA con la versione 4.0 produce un numero di errori di compilazione tale da farti quasi tremare le gambe. I famigerati <span style="font-style: italic;">Breaking changes</span>, per intendersi.<br /> Premetto che con l'ultima release di XNA ci viene consegnata, finalmente, un'ottima piattaforma, ma una piccola riflessione dobbiamo comunque farla.<br /> Nel <a href="http://blogs.msdn.com/b/shawnhar/archive/2010/03/16/breaking-changes-in-xna-game-studio-4-0.aspx">post di Shawn Hargreaves</a> si fa riferimento al sentimento della comunità che l'autore del post ha riassunto con "<span style="font-style: italic;">If you break it, break it good</span>".<br /> Ecco, indipendentemente da quelle che sono le necessità che ti possono portare a tale conclusione, è proprio la condizione nella quale arrivi a trovarti il problema principale.<br /> Parliamoci chiaramente, senza troppi rigiri, XNA è stato affetto sin dall'inizio da alcune scelte di design quantomeno discutibili e trovo che sia proprio questo il motivo per il quale i breaking changes sono in numero così copioso.<br /> Le <span style="font-style: italic;">best pratice</span> non incoraggiano certo a perseguire strade di questo tipo e Microsoft stessa ricorre spesso all'attributo "Obsolete" al fine di garantire una certa retrocompatibilità (tendo a farlo anch'io, nei limiti del possibile).<br /> Certo, per quanto se ne dica, io resto sempre dell'idea che XNA, alla fine, rappresenti poco più che un wrapper su DirectX, ma questo non è sufficiente ad eludere un deficit di design che è apparso evidente a tutti.<br /> Leggevo qualche giorno fa un <a href="http://blogs.ugidotnet.org/pape/archive/2010/10/12/cavar-il-sangue-dalle-rape-siiiii-puograveograveograveograveogravehellip-faaareeeee.aspx">post di Andrea</a> (non vorrei mai essere suo nemico! :-)). Certo, ha ragione, niente da dire, ma cerchiamo di vedere, per una volta, anche il rovescio della medaglia, ovvero che alla prudenza deve essere riconosciuto comunque un certo valore. Al progetto XNA, magari è mancata proprio quest'ultima.<br /> Ora, non vorrei essere frainteso, perchè trovo che Shawn ed il suo gruppo abbiano fatto davvero un gran lavoro, e con una roadmap molto rigida in termini di tempistica, come lui stesso sembra ammettere.<br /> Comunque, e scadiamo nella retorica, tutto è bene quel che finisce bene!<br /> Forse, e dico "forse", qualche noia agli sviluppatori poteva essere evitata, con un pò più di avvedutezza.<br /> Tutto lì. :-P<img src="http://blogs.ugidotnet.org/naighes/aggbug/99375.aspx" width="1" height="1" /> Nicola Baldi http://blogs.ugidotnet.org/naighes/archive/2010/10/21/considerazioni-su-xna-4.0.aspx Thu, 21 Oct 2010 11:41:04 GMT http://blogs.ugidotnet.org/naighes/archive/2010/10/21/considerazioni-su-xna-4.0.aspx#feedback 9 http://blogs.ugidotnet.org/naighes/comments/commentRss/99375.aspx http://blogs.ugidotnet.org/naighes/services/trackbacks/99375.aspx Entity matching - sei sicuro? l'accendiamo? http://blogs.ugidotnet.org/naighes/archive/2010/10/04/entity-matching-sei-sicuro-laccendiamo.aspx Mi vergogno quasi ad ammetterlo, ma effettivamente non ci avevo mai pensato.<br /> Questo fine settimana ho navigato un pò in internet, al fine di trovare qualche idea per arricchire ulteriormente il Domain Model dell'applicazione alla quale sto lavorando e, in particolar modo, definire il più elegantemente possibile un criterio per la comparazione delle entità. La parte che, tendenzialmente, tenevo meno in considerazione era quella relativa all'hashing dell'istanza. Il punto è che, in linea del tutto teorica, il metodo GetHashCode per due tipi differenti può restituire il medesimo valore.<br /> <!-- code formatted by http://manoli.net/csharpformat/ --> <style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: Consolas, "Courier New", Courier, Monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } .csharpcode .type { color : #2B91AF; } ]]></style> <pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">override</span> <span class="type">Int32</span> GetHashCode()<br />{<br />    <span class="type">IEnumerable</span>&lt;<span class="type">PropertyInfo</span>&gt; signatureProperties = GetSignatureProperties();<br />    <span class="type">Int32</span> hashCode = GetType().GetHashCode();<br /><br />    <span class="kwrd">foreach</span> (<span class="type">PropertyInfo</span> property <span class="kwrd">in</span> signatureProperties)<br />    {<br />        <span class="type">Object</span> <span class="kwrd">value</span> = property.GetValue(<span class="kwrd">this</span>, <span class="kwrd">null</span>);<br /><br />        <span class="kwrd">if</span> (<span class="kwrd">value</span> != <span class="kwrd">null</span>)<br />            hashCode = hashCode ^ <span class="kwrd">value</span>.GetHashCode();<br />    }<br /><br />    <span class="kwrd">return</span> signatureProperties.Any() ? hashCode : <span class="kwrd">base</span>.GetHashCode();<br />}</pre> Il metodo GetSignatureProperties fornisce la collezione degli elementi a partire dai quali si determina l'hash.<br /> Quest'ultimo, per le considerazioni di cui sopra, deve tenere conto anche del tipo dell'oggetto.<br /> Insomma, io credo che la questione sia tutt'altro che banale, e questo <a title="Using Equals/GetHashCode Effectively" href="http://devlicio.us/blogs/billy_mccafferty/archive/2007/04/25/using-equals-gethashcode-effectively.aspx">post</a> rappresenta a mio avviso un'autentica miniera di best-pratices.<br /> Giusto a titolo di esempio, qualcuno si è mai posto il problema di valutare l'equivalenza tra una entity POCO e il suo proxy?<img src="http://blogs.ugidotnet.org/naighes/aggbug/99304.aspx" width="1" height="1" /> Nicola Baldi http://blogs.ugidotnet.org/naighes/archive/2010/10/04/entity-matching-sei-sicuro-laccendiamo.aspx Mon, 04 Oct 2010 10:44:10 GMT http://blogs.ugidotnet.org/naighes/archive/2010/10/04/entity-matching-sei-sicuro-laccendiamo.aspx#feedback 4 http://blogs.ugidotnet.org/naighes/comments/commentRss/99304.aspx http://blogs.ugidotnet.org/naighes/services/trackbacks/99304.aspx