<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://msmvps.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Angel "Java" Lopez : C Sharp, C Sharp.NET</title><link>http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/C+Sharp.NET/default.aspx</link><description>Tags: C Sharp, C Sharp.NET</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>Introducción a IoC y DI: Hello, world, flexible</title><link>http://msmvps.com/blogs/lopez/archive/2010/07/13/introducci-243-n-a-ioc-y-di-hello-world-flexible.aspx</link><pubDate>Tue, 13 Jul 2010 22:29:23 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1773878</guid><dc:creator>lopez</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1773878</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2010/07/13/introducci-243-n-a-ioc-y-di-hello-world-flexible.aspx#comments</comments><description>&lt;p&gt;Dentro del &lt;a href="http://msmvps.com/blogs/lopez/archive/2010/03/26/hogwarts_2D00_project.aspx" target="_blank"&gt;Proyecto Hogwarts&lt;/a&gt;, estamos produciendo material para un curso de Inversion of Control y Dependency Injection, que quedará en línea (además de preparar alguna charla o taller presencial). No voy a explicar todavía los términos, sino que quisiera seguir otro camino: tomando la aplicación más simple, ir viendo de flexibilizarla, hasta llegar en algún momento a usar IoC y DI (siglas de los términos en inglés para Inversión de Control e Inyección de Dependencias).&lt;/p&gt;  &lt;p&gt;¿Cuál es la aplicación más simple? Tomemos un clásico “Hello, world” en C# (espero publicar más adelante una serie de versiones en Java, que culmine con el uso de Spring Framework, como hago en mis cursos sobre el tema):&lt;/p&gt;  &lt;pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,courier,monospace;"&gt; &lt;span&gt;class&lt;/span&gt; Program
 {
 &lt;span&gt;static&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; Main(&lt;span&gt;string&lt;/span&gt;[] args)
 {
 Console.WriteLine(&amp;quot;&lt;span&gt;Hello, world&lt;/span&gt;&amp;quot;);
 }
 }
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;¿Qué podemos querer cambiar de esa aplicación? Se me ocurren dos cosas:&lt;/p&gt;

&lt;p&gt;- El mensaje&lt;/p&gt;

&lt;p&gt;- La forma de procesarlo&lt;/p&gt;

&lt;p&gt;Son dos responsabilidades, que podemos asignarlas a dos clases nuevas, digamos, MessageProvider:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,courier,monospace;"&gt; &lt;span&gt;public&lt;/span&gt; &lt;span&gt;class&lt;/span&gt; MessageProvider
 {
 &lt;span&gt;public&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; Message { &lt;span&gt;get&lt;/span&gt;; &lt;span&gt;set&lt;/span&gt;; }
 }
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;y a MessageProcessor:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,courier,monospace;"&gt; &lt;span&gt;public&lt;/span&gt; &lt;span&gt;class&lt;/span&gt; MessageProcessor
 {
 &lt;span&gt;public&lt;/span&gt; MessageProvider Provider { &lt;span&gt;get&lt;/span&gt;; &lt;span&gt;set&lt;/span&gt;; }
 &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; Process()
 {
 Console.WriteLine(&lt;span&gt;this&lt;/span&gt;.Provider.Message);
 }
 }
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Nuestro Hello World puede quedar ahora de esta forma:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,courier,monospace;"&gt; &lt;span&gt;static&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; Main(&lt;span&gt;string&lt;/span&gt;[] args)
 {
 MessageProvider provider = &lt;span&gt;new&lt;/span&gt; MessageProvider() { Message = &amp;quot;&lt;span&gt;Hello, World&lt;/span&gt;&amp;quot; };
 MessageProcessor processor = &lt;span&gt;new&lt;/span&gt; MessageProcessor() { Provider = provider };
 processor.Process();
 }
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Vean que creamos los dos objetos de dos clases concretas, y los “conectamos”: como el MessageProcessor necesita de un MessageProvider, se lo proveemos mediante una propiedad (podríamos haberlo hecho mediante un parámetro en el constructor). Lo que estamos haciendo es construir un grafo de objetos, y dada la forma en que colaboran entre ellos, el grafo lo armamos nosotros. La alternativa sería: DENTRO de MessageProcessor crear un MessageProvider y usarlo. Pero eso dejaría acoplada la responsabilidad de cuál mensaje procesar al propio MessageProcessor. De la forma adoptada arriba, si queremos cambiar el mensaje, NO ALTERAMOS el código de MessageProcessor. A este objeto “le llueve del cielo” su colaborador. Vemos la aparición de un camino a seguir: los “new” de los objetos colaboradores, no están en el código de los consumidores de esos colaboradores. Más adelante, pasaremos a ejemplos más de la vida real. Pero por ahora, exploremos estos temas con ejemplo sencillo. Luego, el problema (armar el grafo de objetos) y la solución (lo armamos “por fuera” de los objetos) será la misma, con variantes, en ejemplos medios y complejos.&lt;/p&gt;

