Pattern Dappertutto http://blogs.ugidotnet.org/adrian/category/Pattern Dappertutto.aspx Pattern Dappertutto it-IT Adrian Florea Subtext Version 2.6.0.0 MVC versus Document/View in MFC http://blogs.ugidotnet.org/adrian/archive/2009/04/03/mvc-versus-documentview-in-mfc.aspx <p>Sto leggendo il bellissimo libro di <a href="http://blogs.ugidotnet.org/dinoes/">Dino</a> &amp; <a href="http://blogs.ugidotnet.org/pape/">Andrea</a>, "<a href="http://www.amazon.com/Microsoft%C2%AE-NET-Architecting-Applications-PRO-Developer/dp/073562609X/">Microsoft .NET: Architecting Applications for the Enterprise</a>" e mi ha incuriosito questa loro osservazione alla pagina 362: "[...] <em>Microsoft Foundation Classes (MFC) offered more than a decade ago an architecture with some points in common with MVC - particularly, the Document/View (DV) model. DV can be seen as a version of MVC where the view and controller are fused together. </em><strong>We really don't know whether the MFC team intentionally discarded MVC to embrace DV</strong><em>; our feeling, however, is that DV blossomed autonomously during the design by simply applying correctly and diffusely the SoC principle</em>".</p> <p><a href="http://www2.roguewave.com/support/developer/WinResources/mvc.cfm">Sembra</a> che alla PDC del 1995, un membro del team di MFC abbia raccontato proprio la storia del "<em>MVC versus DV</em>" nella scelta architetturale di MFC: "[...] <em>for the controller’s message mapping mechanism, can’t we just reuse MFC’s message map solution? Ideally, yes. But there is one big problem here... A separate controller class for message handlers may sound like a good idea, but MFC was designed in such a way that this was thought impossible. MFC allows commands such as menu picks to be rerouted to non-windows, but not windows messages such as mouse clicks. In MFC, only a CWnd can receive windows messages and only one instance of a CWnd can receive the messages for a real Windows window. Since a controller is meant to be a non-window that can handle windows messages and exist in multiple instances per window, we seem to be stuck! An interesting aside, this problem was sited by an original MFC team member as </em><strong>the main reason Microsoft emulated MVC for the CDocument and CView, but stopped short of implementing a controller</strong><em> (MFC Professional Developers Conference, 1995)</em>". Interessante...</p><img src="http://blogs.ugidotnet.org/adrian/aggbug/95872.aspx" width="1" height="1" /> Adrian Florea http://blogs.ugidotnet.org/adrian/archive/2009/04/03/mvc-versus-documentview-in-mfc.aspx Fri, 03 Apr 2009 22:18:48 GMT http://blogs.ugidotnet.org/adrian/archive/2009/04/03/mvc-versus-documentview-in-mfc.aspx#feedback 271 http://blogs.ugidotnet.org/adrian/comments/commentRss/95872.aspx http://blogs.ugidotnet.org/adrian/services/trackbacks/95872.aspx Lazy loading in una riga http://blogs.ugidotnet.org/adrian/archive/2008/05/28/lazy-loading-in-una-riga.aspx <p>Carino <a href="http://realfiction.net/?q=node/157">questo</a> modo proposto da <a href="http://realfiction.net/">Frank Quednau</a> di <a href="http://blogs.ugidotnet.org/Markino/archive/2006/01/05/32476.aspx">implementare il lazy loading</a> utilizzando l'operatore di null coalescing (ECMA-334, 14.12) e il fatto che <em>il risultato</em> di un'assegnazione e' il valore assegnato all'operando sinistro (ECMA-334, 14.14.1):</p> <p><strong>internal sealed class</strong> PersonProxy : Person<br /> {<br />     <strong>public override</strong> AddressCollection Addresses<br />     {<br />         <strong>get</strong><br />         {<br />             <strong>return base</strong>.Addresses ?? (<strong>base</strong>.Addresses = <strong>new</strong> PersonDataMapper().GetAddressesByCode(<strong>this</strong>.Code));<br />         }<br />         <strong>set</strong><br />         {<br />             <strong>base</strong>.Addresses = <strong>value</strong>;<br />         }<br />     }<br /> }</p> <p>A me sembra molto espressivo.</p><img src="http://blogs.ugidotnet.org/adrian/aggbug/92860.aspx" width="1" height="1" /> Adrian Florea http://blogs.ugidotnet.org/adrian/archive/2008/05/28/lazy-loading-in-una-riga.aspx Wed, 28 May 2008 23:04:38 GMT http://blogs.ugidotnet.org/adrian/archive/2008/05/28/lazy-loading-in-una-riga.aspx#feedback 108 http://blogs.ugidotnet.org/adrian/comments/commentRss/92860.aspx http://blogs.ugidotnet.org/adrian/services/trackbacks/92860.aspx Best practice Path.Combine http://blogs.ugidotnet.org/adrian/archive/2008/05/04/best-practice-path.combine.aspx <p>Se vogliamo che il nostro codice giri anche su Mono, dobbiamo utilizzare:</p> <p>Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "aaa.bbb")</p> <p>al posto di:</p> <p>AppDomain.CurrentDomain.BaseDirectory + "aaa.bbb"</p> <p>perche' su Mono, <em>BaseDirectory</em> ritorna una stringa che non finisce in <em>Path.DirectorySeparatorChar</em>, mentre su CLR si'. E questo va anche in generale, quando costruiamo il path da piu' pezzi, non solo nel caso della <em>BaseDirectory</em>. Per esempio, chi utilizza <a href="http://www.fyireporting.com/">fyiReporting RDL Project</a> su Mono, dovrebbe modificare la riga 81 nel file Runtime/RdlEngineConfig.cs nei sorgenti del progetto e ricompilare, da:</p> <p>file = dir + "RdlEngineConfig.xml";</p> <p>a:</p> <p>file = Path.Combine(dir, "RdlEngineConfig.xml");</p> <p>perche' la stringa <em>dir</em>, per come e' stata costruita, su CLR finisce in <em>Path.DirectorySeparatorChar</em>, mentre su Mono no. In <a href="http://www.amazon.com/Framework-Standard-Library-Annotated-Reference/dp/0321154894/">SLAR 1</a> alla pagina 360, <a href="http://joelmarcey.com/">Joel Marcey</a> aggiunge questa nota sulla storia del metodo <em>Combine</em>:</p> <blockquote><em>The</em> Combine <em>method had an interesting ride in the standardization process. It was originally part of the </em>Path <em>class, then removed because it was thought to be too platform-specific, then added back because it was decided it was not any more platform-specific than any of the other methods in this class.</em></blockquote><img src="http://blogs.ugidotnet.org/adrian/aggbug/92512.aspx" width="1" height="1" /> Adrian Florea http://blogs.ugidotnet.org/adrian/archive/2008/05/04/best-practice-path.combine.aspx Sun, 04 May 2008 22:44:32 GMT http://blogs.ugidotnet.org/adrian/archive/2008/05/04/best-practice-path.combine.aspx#feedback 95 http://blogs.ugidotnet.org/adrian/comments/commentRss/92512.aspx http://blogs.ugidotnet.org/adrian/services/trackbacks/92512.aspx Un'API generico a provider per i metadata dei vari ORM http://blogs.ugidotnet.org/adrian/archive/2008/05/03/unapi-generico-a-provider-per-i-metadata-dei-vari-orm.aspx <p>Via <a href="http://weblogs.asp.net/fbouma/archive/2008/05/01/dynamic-data-and-3rd-party-o-r-mappers-is-a-fact.aspx">questo post</a> di <a href="http://weblogs.asp.net/fbouma/">Frans Bouma</a> ho scoperto sotto il namespace <strong>System.Web.DynamicData.ModelProviders</strong> dell'assembly <strong>System.Web.DynamicData.dll</strong> che arriva con l'ultima release della preview di <a href="http://code.msdn.microsoft.com/dynamicdata">ASP.NET Dynamic Data</a>, un'API generico composto da 4 provider per i metadata dei vari ORM (non solo Microsoft): <strong>DataModelProvider</strong>, <strong>TableProvider</strong>, <strong>ColumnProvider</strong> ed <strong>AssociationProvider</strong>. Questo unifica in buona misura le varie API che espongono i metadata degli ORM, per esempio <strong>MetaTable</strong>, <strong>MetaDataMember</strong>, <strong>MetaAssociation</strong> nel caso di LINQ to SQL, oppure quella piu' complessa dell'Entity Framework: <strong>EntitySet</strong>, <strong>EdmMember</strong>, <strong>NavigationProperty</strong>, etc. Frans ha gia' scritto un <em>model provider</em> per il suo <a href="http://www.llblgen.com/">LLBLGen Pro</a>, sarebbe bellissimo averne uno anche per <a href="http://www.nhibernate.org/">NHibernate</a>. E poi mi piacerebbe in futuro vedere questa API staccata dal ASP.NET Dynamics Data con cui non dovrebbe avere tanto in comune.</p><img src="http://blogs.ugidotnet.org/adrian/aggbug/92497.aspx" width="1" height="1" /> Adrian Florea http://blogs.ugidotnet.org/adrian/archive/2008/05/03/unapi-generico-a-provider-per-i-metadata-dei-vari-orm.aspx Sat, 03 May 2008 02:53:11 GMT http://blogs.ugidotnet.org/adrian/archive/2008/05/03/unapi-generico-a-provider-per-i-metadata-dei-vari-orm.aspx#feedback 104 http://blogs.ugidotnet.org/adrian/comments/commentRss/92497.aspx http://blogs.ugidotnet.org/adrian/services/trackbacks/92497.aspx Il pattern Decorator e la decorazione con un extension method generico http://blogs.ugidotnet.org/adrian/archive/2007/11/29/90017.aspx <p>Stamattina, al corso che sto tenendo di architettura base, ho presentato ai ragazzi il classico pattern <em>Decorator</em> per servirci poi nell'implementare i vari servizi di validazione, logging, caching, etc., come decoratori di un repository, ispirato da <a href="http://www.ayende.com/Blog/archive/7598.aspx">questo post</a> di Ayende. Uno di loro mi ha chiesto se si poteva scrivere il corpo della <strong>CreateComponent</strong> in modo ancora piu' <em>usabile</em>. E mi e' venuta l'idea di utilizzare un extension method generico fluente, tanto per introdurli un po' anche nel mondo di C# 3.0</p> <p>Partiamo dall'implementazione standard del pattern:</p> <p><strong>using</strong> System;<br /> <br /> <strong>public</strong> <strong>interface</strong> IComponent {<br />     <strong>void</strong> Operation();<br /> }<br /> <br /> <strong>public</strong> <strong>class</strong> ConcreteComponent : IComponent {<br />     <strong>public</strong> <strong>void</strong> Operation() {<br />         Console.WriteLine("ConcreteComponent");<br />     }<br /> }<br /> <br /> <strong>public</strong> <strong>abstract</strong> <strong>class</strong> Decorator : IComponent {<br />     <strong>private</strong> <strong>readonly</strong> IComponent component;<br /> <br />     <strong>protected</strong> Decorator(IComponent component) {<br />         <strong>if</strong> (component == <strong>null</strong>) <strong>throw</strong> <strong>new</strong> ArgumentNullException("component");<br />         <strong>this</strong>.component = component;<br />     }<br /> <br />     <strong>public</strong> <strong>virtual</strong> <strong>void</strong> Operation() {<br />         <strong>this</strong>.component.Operation();<br />     }<br /> }<br /> <br /> <strong>public</strong> <strong>class</strong> ConcreteDecoratorA : Decorator {<br />     <strong>public</strong> ConcreteDecoratorA(IComponent component) : <strong>base</strong>(component) { }<br /> <br />     <strong>public</strong> <strong>override</strong> <strong>void</strong> Operation() {<br />         Console.WriteLine("ConcreteDecoratorA");<br />         <strong>base</strong>.Operation();<br />     }<br /> }<br /> <br /> <strong>public</strong> <strong>class</strong> ConcreteDecoratorB : Decorator {<br />     <strong>public</strong> ConcreteDecoratorB(IComponent component) : <strong>base</strong>(component) { }<br /> <br />     <strong>public</strong> <strong>override</strong> <strong>void</strong> Operation() {<br />         Console.WriteLine("ConcreteDecoratorB");<br />         <strong>base</strong>.Operation();<br />     }<br /> }<br /> <br /> <strong>class</strong> Program {<br />     <strong>public</strong> <strong>static</strong> IComponent CreateComponent() {<br />         <font color="#ff0000"><strong>return</strong> <br />             <strong>new</strong> ConcreteDecoratorB(<br />             <strong>new</strong> ConcreteDecoratorA(<br />             <strong>new</strong> ConcreteComponent()));</font><br />     }<br /> <br />     <strong>static</strong> <strong>void</strong> Main() {<br />         IComponent component = CreateComponent();<br />         component.Operation();<br />     }<br /> }</p> <p>Questo snippet quindi stampa:</p> <p>ConcreteDecoratorB<br /> ConcreteDecoratorA<br /> ConcreteComponent</p> <p>a console. L'idea per modificare il metodo <strong>CreateComponent</strong> e' semplice: se definiamo una classe statica <strong>ComponentExtension</strong> contenente un'extension method generico come di seguito:</p> <p><strong>public</strong> <strong>static</strong> <strong>class</strong> ComponentExtension {<br />     <strong>public</strong> <strong>static</strong> Decorator DecorateWith&lt;T&gt;(<strong>this</strong> IComponent component) <strong>where</strong> T : Decorator {<br />         <strong>return</strong> (T)Activator.CreateInstance(<strong>typeof</strong>(T), component);<br />     }<br /> }</p> <p>il metodo <strong>CreateComponent</strong> diventa:</p> <p><strong>public</strong> <strong>static</strong> IComponent CreateComponent() {<br />     <font color="#ff0000"><strong>return</strong> <strong>new</strong> ConcreteComponent()<br />             .DecorateWith&lt;ConcreteDecoratorA&gt;()<br />             .DecorateWith&lt;ConcreteDecoratorB&gt;();</font><br /> }</p> <p>che, a mio parere, e' piu' espressivo. Che ne dite?</p><img src="http://blogs.ugidotnet.org/adrian/aggbug/90017.aspx" width="1" height="1" /> Adrian Florea http://blogs.ugidotnet.org/adrian/archive/2007/11/29/90017.aspx Thu, 29 Nov 2007 03:47:56 GMT http://blogs.ugidotnet.org/adrian/archive/2007/11/29/90017.aspx#feedback 121 http://blogs.ugidotnet.org/adrian/comments/commentRss/90017.aspx http://blogs.ugidotnet.org/adrian/services/trackbacks/90017.aspx Collecting Parameter e Fluent Interface - due pattern simmetrici http://blogs.ugidotnet.org/adrian/archive/2007/10/30/89297.aspx <p>Ho notato oggi delle simmetrie tra questi due pattern: il pattern di refactoring, <a href="http://www.industriallogic.com/xp/refactoring/accumulationToCollection.html">CollectingParameter</a>, che accumula informazioni nell'istanza del parametro (<strong>input</strong>) e il pattern <a href="http://martinfowler.com/bliki/FluentInterface.html">FluentInterface</a>, che accumula informazioni nel valore di ritorno (<strong>output</strong>). Il tipo del parametro e' <strong>diverso</strong> dal tipo che contiene i metodi nel <em>CollectingParameter</em>, mentre il tipo del valore di ritorno e <strong>identico</strong> al tipo che contiene i metodi nel <em>FluentInterface</em>.</p> <p>Esempi di altre simmetrie nei pattern trovate nel nostro <a href="http://wiki.ugidotnet.org/default.aspx/UGIdotNETWiki/DesignPatternSimmetrici.html">wiki</a>, raccolti da <a href="http://blogs.ugidotnet.org/luKa/">Luca</a>.</p><img src="http://blogs.ugidotnet.org/adrian/aggbug/89297.aspx" width="1" height="1" /> Adrian Florea http://blogs.ugidotnet.org/adrian/archive/2007/10/30/89297.aspx Tue, 30 Oct 2007 00:52:01 GMT http://blogs.ugidotnet.org/adrian/archive/2007/10/30/89297.aspx#feedback 20 http://blogs.ugidotnet.org/adrian/comments/commentRss/89297.aspx http://blogs.ugidotnet.org/adrian/services/trackbacks/89297.aspx Un modo di marcare il valore di default di un enum http://blogs.ugidotnet.org/adrian/archive/2007/07/28/86906.aspx <P>"<I>Do provide a value of zero on simple enums</I>" dice una linea guida del <A href="http://www.amazon.com/Framework-Design-Guidelines-Conventions-Development/dp/0321246756/">FDG</A> (p. 95). Ma forse sarebbe ancora piu' espressivo <I>marcare</I> questo valore di default di un enum appunto come una <I>default value expression</I> (<A href="http://www.ecma-international.org/publications/standards/Ecma-334.htm">ECMA-334</A>, 14.5.14) anziche' impostarlo a 0. Cioe', scrivere:</P> <P><STRONG>public enum</STRONG> Compression<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;None = (<STRONG>int</STRONG>)<STRONG>default</STRONG>(Compression),<BR>&nbsp;&nbsp;&nbsp;&nbsp;GZip,<BR>&nbsp;&nbsp;&nbsp;&nbsp;Deflate<BR>}</P> <P>al posto di None = 0. In ogni caso, il compilatore genera lo stesso IL. E' solo un'idea, che ne dite?</P><img src="http://blogs.ugidotnet.org/adrian/aggbug/86906.aspx" width="1" height="1" /> Adrian Florea http://blogs.ugidotnet.org/adrian/archive/2007/07/28/86906.aspx Sat, 28 Jul 2007 20:12:00 GMT http://blogs.ugidotnet.org/adrian/archive/2007/07/28/86906.aspx#feedback 29 http://blogs.ugidotnet.org/adrian/comments/commentRss/86906.aspx http://blogs.ugidotnet.org/adrian/services/trackbacks/86906.aspx EqualsDefault e l'Equals statico della System.Object http://blogs.ugidotnet.org/adrian/archive/2006/10/29/53236.aspx <P>A volte, un umile metodo come l'<B>Equals</B> statico della classe <B>System.Object</B> pu&#242; rendersi sorprendentemente utile. Per esempio, in una classe generica in cui il type parameter T pu&#242; essere sia una <B>class</B> che una <B>struct</B>, abbiamo la necessit&#224; di controllare che un'istanza di T sia <B>default</B>(T).</P> <P><B>class</B> Foo&lt;T&gt; { <B>public bool</B> EqualsDefault(T t) { /* ? */ } } </P> <P>Senza l'<B>Equals</B> statico le soluzioni sono abbastanza bruttine:</P> <UL> <LI>non possiamo avere t == <B>null</B> perch&#233; T pu&#242; essere una <B>struct</B>; </LI> <LI>non possiamo avere t == <B>default</B>(T) per l'errore <B>CS0019</B> ("<I>Operator '</I>==<I>' cannot be applied to operands of type '</I>T<I>' and '</I>T<I>'</I>"); </LI> <LI>non possiamo avere t.<B>Equals</B>(<B>default</B>(T)) perch&#233; se t &#232; <B>null</B>, abbiamo <B>NullReferenceException</B>.</LI></UL> <P>Utilizzando&nbsp;l'<STRONG>Equals</STRONG> statico invece, la soluzione&nbsp;diventa&nbsp;banale:</P> <P><B>return object.Equals</B>(t, <B>default</B>(T));</P><img src="http://blogs.ugidotnet.org/adrian/aggbug/53236.aspx" width="1" height="1" /> Adrian Florea http://blogs.ugidotnet.org/adrian/archive/2006/10/29/53236.aspx Sun, 29 Oct 2006 13:24:00 GMT http://blogs.ugidotnet.org/adrian/archive/2006/10/29/53236.aspx#feedback 3 http://blogs.ugidotnet.org/adrian/comments/commentRss/53236.aspx http://blogs.ugidotnet.org/adrian/services/trackbacks/53236.aspx [GUISA] Generic Special Case? http://blogs.ugidotnet.org/adrian/archive/2006/10/27/53186.aspx <A href="http://guisa.it/forums/thread/148.aspx">Un altro thread</A> sul forum di GUISA, partendo da una <A href="http://blogs.ugidotnet.org/janky/archive/2006/10/09/50571.aspx">frase di Janky</A>. Solo un invito a trovare una soluzione insieme...<img src="http://blogs.ugidotnet.org/adrian/aggbug/53186.aspx" width="1" height="1" /> Adrian Florea http://blogs.ugidotnet.org/adrian/archive/2006/10/27/53186.aspx Fri, 27 Oct 2006 20:10:00 GMT http://blogs.ugidotnet.org/adrian/archive/2006/10/27/53186.aspx#feedback 29 http://blogs.ugidotnet.org/adrian/comments/commentRss/53186.aspx http://blogs.ugidotnet.org/adrian/services/trackbacks/53186.aspx [GUISA] Enumerable State Machine http://blogs.ugidotnet.org/adrian/archive/2006/10/26/52943.aspx Sul forum di <A href="http://guisa.it/">GUISA</A> ho postato <A href="http://guisa.it/forums/thread/136.aspx">qui</A> un'implementazione del pattern State sfruttando la macchina a stati generata dal compilatore C# 2.0 per un iteratore generico. L'idea mi &#232; venuta per gioco, diciamo che per adesso potrebbe essere interessante soprattutto per quelli che vogliono capire gli iteratori generici, non necessariamente come implementazione "seria" del pattern State.<img src="http://blogs.ugidotnet.org/adrian/aggbug/52943.aspx" width="1" height="1" /> Adrian Florea http://blogs.ugidotnet.org/adrian/archive/2006/10/26/52943.aspx Thu, 26 Oct 2006 13:56:00 GMT http://blogs.ugidotnet.org/adrian/archive/2006/10/26/52943.aspx#feedback 30 http://blogs.ugidotnet.org/adrian/comments/commentRss/52943.aspx http://blogs.ugidotnet.org/adrian/services/trackbacks/52943.aspx