&lt;p&gt;Próximo paso: ahora que tenemos objetos que se hacen cargo de las responsabilidades que descubrimos, podemos refinar el ejemplo: ahora, MessageProcessor está acoplado a una clase concreta MessageProvider. Pero ¿qué necesita realmente MessageProcessor? En lugar de consumir un objeto de una clase concreta, ahora que tenemos un mini caso de uso codificado, podemos extraer, “descubrir” la interface que necesita consumir MessageProcessor. Y ya que estamos, también extraer, descubrir la interface, la conducta expuesta de cualquier MessageProcessor que se nos ocurra mañana. Pueden hacerlo a mano, o apelar a las capacidades de Refactoring, Extract Interface de Visual Studio. Tenemos IMessageProvider:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,courier,monospace;"&gt; &lt;span&gt;public&lt;/span&gt; &lt;span&gt;interface&lt;/span&gt; IMessageProvider
 {
 &lt;span&gt;string&lt;/span&gt; Message { &lt;span&gt;get&lt;/span&gt;; &lt;span&gt;set&lt;/span&gt;; }
 }
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;IMessageProcessor:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,courier,monospace;"&gt; &lt;span&gt;public&lt;/span&gt; &lt;span&gt;interface&lt;/span&gt; IMessageProcessor
 {
 &lt;span&gt;void&lt;/span&gt; Process();
 IMessageProvider Provider { &lt;span&gt;get&lt;/span&gt;; &lt;span&gt;set&lt;/span&gt;; }
 }
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Y nuestras clases ahora implementan y esperan esas interfaces:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,courier,monospace;"&gt; &lt;span&gt;public&lt;/span&gt; &lt;span&gt;class&lt;/span&gt; MessageProvider : HelloWorldInterfacesExample.IMessageProvider
 {
 &lt;span&gt;public&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; Message { &lt;span&gt;get&lt;/span&gt;; &lt;span&gt;set&lt;/span&gt;; }
 }
&lt;/pre&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,courier,monospace;"&gt; &lt;span&gt;public&lt;/span&gt; &lt;span&gt;class&lt;/span&gt; MessageProcessor : HelloWorldInterfacesExample.IMessageProcessor
 {
 &lt;span&gt;public&lt;/span&gt; IMessageProvider Provider { &lt;span&gt;get&lt;/span&gt;; &lt;span&gt;set&lt;/span&gt;; }
 &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; Process()
 {
 Console.WriteLine(&lt;span&gt;this&lt;/span&gt;.Provider.Message);
 }
 }
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Vemos que MessageProcessor es UNA implementación de IMessageProcessor, y que no espera un MessageProvider, sino que se las arregla con cualquier implementación, actual o futura, de IMessageProvider. Como antes, él no se preocupa de crear esa instancia ayudante, sino que alguien proveerá.&lt;/p&gt;

&lt;p&gt;Nuestra invocación queda:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,courier,monospace;"&gt; &lt;span&gt;static&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; Main(&lt;span&gt;string&lt;/span&gt;[] args)
 {
 IMessageProvider provider = &lt;span&gt;new&lt;/span&gt; MessageProvider() { Message = &amp;quot;&lt;span&gt;Hello, World&lt;/span&gt;&amp;quot; };
 IMessageProcessor processor = &lt;span&gt;new&lt;/span&gt; MessageProcessor() { Provider = provider };
 processor.Process();
 }
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Por ahora, no parece que ganemos mucho (para este ejemplo simple). Si tenemos que cambiar el proveedor del mensaje, el mensaje, o la forma de procesarlo (por ejemplo, que genere, en lugar de un mensaje en pantalla, otra cosa, como un archivo PDF o una página web), tenemos que tocar el código de nuestra rutina de inicio. Exploraremos cómo, ayudados por algún framework, conseguir que ese armado y esos datos se deleguen a configuración.&lt;/p&gt;

&lt;p&gt;Código de los ejemplos en &lt;a href="http://cid-9f903f3d6db0c176.office.live.com/self.aspx/Examples/Hogwarts/HelloWorldObjectsExample.zip" target="_blank"&gt;HelloWorldObjectsExample.zip&lt;/a&gt; y &lt;a href="http://cid-9f903f3d6db0c176.office.live.com/self.aspx/Examples/Hogwarts/HelloWorldInterfacesExample.zip" target="_blank"&gt;HelloWorldInterfacesExample.zip&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nos leemos!&lt;/p&gt;

&lt;p&gt;Angel “Java” Lopez 
  &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; 

  &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1773878" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Cursos/default.aspx">Cursos</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp.NET/default.aspx">C Sharp.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Hogwarts/default.aspx">Hogwarts</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Inversion+of+Control/default.aspx">Inversion of Control</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Dependency+Injection/default.aspx">Dependency Injection</category></item></channel></rss>