<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Koalite</title>
	
	<link>http://blog.koalite.com</link>
	<description>El código importa, pero el contexto más</description>
	<lastBuildDate>Mon, 17 Jun 2013 05:06:30 +0000</lastBuildDate>
	<language>es-ES</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/KoalitesBlog" /><feedburner:info uri="koalitesblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Usando C# para entender los prototipos de Javascript</title>
		<link>http://feedproxy.google.com/~r/KoalitesBlog/~3/mkPduG-TbXs/</link>
		<comments>http://blog.koalite.com/2013/06/usando-c-para-entender-los-prototipos-de-javascript/#comments</comments>
		<pubDate>Mon, 17 Jun 2013 05:06:00 +0000</pubDate>
		<dc:creator>Juanma</dc:creator>
				<category><![CDATA[development]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[prototype]]></category>

		<guid isPermaLink="false">http://blog.koalite.com/?p=3112</guid>
		<description><![CDATA[Que cada vez se usa más javascript no es ninguna novedad, pero por desgracia tampoco es novedad que muchas veces se usa javascript en el contexto de un framework sin entender realmente el lenguaje. Aparte de ser un lenguaje dinámico, una característica que diferencia mucho a javascript de lenguajes como C# y Java es el...  <a href="http://blog.koalite.com/2013/06/usando-c-para-entender-los-prototipos-de-javascript/" class="more-link" title="Read Usando C# para entender los prototipos de Javascript">Leer más &#187;</a>
<strong>Posts relacionados:</strong><ol>
<li><a href='http://blog.koalite.com/2011/12/mixins-en-javascript/' rel='bookmark' title='Mixins en Javascript'>Mixins en Javascript</a></li>
<li><a href='http://blog.koalite.com/2012/04/swiftcore-js-un-contenedor-ioc-para-javascript/' rel='bookmark' title='Swiftcore.js: un contenedor IoC para Javascript'>Swiftcore.js: un contenedor IoC para Javascript</a></li>
<li><a href='http://blog.koalite.com/2011/11/modificar-una-clase-en-javascript-eliminar-los-markers-de-google-maps/' rel='bookmark' title='Modificar una clase en Javascript: Eliminar los markers de Google Maps'>Modificar una clase en Javascript: Eliminar los markers de Google Maps</a></li>
</ol>]]></description>
				<content:encoded><![CDATA[<p>Que cada vez se usa más javascript no es ninguna novedad, pero por desgracia tampoco es novedad que muchas veces se usa javascript en el contexto de <a href="http://blog.koalite.com/2011/08/%c2%bfhacen-los-frameworks-tontos-a-los-desarrolladores/" title="¿Hacen los frameworks tontos a los desarrolladores?" target="_blank">un framework sin entender realmente el lenguaje</a>. </p>
<p>Aparte de ser un lenguaje dinámico, una característica que diferencia mucho a javascript de lenguajes como C# y Java es el mecanismo de herencia. En lugar de utilizar un sistema de herencia basado en clases, se usa herencia basada en prototipos.</p>
<p>Una buena forma de entender como funcionan las cosas es intentar implementarlas. No se trata de realizar una implementación &#8220;usable&#8221;, sino de utilizar cosas que ya conocemos para entender mejor cosas nuevas. Voy a dedicar un par de posts para ver cómo simular con C# la herencia prototípica de javascript.</p>
<h3>Clases vs Prototipos</h3>
<p>No voy a entrar en conceptos complicados como <a href="http://en.wikipedia.org/wiki/Type_system" target="_blank">sistemas de tipos</a>, <a href="https://en.wikipedia.org/wiki/Category_theory" target="_blank">teoría de categorías</a> y cosas por el estilo, pero vamos a intentar definir &#8220;más o menos&#8221; cómo funciona cada sistema.</p>
<p>En un lenguaje basado en clases se definen <strong>clases que agrupan datos y operaciones</strong>. A partir de esas clases, se crean objetos (instancias) que contendrán los datos y operaciones definidos en la clase a la que pertenecen. Además, podemos definir subclases, es decir, clases que heredan de otras clases y en las que podemos añadir o modificar el comportamiento de la clase base.</p>
<p>En la lenguaje basado en prototipos no existen las clases. Existen sólo objetos, pero <strong>cada objeto tiene un prototipo</strong> asociado. Este prototipo no es más que otro objeto (con su respectivo prototipo). Al invocar una operación sobre un objeto, primero se mira si el objeto ha definido esa operación. Si la ha definido, se invoca la operación y ya está. Si no, se intenta invocar la operación definida en el objeto que actúa como prototipo, y si no en el prototipo del prototipo y así sucesivamente.</p>
<p>Una consecuencia de esta diferencia es que en el caso de una lenguaje basado en clases el comportamiento del objeto queda definido por la clase a la que pertenece y, por tanto, queda definido en el momento de su creación, mientras que con prototipos el comportamiento del objeto puede cambiar siempre que cambiemos su prototipo, cosa que podríamos hacer en cualquier momento (incluso después de crearlo).</p>
<p>Insisto, ésta no es una definición en absoluto rigurosa y puede haber lenguajes que se comporten de manera diferente, pero para nuestro objetivo, que es entender cómo funciona la herencia en javascript con respecto a C# o Java, nos sirve.</p>
<h3>Simulando un objeto Javascript con C#</h3>
<p>Para nuestro experimento, lo primero que necesitamos es simular un objeto javascript usando C#. El objetivo es pasar este test:</p>
<pre class="brush:csharp">
dynamic p = new ProtoObject();
p.Name = "Lucas";
Assert.That(p.Name, Is.EqualTo("Lucas"));
</pre>
<p>Esto lo podríamos hacer directamente con un <a href="http://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject.aspx" target="_blank">ExpandoObjet</a>, pero desgraciadamente Microsoft tiene la mala costumbre de hacer muchas clases <code>sealed</code> (cuando no <code>internal</code>) y no podemos heredar de él, así que vamos a crear una clase que herede de <code>DynamicObject</code> y use un diccionario para almacenar las propiedades:</p>
<pre class="brush:csharp">
public class ProtoObject : DynamicObject
{
  private readonly IDictionary&lt;string, object&gt; properties = new Dictionary&lt;string, object&gt;();

  public override bool TrySetMember(SetMemberBinder binder, object value)
  {
    properties[binder.Name] = value;
    return true;
  }

  public override bool TryGetMember(GetMemberBinder binder, out object result)
  {
    return properties.TryGetValue(binder.Name, out result);
  }
}
</pre>
<p>Aunque el ejemplo sea con una propiedad, podríamos añadir métodos usando proiedades de tipo <code>Acion</code> o <code>Func</code> y funcionaría igual (aunque la sintaxis es un poco desagradable):</p>
<pre class="brush:csharp">
dynamic p = new ProtoObject();
p.Sum = new Func&lt;int, int, int&gt;((a, b) =&gt; a + b);
Assert.That(p.Sum(2, 3), Is.EqualTo(5));
</pre>
<p>Ahora que tenemos creado nuestro objeto dinámico, vamos a implementar la propiedad <code>__proto__</code> de javascript.</p>
<h3>Añadiendo una cadena de prototipos a través de __proto__</h3>
<p>Al explicar las diferencias de un sistema basado en clases y uno basado en prototipos, decía que en el segundo cada objeto tiene un prototipo y, cuando no podemos resolver una propiedad dentro de un objeto, tratamos de hacerlo en su prototipo. Pues bien, en javascript <strong>el prototipo se almacena como una propiedad más</strong> del objeto, llamada <code>__proto__</code>. </p>
<p>Vamos intentar simularlo pasando este test:</p>
<pre class="brush:csharp">
dynamic p = new ProtoObject();

p.__proto__.Name = "Lucas";
Assert.That(p.Name, Is.EqualTo("Lucas"));

p.Name = "Tengo preferencia";
Assert.That(p.Name, Is.EqualTo("Tengo preferencia"));
</pre>
<p>Para pasar este test, necesitamos modificar nuestra clase <code>ProtoObject</code>:</p>
<pre class="brush:csharp">
public class ProtoObject : DynamicObject
{
    private readonly IDictionary&lt;string, object&gt; properties = new Dictionary&lt;string, object&gt;();

    private ProtoObject lazyInitializedProto;

    public ProtoObject __proto__
    {
        get { return lazyInitializedProto ?? (lazyInitializedProto = new ProtoObject()); }
        set { lazyInitializedProto = value ?? new ProtoObject(); }
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        properties[binder.Name] = value;
        return true;
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        var hasMember = properties.TryGetValue(binder.Name, out result);
        return hasMember || __proto__.TryGetMember(binder, out result);

    }
}
</pre>
<p>Hemos añadido una propiedad <code>__proto__</code> y hemos hecho que cuando no se pueda resolver la propiedad en el diccionario de objetos local, se intente resolverla a través de <code>__proto__</code>. La parte más extraña es tener que inicializar de forma perezosa el prototipo, pero eso es únicamente para evitar una recursión infinita al crear el objeto (se crearía el <code>__proto__</code>, que a su vez crearía su <code>__proto__</code> que a su vez&#8230;).</p>
<h3>Conclusión</h3>
<p>Aunque sólo sirva para fines didácticos (que a nadie se le ocurra intentar usar esto en el mundo real), esta implementación permite comprender fácilmente cómo funciona de forma aproximada el sistema de prototipos en javascript. </p>
<p>Falta un aspecto fundamental, que es el <code>this</code>, puesto que no tenemos una limpia de definir operaciones en los prototipos que actúen sobre las propiedades definidas en el propio objeto, pero sirve para hacernos una idea de <strong>qué es esa misteriosa propiedad <code>__proto__</code></strong> que encontramos en los objetos javascript cuando los inspeccionamos con un depurador.</p>
<p>Es muy atractiva la simplicidad de la idea. En el fondo <strong>todo se basa en composición y delegación</strong>, pero empleando únicamente esos dos conceptos se pueden conseguir resultados realmente interesantes.</p>
<p><strong>Posts relacionados:</strong></p><ol>
<li><a href='http://blog.koalite.com/2011/12/mixins-en-javascript/' rel='bookmark' title='Mixins en Javascript'>Mixins en Javascript</a></li>
<li><a href='http://blog.koalite.com/2012/04/swiftcore-js-un-contenedor-ioc-para-javascript/' rel='bookmark' title='Swiftcore.js: un contenedor IoC para Javascript'>Swiftcore.js: un contenedor IoC para Javascript</a></li>
<li><a href='http://blog.koalite.com/2011/11/modificar-una-clase-en-javascript-eliminar-los-markers-de-google-maps/' rel='bookmark' title='Modificar una clase en Javascript: Eliminar los markers de Google Maps'>Modificar una clase en Javascript: Eliminar los markers de Google Maps</a></li>
</ol><img src="http://feeds.feedburner.com/~r/KoalitesBlog/~4/mkPduG-TbXs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.koalite.com/2013/06/usando-c-para-entender-los-prototipos-de-javascript/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.koalite.com/2013/06/usando-c-para-entender-los-prototipos-de-javascript/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=usando-c-para-entender-los-prototipos-de-javascript</feedburner:origLink></item>
		<item>
		<title>AngularJS: Lo bueno y lo malo</title>
		<link>http://feedproxy.google.com/~r/KoalitesBlog/~3/0cIBB1Ag7uA/</link>
		<comments>http://blog.koalite.com/2013/06/angularjs-lo-bueno-y-lo-malo/#comments</comments>
		<pubDate>Mon, 10 Jun 2013 05:06:17 +0000</pubDate>
		<dc:creator>Juanma</dc:creator>
				<category><![CDATA[development]]></category>
		<category><![CDATA[angularjs]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://blog.koalite.com/?p=3102</guid>
		<description><![CDATA[En mis últimos post he hecho un buen repaso de las características que me parecen más interesantes de AngularJS, empezando por los conceptos básicos, siguiendo con la organización en módulos con servicios e inyección de dependencias, las directivas y filtros para mejorar el mejorar el interfaz de usuario y terminando con las herramientas que ofrece...  <a href="http://blog.koalite.com/2013/06/angularjs-lo-bueno-y-lo-malo/" class="more-link" title="Read AngularJS: Lo bueno y lo malo">Leer más &#187;</a>
<strong>Posts relacionados:</strong><ol>
<li><a href='http://blog.koalite.com/2013/05/angularjs-servicios-inyeccion-de-dependencias-y-modulos/' rel='bookmark' title='AngularJS: Servicios, Inyección de Dependencias y Módulos'>AngularJS: Servicios, Inyección de Dependencias y Módulos</a></li>
<li><a href='http://blog.koalite.com/2013/06/angularjs-directivas-y-filtros/' rel='bookmark' title='AngularJS: Directivas y Filtros'>AngularJS: Directivas y Filtros</a></li>
<li><a href='http://blog.koalite.com/2013/05/angularjs-conceptos-basicos/' rel='bookmark' title='AngularJS: Conceptos Básicos'>AngularJS: Conceptos Básicos</a></li>
</ol>]]></description>
				<content:encoded><![CDATA[<p>En mis últimos post he hecho un buen repaso de las características que me parecen más interesantes de <a href="http://angularjs.org" target="_blank">AngularJS</a>, empezando por los <a href="http://blog.koalite.com/2013/05/angularjs-conceptos-basicos/" title="AngularJS: Conceptos Básicos" target="_blank">conceptos básicos</a>, siguiendo con la <a href="http://blog.koalite.com/2013/05/angularjs-servicios-inyeccion-de-dependencias-y-modulos/" title="AngularJS: Servicios, Inyección de Dependencias y Módulos" target="_blank">organización en módulos con servicios e inyección de dependencias</a>, las <a href="http://blog.koalite.com/2013/06/angularjs-directivas-y-filtros/" title="AngularJS: Directivas y Filtros" target="_blank">directivas y filtros</a> para mejorar el mejorar el interfaz de usuario y terminando con las herramientas que ofrece angular para realizar <a href="http://blog.koalite.com/2013/06/angularjs-tests-unitarios-y-de-extremo-a-extremo/" title="AngularJS: Tests Unitarios y de Extremo a Extremo" target="_blank">tests unitarios y de extremo a extremo</a>.</p>
<img src="http://blog.koalite.com/wp-content/uploads/AngularJS-large.png" alt="Logo de AngularJS" class="alignright size-full wp-image-3029" />
<p>En este post voy a tratar de sintetizar lo que más y lo que menos me ha gustado de angular. </p>
<p>Como siempre, este tipo de cosas son bastante personales, por lo que cualquier opinión (especialmente si es distinta) será bienvenida en los comentarios.</p>
<h3>Un poco de contexto antes de empezar</h3>
<p>Angular es una <strong>solución completa</strong> que incluye prácticamente todos los aspectos que puedes necesitar para crear una aplicación cliente en javascript. Esto incluye la generación de vistas, el uso de databinding, las rutas, la organización de componentes en módulos, la comunicación con el servidor&#8230;</p>
<p>Eso quiere decir que no tiene sentido compararlo con librerías como jQuery, Knockout, Handlebars o PagerJs. Eso son librerías orientadas a resolver un problema concreto, pero no proporcionan una solución global para desarrollar aplicaciones.</p>
<p>No hay que olvidar que angular está <strong>diseñado para desarrollar aplicaciones</strong>, no páginas web. Si lo que estás desarrollando es una página web, donde prime el contenido, necesites una buena indexación y un html limpio y cristalino, angular no es una buena solución, pero no porque sea un mal producto, simplemente no está diseñado para ello.</p>
<h3>Las partes buenas</h3>
<p>El sistema de databinding es muy completo y potente. De serie permite hacer casi cualquier cosa que necesites, pero además se trata de un <strong>sistema de databinding fácilmente extensible</strong> mediante directivas y filtros, lo que permite a crear pequeños componentes que facilitan que la capa de presentación sea algo organizado y no el típico jaleo que acaba siendo muchas veces.</p>
<p>La idea de poder anidar los <code>$scopes</code> (<code>ViewModels</code>), aunque al principio parezca un poco extraña, acaba resultando bastante natural y posibilita crear diseños bastante interesantes.</p>
<p>Aunque al principio era un poco reticente al uso de un <strong>contenedor de inversión de control</strong> en javascript (no así a la <a href="http://blog.koalite.com/2012/04/inyeccion-de-dependencias-en-javascript-y-otros-lenguajes-dinamicos/" title="Inyección de dependencias en Javascript (y otros lenguajes dinámicos)" target="_blank">inyección de dependencias</a>), después de trabajar con angular tengo que reconocer que he cambiado de opinión. </p>
<p>Es cierto que hay que definir explicítamente las dependencias y la sintaxis es un poco desagradable para evitar problemas con los <em>minifiers</em> y <em>uglifiers</em>, pero al final compensa porque te permite concentrarte en la clase que estás desarrollando sin tener que preocuparte de la implementación y el ciclo de vida de sus dependencias.</p>
<p>Desde el principio, angular está diseñado para ser <strong>fácilmente testeable</strong>. Teniendo en cuenta <a href="http://blog.koalite.com/2012/04/la-importancia-de-los-tests-en-javascript/" title="La importancia de los tests en Javascript" target="_blank">lo imporantes que son los tests en javascript</a>, esto es una cosa muy de agradecer. A través de karma se pueden crear tanto tests unitarios (ayudados por los mocks que se incluyen en angular) como tests de extremo a extremo, y eso es un factor crítico para mantener la estabilidad de la aplicación.</p>
<h3>Las partes malas</h3>
<p>Una de las cosas que más confusas me han resultado al trabajar con angular es <strong>la nomenclatura</strong> elegida para las cosas. La mayoría de los conceptos que se manejan con angular son conceptos habituales que ya conocía, pero la forma de llamarlos es un poco rara.</p>
<p>La mayoría de los filtros no filtran nada, sino que formatean. El estado se mantiene a través de servicios. Los <code>ViewModel</code> se convierten en los <code>$scope</code>. No soy muy bueno poniendo nombres a las cosas, pero yo los hubiera llamado algo así como <code>Components</code>, <code>Transformers</code> y <code>ViewModels</code>.</p>
<p>Esto además nos lleva a otro problema muy frecuente en proyectos opensource y especialmente en la comunidad javascript, que está evolucionando tan rápido: <strong>la falta de documentación</strong>.</p>
<p>La <a href="http://docs.angularjs.org/guide/" target="_blank">documentación oficial de angular</a> no es que esté mal, pero no es todo lo completa que a uno le gustaría, muchas veces falta ejemplos y no siempre está actualizada. Es verdad que es fácil encontrar documentación en forma de videos, tutoriales y posts, pero la velocidad a la que se desarrolla angular hace que se queden obsoletos muy pronto. En cuanto sales de los ejemplos típicos y encuentras problemas, no encuentras mucha ayuda.</p>
<p>Por último, hay que tener en cuenta que <strong>si decides usar angular, te casas con angular</strong>. Esto está motivado por la propia concepción de angular como solución &#8220;todo incluido&#8221;, por lo que tampoco es muy achacable al propio angular, pero no deja de ser un factor importante.</p>
<p>Me parece complicado desarrollar una aplicación completa con angular y luego tratar de migrarla a otro framework, porque la mayoría de la funcionalidad va a estar muy integrada con clase que dependen de angular. </p>
<p>Es un riesgo que puede merecer la pena asumir, pero que hay que tener presente.</p>
<h3>Conclusión</h3>
<p>Ante la pregunta de si usaría angular para mi próximo aplicación con javascript, la respuesta es, a día de hoy sí (de hecho lo estoy haciendo). </p>
<p>La curva de aprendizaje se hace un poco dura, sobre todo por la falta de documentación y la elección de nombres, pero luego resulta bastante productivo gracias a cosas como el databinding y el contenedor de inversión de control.</p>
<p>El aspecto más preocupante de utilizar angular es el mismo de utilizar cualquier framework de estas características: te atas mucho a él y asumes un riesgo grande al ligar tu aplicación al destino de angular. </p>
<p>La parte positiva de esto es que se trata de un proyecto opensource y con un código <em>relativamente</em> fácil de seguir, por lo que en caso de apuro, siempre podrás meterlo mano para solucionar los problemas que te vayan surgiendo.</p>
<p><strong>Posts relacionados:</strong></p><ol>
<li><a href='http://blog.koalite.com/2013/05/angularjs-servicios-inyeccion-de-dependencias-y-modulos/' rel='bookmark' title='AngularJS: Servicios, Inyección de Dependencias y Módulos'>AngularJS: Servicios, Inyección de Dependencias y Módulos</a></li>
<li><a href='http://blog.koalite.com/2013/06/angularjs-directivas-y-filtros/' rel='bookmark' title='AngularJS: Directivas y Filtros'>AngularJS: Directivas y Filtros</a></li>
<li><a href='http://blog.koalite.com/2013/05/angularjs-conceptos-basicos/' rel='bookmark' title='AngularJS: Conceptos Básicos'>AngularJS: Conceptos Básicos</a></li>
</ol><img src="http://feeds.feedburner.com/~r/KoalitesBlog/~4/0cIBB1Ag7uA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.koalite.com/2013/06/angularjs-lo-bueno-y-lo-malo/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://blog.koalite.com/2013/06/angularjs-lo-bueno-y-lo-malo/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=angularjs-lo-bueno-y-lo-malo</feedburner:origLink></item>
		<item>
		<title>AngularJS: Tests Unitarios y de Extremo a Extremo</title>
		<link>http://feedproxy.google.com/~r/KoalitesBlog/~3/qBR1VzQrTz8/</link>
		<comments>http://blog.koalite.com/2013/06/angularjs-tests-unitarios-y-de-extremo-a-extremo/#comments</comments>
		<pubDate>Thu, 06 Jun 2013 05:06:03 +0000</pubDate>
		<dc:creator>Juanma</dc:creator>
				<category><![CDATA[development]]></category>
		<category><![CDATA[angularjs]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[tdd]]></category>

		<guid isPermaLink="false">http://blog.koalite.com/?p=3093</guid>
		<description><![CDATA[Este es el cuarto post de una serie en la que estoy explicando las características más destacadas de angularjs. Hasta ahora hemos visto los conceptos básicos, la forma en que se trabaja con servicios, inyección de dependencias y módulos, y cómo mejorar la capa de presentación usando directivas y filtros. Hoy quiero analizar algo que,...  <a href="http://blog.koalite.com/2013/06/angularjs-tests-unitarios-y-de-extremo-a-extremo/" class="more-link" title="Read AngularJS: Tests Unitarios y de Extremo a Extremo">Leer más &#187;</a>
<strong>Posts relacionados:</strong><ol>
<li><a href='http://blog.koalite.com/2012/09/como-no-escribir-tests-unitarios-resumen-final/' rel='bookmark' title='Cómo NO escribir tests unitarios: Resumen final'>Cómo NO escribir tests unitarios: Resumen final</a></li>
<li><a href='http://blog.koalite.com/2012/09/como-no-escribir-tests-unitarios-todos-a-la-vez/' rel='bookmark' title='Cómo NO escribir tests unitarios: Todos a la vez'>Cómo NO escribir tests unitarios: Todos a la vez</a></li>
<li><a href='http://blog.koalite.com/2012/08/como-no-escribir-test-unitarios-replicando-calculos-en-el-test/' rel='bookmark' title='Cómo NO escribir tests unitarios: Replicando cálculos en el test'>Cómo NO escribir tests unitarios: Replicando cálculos en el test</a></li>
</ol>]]></description>
				<content:encoded><![CDATA[<img src="http://blog.koalite.com/wp-content/uploads/AngularJS-large.png" alt="Logo de AngularJS" class="alignright size-full wp-image-3029" />
<p>Este es el cuarto post de una serie en la que estoy explicando las características más destacadas de <a href="http://angularjs.org" target="_blank">angularjs</a>. Hasta ahora hemos visto los <a href="http://blog.koalite.com/2013/05/angularjs-conceptos-basicos/" title="AngularJS: Conceptos Básicos" target="_blank">conceptos básicos</a>, la forma en que se trabaja con <a href="http://blog.koalite.com/2013/05/angularjs-servicios-inyeccion-de-dependencias-y-modulos/" title="AngularJS: Servicios, Inyección de Dependencias y Módulos" target="_blank">servicios, inyección de dependencias y módulos</a>, y cómo mejorar la capa de presentación usando <a href="http://blog.koalite.com/2013/06/angularjs-directivas-y-filtros/" target="_blank">directivas y filtros</a>.</p>
<p>Hoy quiero analizar algo que, por desgracia, para muchos será irrelevante, pero que para mi es <strong>fundamental antes de decidirme a utilizar un framework</strong>: el soporte para testearlo. </p>
<p>En este blog que hablado mucho sobre <a href="http://blog.koalite.com/tag/tdd/" target="_blank">tests automatizados</a> (ya fuera aplicando <abbr title="Test-Driven Design">TDD</abbr> o no) y he insistido en <a href="http://blog.koalite.com/2012/04/la-importancia-de-los-tests-en-javascript/" title="La importancia de los tests en Javascript" target="_blank">la importancia de los tests en javascript</a>.  </p>
<p>Si ya considero que los tests automatizados son una de las cosas que más calidad aporta a un proyecto, en el caso de un lenguaje dinámico como javascript creo que su importancia aumenta enormemente al perder al seguridad que ofrece la comprobación de tipos que realiza el compilador.</p>
<p>En ese sentido, angular está diseñado desde el principio para poder ser fácilmente testeable y para ello cuenta con dos tipos de tests diferenciados, tests unitarios y tests de extremo a extremo.</p>
<p><strong>OJO</strong>: en estos post no vas a encontrar información detallada sobre cómo trabajar con angular ni <a href="http://blog.koalite.com/2012/06/nos-gusta-demasiado-la-pornografia/" title="Nos gusta demasiado la pornografía" target="_blank">mucho código fuente</a>, si estás buscando ese tipo de detalles, te recomiendo que eches un vistazo a la <a href="http://docs.angularjs.org/guide/" target="_blank">documentación oficial</a> o sigas el <a href="http://docs.angularjs.org/tutorial/index" target="_blank">tutorial</a>.</p>
<h3>Karma</h3>
<p>Los sistemas de tests empleados por defecto en angular, tanto unitarios como extremo a extremo, se basan en el uso de <a href="http://karma-runner.github.io/0.8/index.html" target="_blank">Karma</a>, un lanzador de tests que se integra con distintos frameworks (Jasmine, QUnit, Mocha, etc.) para ejecutar tests en navegadores reales (Firefox, Chrome, Phantom, e incluso Internet Explorer).</p>
<p>Esto nos permite comprobar que la aplicación funciona realmente sobre los motores de javascript que la van a ejecutar, lo que nos ayudará a detectar posibles problemas por <a href="http://blog.koalite.com/2012/04/echo-de-menos-la-bcl-formato-y-parsing-de-fechas-en-javascript/" title="Echo de menos la BCL: formato y parsing de fechas en Javascript" target="_blank">incompatibilidades de javascript</a> entre ellos.</p>
<p>La configuración de Karma no es todo lo sencilla que me gustaría y su integración con herramientas como <a href="http://gruntjs.com/" target="_blank">grunt</a> a veces resulta un poco complicada, sobre todo por la gestión de versiones (algo demasiado frecuente en el cambiante mundo de las librerías javascript). Un buen punto de partida para configurarlo es el proyecto <a href="https://github.com/angular/angular-seed" target="_blank">angular-seed</a>, que ofrece una plantilla de proyecto ya configurada.</p>
<p>Aun así, una vez que lo tienes configuarado es bastante estable y se puede usar sin demasiados problemas con un <a href="http://blog.koalite.com/2013/05/servidor-de-integracion-continua-una-buena-inversion/" title="Servidor de Integración Continua, una buena inversión" target="_blank">servidor de integración continua</a>.</p>
<h3>Tests Unitarios</h3>
<p>Con angular podemos escribir tests unitarios que nos permitan definir y comprobar el funcionamiento de los componentes de la aplicación por separado.</p>
<p>Aprovechando el sistema de <a href="http://blog.koalite.com/2013/05/angularjs-servicios-inyeccion-de-dependencias-y-modulos/" title="AngularJS: Servicios, Inyección de Dependencias y Módulos" target="_blank">inyección de dependencias</a> es sencillo modificar las dependencias de los componentes para inyectar mocks/stubs/fakes/lo-que-más-te-guste y poder aislar el componente que estamos testeando.</p>
<p>No soy muy partidario de los <a href="http://blog.koalite.com/2012/09/como-no-escribir-tests-unitarios-verificando-interacciones/" title="Cómo NO escribir tests unitarios: Verificando interacciones" target="_blank">tests de interacción con mocks</a>, y en el caso de javascript todavía menos, pero a veces no queda más remedio que utilizarlos para testar cosas concretas.</p>
<p>Aun así, siguiendo los mismos <a href="http://blog.koalite.com/2012/09/como-no-escribir-tests-unitarios-resumen-final/" title="Cómo NO escribir tests unitarios: Resumen final" target="_blank">principios para escribir tests unitarios</a> que aplicaríamos en otros lenguajes es posible conseguir una buena suite de tests en la que podamos confiar.</p>
<h3>Tests de Extremo a Extremo</h3>
<p>Usando Karma podemos también ejecutar tests de integración de extremo a extremo. Estos tests levantan un servidor web de verdad e interactúan con nuestra aplicación desde un browser como lo haría un usuario. Para ello angular ofrece un <a href="http://docs.angularjs.org/guide/dev_guide.e2e-testing" target="_blank">DSL</a> no demasiado complicado de manejar que nos permite indicar cosas como &#8220;navega a esta página&#8221;, &#8220;pulsa este botón&#8221;, &#8220;comprueba el texto de este &lt;p&gt;&#8221;&#8230;</p>
<p>Este tipo de tests es bastante más lento de ejecutar que los tests unitarios y normalmente suele haber muchos menos tests de extremo a extremo que tests unitarios. No obstante, en mi caso, en este tipo de aplicaciones escribo más tests de extremo a extremo que los que escribiría en otros entornos.</p>
<p>En un lenguaje estático los tipos ayudan mucho a mantener la estructura de la aplicación en pie. Si modificas el interfaz de una clase y no actualizas los clientes, la aplicación no compilará, tendrás que revisar los clientes y por lo menos tendrás una oportunidad de corregir el comportamiento. Si además tienes tests unitarios que comprueben el funcionamiento de cada clase por separado&#8230; tienes una cierta seguridad.</p>
<p>En javascript, si cambias el comportamiento de una clase, los clientes no se van a enterar. No hay un compilador que te diga que la llamada es incorrecta. Si tienes tests unitarios te pueden ayudar a detectar problemas, pero si la clase cliente ha sustituido la dependencia por un mock/fake/stub, todos los tests seguirán pasando sin errores pese a los cambios (esto en un lenguaje estático no ocurriría porque al cambiar el interface del componente tendrías que actualizar el mock/fake/stub y tendrías una pista de que hay algo que ajustar).</p>
<p>Si a esto le unimos la cantidad de configuración que va en el propio HTML a través de <a href="http://blog.koalite.com/2013/06/angularjs-directivas-y-filtros/" title="AngularJS: Directivas y Filtros" target="_blank">directivas y filtros</a> aplicados, los tests de extremo a extremo se convierten en algo indispensable para garantizar el comportamiento del sistema.</p>
<h3>Resumen</h3>
<p>Por suerte, angular está bien diseñado para permitirnos testear nuestras aplicaciones. Ya he dicho antes que para mi es un factor crítico a la hora de elegir un framework y en este caso estoy muy contento con el soporte que da angular para ello.</p>
<p>Con este post termino el repaso a las características que me parecen más interesantes de angular. Aprovecharé el último post de la serie para hacer una pequeña valoración (aun) más personal de este framework que está tan de moda (ahora).</p>
<p><strong>Posts relacionados:</strong></p><ol>
<li><a href='http://blog.koalite.com/2012/09/como-no-escribir-tests-unitarios-resumen-final/' rel='bookmark' title='Cómo NO escribir tests unitarios: Resumen final'>Cómo NO escribir tests unitarios: Resumen final</a></li>
<li><a href='http://blog.koalite.com/2012/09/como-no-escribir-tests-unitarios-todos-a-la-vez/' rel='bookmark' title='Cómo NO escribir tests unitarios: Todos a la vez'>Cómo NO escribir tests unitarios: Todos a la vez</a></li>
<li><a href='http://blog.koalite.com/2012/08/como-no-escribir-test-unitarios-replicando-calculos-en-el-test/' rel='bookmark' title='Cómo NO escribir tests unitarios: Replicando cálculos en el test'>Cómo NO escribir tests unitarios: Replicando cálculos en el test</a></li>
</ol><img src="http://feeds.feedburner.com/~r/KoalitesBlog/~4/qBR1VzQrTz8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.koalite.com/2013/06/angularjs-tests-unitarios-y-de-extremo-a-extremo/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.koalite.com/2013/06/angularjs-tests-unitarios-y-de-extremo-a-extremo/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=angularjs-tests-unitarios-y-de-extremo-a-extremo</feedburner:origLink></item>
		<item>
		<title>AngularJS: Directivas y Filtros</title>
		<link>http://feedproxy.google.com/~r/KoalitesBlog/~3/NR29nm0Ed0c/</link>
		<comments>http://blog.koalite.com/2013/06/angularjs-directivas-y-filtros/#comments</comments>
		<pubDate>Mon, 03 Jun 2013 05:06:25 +0000</pubDate>
		<dc:creator>Juanma</dc:creator>
				<category><![CDATA[development]]></category>
		<category><![CDATA[angularjs]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://blog.koalite.com/?p=3070</guid>
		<description><![CDATA[En esta serie de posts estoy haciendo un repaso de muchas de las características de angularjs. En el primer post explicaba los conceptos básicos en que se fundamenta angular, y especialmente la capa de presentación, mientras que en el segundo profundizaba un poco en la organización interna basada en módulos, servicios e inyección de dependencias....  <a href="http://blog.koalite.com/2013/06/angularjs-directivas-y-filtros/" class="more-link" title="Read AngularJS: Directivas y Filtros">Leer más &#187;</a>
<strong>Posts relacionados:</strong><ol>
<li><a href='http://blog.koalite.com/2013/05/angularjs-servicios-inyeccion-de-dependencias-y-modulos/' rel='bookmark' title='AngularJS: Servicios, Inyección de Dependencias y Módulos'>AngularJS: Servicios, Inyección de Dependencias y Módulos</a></li>
<li><a href='http://blog.koalite.com/2013/05/angularjs-conceptos-basicos/' rel='bookmark' title='AngularJS: Conceptos Básicos'>AngularJS: Conceptos Básicos</a></li>
</ol>]]></description>
				<content:encoded><![CDATA[<img src="http://blog.koalite.com/wp-content/uploads/AngularJS-large.png" alt="Logo de AngularJS" class="alignright size-full wp-image-3029" />
<p>En esta serie de posts estoy haciendo un repaso de muchas de las características de <a href="http://angularjs.org" target="_blank">angularjs</a>. En el primer post explicaba los <a href="http://blog.koalite.com/2013/05/angularjs-conceptos-basicos/" title="AngularJS: Conceptos Básicos" target="_blank">conceptos básicos</a> en que se fundamenta angular, y especialmente la capa de presentación, mientras que en el segundo profundizaba un poco en la organización interna basada en <a href="http://blog.koalite.com/2013/05/angularjs-servicios-inyeccion-de-dependencias-y-modulos/" title="AngularJS: Servicios, Inyección de Dependencias y Módulos" target="_blank">módulos, servicios e inyección de dependencias</a>.</p>
<p>Esta vez toca volver a la capa de presentación para hacer hincapié en dos herramientas que ofrece angular para <strong>desarrollar la capa de presentación de forma lógica y sencilla</strong>.</p>
<p><strong>OJO</strong>: en estos post no vas a encontrar información detallada sobre cómo trabajar con angular ni <a href="http://blog.koalite.com/2012/06/nos-gusta-demasiado-la-pornografia/" title="Nos gusta demasiado la pornografía" target="_blank">mucho código fuente</a>, si estás buscando ese tipo de detalles, te recomiendo que eches un vistazo a la <a href="http://docs.angularjs.org/guide/" target="_blank">documentación oficial</a> o sigas el <a href="http://docs.angularjs.org/tutorial/index" target="_blank">tutorial</a>.</p>
<h3>Directivas</h3>
<p>En el primer post expliqué que angular utiliza un sistema de <em>databinding</em> declarativo bidireccional para enganchar el <code>$scope</code>, es decir el <code>ViewModel</code> en terminología de angular, con la vista. Para ello se emplean lo que en angular se conoce como <em>directivas</em>.</p>
<p>Las directivas tienen el aspecto de <strong>elementos o atributos en el código HTML</strong>, pero son interpretadas por angular al generar las vistas, lo que nos permite modificar el DOM o añadir nuevos comportamientos. </p>
<p>Podéis ver bastantes ejemplos de directivas en el proyecto <a href="http://angular-ui.github.io/bootstrap/" target="_blank">UI Boostrap</a>, que permite utilizar los componentes de <a href="http://twitter.github.io/bootstrap/" target="_blank">Twitter Bootstrap</a> en angular, pero para hacernos una idea de cómo funcionan vamos a ver un par de ejemplos.</p>
<p>Una directiva de atributo se utiliza como si fuese un atributo más de un elemento HTML y puede llevar parámetros o no, pero además tiene la ventaja de que desde ella podemos referenciar el <code>$scope</code> (el <code>ViewModel</code>) para realizar acciones o leer datos:</p>
<pre class="brush:html">
&lt;div ng-controller="SampleController"&gt;
  &lt;input ng-model="person.name"/&gt;
  &lt;button ng-click="save()"/&gt;
&lt;/div&gt;
</pre>
<p>En este ejemplo aparecen las directivas <code>ng-controller</code>, <code>ng-model</code> y <code>ng-click</code>, que nos permiten enlazar un <code>Controller</code> a un elemento HTML, enlazar la propiedad <code>person.model</code> a un cuadro de texto e invocar la función <code>$scope.save()</code> al pulsar un botón.</p>
<p>Las directivas de elemento se utilizan como cualquier otro elemento HTML y simplifican los procesos de creación de fragmentos HTML. Por ejemplo, podemos tener una directiva que nos permita generar pestañas:</p>
<pre class="brush:html">
&lt;tabs&gt;
  &lt;pane heading="Static title"&gt;Static content&lt;/pane&gt;
  &lt;pane ng-repeat="pane in panes" 
        heading="{{pane.title}}" 
        active="pane.active"&gt;
    {{pane.content}}
  &lt;/pane&gt;
&lt;/tabs&gt;
</pre>
<p>Aquí estamos usando las directivas <code>tabs</code> y <code>pane</code> para generar la estructura de HTML necesaria para implementar un sistema de pestañas.</p>
<p>Lo mejor de las directivas es que <strong>es muy sencillo crear nuevas directivas</strong> para encapsular pequeños fragmentos de funcionalidad y poder así mantener unas vistas más limpias y claras. Podríamos considerar las directivas como algo similar a los controles de usuario de ASP.NET o los HTML helpers de ASP.NET MVC.</p>
<h3>Filtros</h3>
<p>Los filtros en angular son los encargados de procesar la información antes de mostrarla en pantalla. Permiten hacer muchas cosas, pero lo más habitual es utilizarlos para <strong>modificar los valores a presentar o aplicarles formato</strong>.</p>
<p>Se aplican dentro de las expresiones de databinding y se indican con el caracter <code>|</code>. Al igual que las directivas, los filtros pueden recibir parametros que modifiquen su comportamiento. </p>
<p>El ejemplo más típico de uso de un filtro que modifica lo que estamos presentando es el filtro <code>filter</code> que permite seleccionar elementos de un array:</p>
<pre class="brush:html">
&lt;ul&gt;
  &lt;li ng-repeat="c in customers | filter:{region: 'Madrid'}"&gt;{{c.name}}&lt;/li&gt;
&lt;/ul&gt;
</pre>
<p>En este ejemplo estaríamos filtrando los elementos del array <code>customers</code> antes de pasárselos a la directiva <code>ng-repeat</code> para mostrar sólo los clientes cuya <code>region</code> es Madrid.</p>
<p>En el caso de formatear valores, podríamos tener un filtro que tradujese cadenas de texto antes de mostrarlas al usuario y su uso sería similar a este:</p>
<pre class="brush:html">
&lt;p&gt;{{'SAMPLE_KEY' | localize}}&lt;/p&gt;
</pre>
<p>El filtro <code>localize</code> se encargaría de traducir, seguramente usando algún <a href="http://blog.koalite.com/2013/05/angularjs-servicios-inyeccion-de-dependencias-y-modulos/" title="AngularJS: Servicios, Inyección de Dependencias y Módulos" target="_blank">servicio</a>, la expresión a la que se aplica el filtro, en este caso <code>'SAMPLE_KEY'</code>. </p>
<p>Al igual que las directivas, es <strong>fácil definir nuevos filtros</strong> que permitan reutilizar comportamiento entre distintas partes de la aplicación. Además, angular permite aplicar secuencialmente filtros, por lo que es sencillo crear muchos filtros focalizados y luego componerlos para obtener el resultado final:</p>
<pre class="brush:html">
&lt;p&gt;{{message | pluralize | toUpperCase}}&lt;/p&gt;
</pre>
<p>Seguramente lo más confuso de los filtros es que el primer ejemplo que se ve es el de filtro <code>filter</code>, por lo que <em>parece que únicamente sirven para filtrar colecciones</em>, pero en realidad, como hemos visto pueden utilizarse para otro tipo de cosas, como formatear valores o incluso realizar otras transformaciones (por ejemplo, agregados sobre colecciones). </p>
<h3>Resumen</h3>
<p>Los filtros y las directivas son de las cosas que más me gustan de angular. En la mayoría de aplicaciones el código más feo, más enrevesado y más difícil de mantener está en la capa de presentación y, sobre todo, en las vistas, por lo que contar con herramientas como estas es de mucha ayuda para que la aplicación no se haga inmanejable con el paso del tiempo.</p>
<p>Todavía no he dicho nada en esta serie sobre otro factor que está bastante bien trabajado en angular, que son las herramientas para realizar tests, pero eso queda para el próximo post.</p>
<p><strong>Posts relacionados:</strong></p><ol>
<li><a href='http://blog.koalite.com/2013/05/angularjs-servicios-inyeccion-de-dependencias-y-modulos/' rel='bookmark' title='AngularJS: Servicios, Inyección de Dependencias y Módulos'>AngularJS: Servicios, Inyección de Dependencias y Módulos</a></li>
<li><a href='http://blog.koalite.com/2013/05/angularjs-conceptos-basicos/' rel='bookmark' title='AngularJS: Conceptos Básicos'>AngularJS: Conceptos Básicos</a></li>
</ol><img src="http://feeds.feedburner.com/~r/KoalitesBlog/~4/NR29nm0Ed0c" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.koalite.com/2013/06/angularjs-directivas-y-filtros/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.koalite.com/2013/06/angularjs-directivas-y-filtros/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=angularjs-directivas-y-filtros</feedburner:origLink></item>
		<item>
		<title>AngularJS: Servicios, Inyección de Dependencias y Módulos</title>
		<link>http://feedproxy.google.com/~r/KoalitesBlog/~3/WMFIX4SXkHU/</link>
		<comments>http://blog.koalite.com/2013/05/angularjs-servicios-inyeccion-de-dependencias-y-modulos/#comments</comments>
		<pubDate>Thu, 30 May 2013 05:06:43 +0000</pubDate>
		<dc:creator>Juanma</dc:creator>
				<category><![CDATA[development]]></category>
		<category><![CDATA[angularjs]]></category>
		<category><![CDATA[dependency injection]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://blog.koalite.com/?p=3050</guid>
		<description><![CDATA[En el anterior post sobre angularjs explicaba la forma en que se organiza la capa de presentación alrededor de los conceptos de Views, Controllers, ViewModels y Routes. Siguiendo con mi política de conocer los frameworks sobre los que trabajo, en este post vamos a bajar de nivel y vamos a ver qué hay por debajo...  <a href="http://blog.koalite.com/2013/05/angularjs-servicios-inyeccion-de-dependencias-y-modulos/" class="more-link" title="Read AngularJS: Servicios, Inyección de Dependencias y Módulos">Leer más &#187;</a>
<strong>Posts relacionados:</strong><ol>
<li><a href='http://blog.koalite.com/2012/04/inyeccion-de-dependencias-en-javascript-y-otros-lenguajes-dinamicos/' rel='bookmark' title='Inyección de dependencias en Javascript (y otros lenguajes dinámicos)'>Inyección de dependencias en Javascript (y otros lenguajes dinámicos)</a></li>
<li><a href='http://blog.koalite.com/2013/05/angularjs-conceptos-basicos/' rel='bookmark' title='AngularJS: Conceptos Básicos'>AngularJS: Conceptos Básicos</a></li>
<li><a href='http://blog.koalite.com/2012/05/dependencias-binarias-y-dependencias-de-codigo-fuente/' rel='bookmark' title='Dependencias binarias y dependencias de código fuente'>Dependencias binarias y dependencias de código fuente</a></li>
</ol>]]></description>
				<content:encoded><![CDATA[<img src="http://blog.koalite.com/wp-content/uploads/AngularJS-large.png" alt="Logo de AngularJS" class="alignright size-full wp-image-3029" />
<p>En el <a href="http://blog.koalite.com/2013/05/angularjs-conceptos-basicos/" target="_blank">anterior post sobre angularjs</a> explicaba la forma en que se organiza la capa de presentación alrededor de los conceptos de <code>Views</code>, <code>Controllers</code>, <code>ViewModels</code> y <code>Routes</code>. Siguiendo con mi política de <a href="http://blog.koalite.com/2011/08/%c2%bfhacen-los-frameworks-tontos-a-los-desarrolladores/" title="¿Hacen los frameworks tontos a los desarrolladores?" target="_blank">conocer los frameworks sobre los que trabajo</a>, en este post vamos a bajar de nivel y vamos a ver qué hay por debajo de la capa de presentación.</p>
<p><strong>OJO</strong>: en estos post no vas a encontrar información detallada sobre cómo trabajar con angular ni <a href="http://blog.koalite.com/2012/06/nos-gusta-demasiado-la-pornografia/" title="Nos gusta demasiado la pornografía" target="_blank">mucho código fuente</a>, si estás buscando ese tipo de detalles, te recomiendo que eches un vistazo a la <a href="http://docs.angularjs.org/guide/" target="_blank">documentación oficial</a> o sigas el <a href="http://docs.angularjs.org/tutorial/index" target="_blank">tutorial</a>.</p>
<h3>Servicios</h3>
<p>Con los elementos que veíamos en el post anterior tenemos herramientas suficientes para construir una aplicación, pero cuando la aplicación se complica, tener toda la lógica metida entre los <code>Controllers</code> y los <code>ViewModels</code> (a.k.a. <code>$scopes</code>), no es una buena idea. </p>
<p>Los servicios son un concepto importante en angular. Igual que podemos definir <code>Controllers</code>, podemos definir servicios en los que agrupemos funcionalidad que luego estará disponible para ser usada en los <code>Controllers</code>, mejorando la claridad del código y favoreciendo la reutilización. </p>
<p>Hasta aquí, nada nuevo. Es un concepto manejado por todos desde hace mucho tiempo y resulta familiar. La parte que puede resultar más extraña es que en angular <strong>los servicios se utilizan también para mantener estado</strong>.</p>
<p>En la mayoría de arquitecturas que he utilizado los servicios suelen ser objetos <em>stateless</em> (sin estado), que implementan operaciones pero no mantienen el estado de la aplicación. Sin embargo, en angular los servicios son la herramienta básica para mantener el estado de la aplicación (hablo siempre de la capa cliente) y compartir información entre los <code>Controllers</code>. </p>
<p>En una aplicación web MVC típica, del estilo ASPNET MVC o Rails, la información fluye entre los <code>Controllers</code> a través de las peticiones http, pero en una aplicación con angular no se emplea ese concepto, sino que un <code>Controller</code> modifica el estado de un servicio y el siguiente <code>Controller</code> utiliza ese servicio para acceder al nuevo estado.</p>
<p>En realidad, la existencia de este tipo de objetos no es algo raro, pero catalogarlos como servicios resulta un tanto confuso cuando empiezas a trabajar con angular.</p>
<h3>Inyección de dependencias</h3>
<p>Hace tiempo escribí de la utilidad de la <a href="http://blog.koalite.com/2012/04/inyeccion-de-dependencias-en-javascript-y-otros-lenguajes-dinamicos/" target="_blank">inyección de dependencias en javascript</a> y una de las cosas que me gusta de angular es que hace un uso intensivo de ella usando un <a href="http://blog.koalite.com/2011/10/ioc-vs-servicelocator/" title="IoC vs ServiceLocator" target="_blank">contenedor de inversión de control</a>.</p>
<p>Esto quiere decir que a la hora de definir cualquier componente, ya sea un <code>Controller</code>, un <code>Service</code> o lo que sea, debemos indicar de qué otros componentes depende y angular se encargará de proporcionárselos a través de la función constructura (o de la función factoría que lo construya, que para el caso es lo mismo).</p>
<p>Todos los componentes registrados en angular son singleton, es decir, sólo existe una instancia de ellos en la aplicación y si hay varios componentes que dependen de un mismo objeto, todos recibirán la misma instancia del objeto. Esto es lo que permite utilizar fácilmente los servicios para almacenar estado, ya que dos <code>Controllers</code> que dependan de un mismo servicio estarán utilizando el mismo objeto y, por tanto, podrán compartir información a través de él.</p>
<p>El mayor inconveniente de usar un contenedor de inyección de dependencias en un lenguaje dinámico como javascript es que necesitamos definir explicítamente las dependencias ya que no existen un sistema de tipos que permita inferirlas automáticamente. Hace tiempo explicaba <a href="http://blog.koalite.com/2012/04/swiftcore-js-un-contenedor-ioc-para-javascript/" target="_blank">cómo funcionaba switfcore.js</a>, un contenedor IoC para javascript, y, aunque el API es distinta, las mismas pegas que comentaba en aquel post se puede aplicar a angular. </p>
<h3>Módulos</h3>
<p>Con todo lo que llevamos visto hasta ahora es fácil imaginarse que una aplicación con angular puede crecer bastante y gestionar las dependencias puede complicarse. </p>
<p>Para solucionar esto y permitirnos organizar un poco mejor el código, angular implementa un sistema de módulos de tal forma que siempre que se define un componente, se hace (o mejor dicho, se debería hacer) dentro de un módulo. Podemos asimilar estos módulos a <em>namespaces</em>, y podemos establecer dependencias entre módulos para que angular sepa qué componentes utilizar en cada momento.</p>
<h3>Resumen</h3>
<p>En estos dos posts hemos visto ya gran parte de los conceptos fundamentales que maneja angular. Quedan todavía algunas cosas más que me gustaría destacar, como el uso de directivas y filtros para encapsular pequeños bloques de comportamiento en la capa de presentación, pero eso será tema de otro post.</p>
<p><strong>Posts relacionados:</strong></p><ol>
<li><a href='http://blog.koalite.com/2012/04/inyeccion-de-dependencias-en-javascript-y-otros-lenguajes-dinamicos/' rel='bookmark' title='Inyección de dependencias en Javascript (y otros lenguajes dinámicos)'>Inyección de dependencias en Javascript (y otros lenguajes dinámicos)</a></li>
<li><a href='http://blog.koalite.com/2013/05/angularjs-conceptos-basicos/' rel='bookmark' title='AngularJS: Conceptos Básicos'>AngularJS: Conceptos Básicos</a></li>
<li><a href='http://blog.koalite.com/2012/05/dependencias-binarias-y-dependencias-de-codigo-fuente/' rel='bookmark' title='Dependencias binarias y dependencias de código fuente'>Dependencias binarias y dependencias de código fuente</a></li>
</ol><img src="http://feeds.feedburner.com/~r/KoalitesBlog/~4/WMFIX4SXkHU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.koalite.com/2013/05/angularjs-servicios-inyeccion-de-dependencias-y-modulos/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.koalite.com/2013/05/angularjs-servicios-inyeccion-de-dependencias-y-modulos/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=angularjs-servicios-inyeccion-de-dependencias-y-modulos</feedburner:origLink></item>
		<item>
		<title>AngularJS: Conceptos Básicos</title>
		<link>http://feedproxy.google.com/~r/KoalitesBlog/~3/YkdZ1zlvd8I/</link>
		<comments>http://blog.koalite.com/2013/05/angularjs-conceptos-basicos/#comments</comments>
		<pubDate>Mon, 27 May 2013 05:06:09 +0000</pubDate>
		<dc:creator>Juanma</dc:creator>
				<category><![CDATA[development]]></category>
		<category><![CDATA[angularjs]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://blog.koalite.com/?p=3028</guid>
		<description><![CDATA[Actualmente es cada vez más frecuente utilizar HTML5 como plataforma para desarrollar aplicaciones complejas. El aumento de rendimiento de los motores de javascript y las posibilidades que ofrecen HTML5 y CSS3 hacen que se pueda conseguir una experiencia cercana a las aplicaciones de escritorio, con la ventaja de poder ser casi multiplataforma (siempre hay pequeñas...  <a href="http://blog.koalite.com/2013/05/angularjs-conceptos-basicos/" class="more-link" title="Read AngularJS: Conceptos Básicos">Leer más &#187;</a>
No hay posts relacionados.]]></description>
				<content:encoded><![CDATA[<p>Actualmente es cada vez más frecuente utilizar HTML5 como plataforma para desarrollar aplicaciones complejas. El aumento de rendimiento de los motores de javascript y las posibilidades que ofrecen HTML5 y CSS3 hacen que se pueda conseguir una experiencia cercana a las aplicaciones de escritorio, con la ventaja de poder ser <em>casi</em> multiplataforma (siempre hay pequeñas diferencias con las que lidiar cuando saltamos de un navegador a otro).</p>
<img src="http://blog.koalite.com/wp-content/uploads/AngularJS-large.png" alt="Logo de AngularJS" class="alignright size-full wp-image-3029" />
<p>Para facilitar el desarrollo de este tipo de aplicaciones han ido surgiendo multitud de frameworks e incluso en este blog ya he escrito sobre algunos de ellos como <a href="http://blog.koalite.com/2012/01/tutorial-jquery-mobile-knockout-i-sentando-las-bases/" title="Tutorial jQuery Mobile + Knockout (I): Sentando las bases" target="_blank">Knockout y jQuery Mobile</a>. </p>
<p>Últimamente he estado trabajando con <a href="http://angularjs.org" target="_blank">angularjs</a>, un framework desarrollado por Google y, como creo que <a href="http://blog.koalite.com/2011/08/%c2%bfhacen-los-frameworks-tontos-a-los-desarrolladores/" title="¿Hacen los frameworks tontos a los desarrolladores?" target="_blank">es importante conocer los frameworks que se utilizan</a>, en estos post voy a intentar explicar los conceptos básicos sobre los que se asienta la filosofía de angular. </p>
<p><strong>OJO</strong>: en estos post no vas a encontrar información detallada sobre cómo trabajar con angular ni <a href="http://blog.koalite.com/2012/06/nos-gusta-demasiado-la-pornografia/" title="Nos gusta demasiado la pornografía" target="_blank">mucho código fuente</a>, si estás buscando ese tipo de detalles, te recomiendo que eches un vistazo a la <a href="http://docs.angularjs.org/guide/" target="_blank">documentación oficial</a> o sigas el <a href="http://docs.angularjs.org/tutorial/index" target="_blank">tutorial</a>.</p>
<h3>Arquitectura de la Capa de Presentación</h3>
<p>Angular ha sido definido como un framework <a href="https://plus.google.com/+AngularJS/posts/aZNVhj355G2" target="_blank">Model-View-Whatever</a>, es decir, Modelo-Vista-<em>Lo-que-sea</em>. Pretende de esta forma huir de la discusión entre <abbr title="Model-View-ViewModel">MVVM</abbr> vs <abbr title="Model-View-Controller">MVC</abbr> vs <abbr title="Model-View-Presenter">MVP</abbr>, pero lo cierto es que desde mi punto de vista tiene <strong>un marcado estilo MVVM</strong>.</p>
<p>Pese a este estilo MVVM, la aplicación se organiza entorno a <code>Controllers</code> responsables de construir los <code>ViewModels</code> que se enlazarán a las vistas. <strong>El papel que juegan los Controllers es un tanto limitado</strong>, por lo que no creo que se puedan comparar a los <code>Controllers</code> de la típica arquitectura web MVC, donde construyen un modelo &#8220;tonto&#8221; y luego se encargan ellos de gestionar las operaciones. En angular el controller puede construir un <code>ViewModel</code> que luego toma el control completo de las operaciones realizadas en la vista, por lo que básicamente actúan como factorías de <code>ViewModels</code>.</p>
<p>El enlace entre vistas y <code>ViewModels</code> se realiza mediante un sistema de <strong><em>databinding</em> declarativo bidireccional</strong>. Para ello se &#8220;decoran&#8221; los elementos html con <em>directivas</em> (de las que hablaremos más adelante) y se usa un sistema de plantillas parecido a <a href="http://handlebarsjs.com/" target="_blank">handlebars</a>:</p>
<pre class="brush:html">
&lt;div ng-controller="PhoneCtrl"&gt;
  &lt;ul&gt;
    &lt;li ng-repeat="phone in phones"&gt;{{phone.name}}&lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;
</pre>
<p>Una cosa que resulta extraña al principio es que no existe una definición del <code>ViewModel</code> como tal, sino que cada <code>Controller</code> tiene asociado un objecto <strong>$scope</strong> sobre el que construirlo. En el ejemplo anterior, el controller <code>PhoneCtrl</code> añadiría a su objeto <code>$scope</code> una lista de teléfonos, cada uno de ellos con una propiedad <code>name</code>, y eso sería lo que se enlaza a la vista.</p>
<p>Otro aspecto curioso es que <strong>los $scopes, es decir, ViewModels, están jerarquizados</strong>. Es decir, en una misma página podemos tener <code>$scopes</code> anidados unos con otros, y los <code>$scope</code> hijos pueden acceder a las propiedades y funciones de los <code>$scope</code> padre. </p>
<p>La raíz del árbol de <code>$scopes</code> es el <code>$rootScope</code> y podríamos considerarlo como el <code>ViewModel</code> global en el que colocar datos como el usuario loggeado actualmente o funciones de utilidad que queramos tener accesibles en cualquier otro <code>$scope</code>.</p>
<p>La jerarquía de <code>Controllers</code>/<code>$scopes</code> se corresponde con la jerarquía de elementos html en la página. Puesto que los <code>Controllers</code> están asociados a elementos html, si el elemento asociado a un <code>Controller</code> contiene un elemento asociado a otro <code>Controller</code>, el <code>$scope</code> del segundo podrá acceder a las propiedades del primero.</p>
<p>Para navegar entre las páginas de la aplicación se utilizan <strong>rutas</strong>, que podemos asociar a <code>Controllers</code> y fragmentos de html. Cuando se accede a una ruta, se carga ese fragmento de html (que puede residir en un archivo externo) mediante ajax y se inserta en la página actual en el elemento que esté marcado con la directiva <code>ng-view</code>:</p>
<pre class="brush:html">
&lt;body ng-app="MyApp"&gt;
  &lt;div ng-view&gt;
	&lt;!-- 
	  Aquí se irán cargando las vistas asociadas a las rutas
	  de la aplicación MyApp definida en el elemento body
	  con la directiva ng-app
	--&gt;
  &lt;/div&gt;
&lt;/body&gt;
</pre>
<p>Angular se encarga de mantener el historial de navegacion y todas esas cosas básicas, por lo que el manejo es bastante sencillo.</p>
<h3>Resumen</h3>
<p>Este post presenta una visión general de la forma en que se organiza la capa superior de angularjs, donde encontramos elementos conocidos (<code>Views</code>, <code>Controllers</code>, <code>ViewModels</code>, <code>Routes</code>), pero también algunas particularidades, como la jerarquización de los <code>ViewModels</code> o el reducido papel que juegan los <code>Controllers</code> en esta historia.</p>
<p>En próximos posts veremos más cosas interesantes de angular, como su organización en módulos, los servicios, el sistema de inyección de dependencias o el uso de directivas para encapsular comportamiento del interfaz de usario.</p>
<p>No hay posts relacionados.</p><img src="http://feeds.feedburner.com/~r/KoalitesBlog/~4/YkdZ1zlvd8I" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.koalite.com/2013/05/angularjs-conceptos-basicos/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		<feedburner:origLink>http://blog.koalite.com/2013/05/angularjs-conceptos-basicos/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=angularjs-conceptos-basicos</feedburner:origLink></item>
		<item>
		<title>Automatizar la compilación con MSBuild</title>
		<link>http://feedproxy.google.com/~r/KoalitesBlog/~3/GAzg5Egjcis/</link>
		<comments>http://blog.koalite.com/2013/05/automatizar-la-compilacion-con-msbuild/#comments</comments>
		<pubDate>Mon, 20 May 2013 05:06:42 +0000</pubDate>
		<dc:creator>Juanma</dc:creator>
				<category><![CDATA[development]]></category>
		<category><![CDATA[continuous integration]]></category>
		<category><![CDATA[msbuild]]></category>

		<guid isPermaLink="false">http://blog.koalite.com/?p=3016</guid>
		<description><![CDATA[Cuando en mi anterior post explicaba las ventajas de usar un servidor de integración continua, decía que el primer paso para mejorar el proceso de integración es automatizar el proceso de compilación. En este post voy a explicar con un ejemplo sencillo cómo podemos automatizar este proceso usando MSBuild. Para este ejemplo vamos a tener...  <a href="http://blog.koalite.com/2013/05/automatizar-la-compilacion-con-msbuild/" class="more-link" title="Read Automatizar la compilación con MSBuild">Leer más &#187;</a>
<strong>Posts relacionados:</strong><ol>
<li><a href='http://blog.koalite.com/2012/06/testear-javascript-con-phantomjs-qunit-y-msbuild/' rel='bookmark' title='Testear Javascript con PhantomJS, QUnit y MSBuild'>Testear Javascript con PhantomJS, QUnit y MSBuild</a></li>
</ol>]]></description>
				<content:encoded><![CDATA[<p>Cuando en mi anterior post explicaba las <a href="http://blog.koalite.com/2013/05/servidor-de-integracion-continua-una-buena-inversion/" title="Servidor de Integración Continua, una buena inversión" target="_blank">ventajas de usar un servidor de integración continua</a>, decía que el primer paso para mejorar el proceso de integración es automatizar el proceso de compilación. En este post voy a explicar con un ejemplo sencillo cómo podemos automatizar este proceso usando <a href="http://msdn.microsoft.com/en-us/library/wea2sca5%28v=vs.90%29.aspx" target="_blank">MSBuild</a>.</p>
<p>Para este ejemplo vamos a tener una solución de Visual Studio con dos proyectos: nuestra aplicación y un proyecto de tests, y nuestro script se va a encargar de realizar los siguientes pasos:</p>
<ol>
<li>Limpiar los resultados de ejecuciones anteriores.</li>
<li>Compilar la solución.</li>
<li>Ejecutar los tests.</li>
<li>Generar un paquete NuGet con el resultado.</li>
</ol>
<p>El objetivo será que alguien que se baje el proyecto desde el control de código fuente pueda realizar todos estos pasos ejecutando un único comando, sin necesidad de instalar manualmente ningún componente adicional en la máquina (más allá el SDK de .NET). De esta forma conseguiremos que la compilación siempre se realice en un entorno controlado, con versiones adecuadas de cada dependencia y sin posibilidad de introducir errores en el proceso por saltarnos algún paso manual.</p>
<h3>Estructura de Carpetas</h3>
<p>Cuando diseñamos un script de estas características, es importante definir una estructura de carpetas razonable. Esto, además de ayudarnos a crear el script, nos permitirá adaptarlo fácilmente a nuevos proyectos siempre que mantengamos la misma estructura de carpetas. </p>
<p>La estructura de carpetas que vamos a utilizar es la siguiente:</p>
<img src="http://blog.koalite.com/wp-content/uploads/folders1.png" alt="folders" class="aligncenter size-full wp-image-3017" />
<p>La carpeta <code>src</code> será la carpeta donde se encontrará la solución de Visual Studio y los paquetes NuGet utilizados. Toda la gestión de paquetes NuGet la haremos desde Visual Studio, donde además de instalarlos deberemos hablitar la opción de Restaurar Paquetes NuGet (<em>Enable NuGet Package Restore</em>). Podríamos hacerlo desde el propio script de compilación usando NuGet por línea de comandos, pero resulta más cómodo hacerlo desde Visual Studio.</p>
<p>En la carpeta <code>build</code> generemos los archivos compilados (.exes y .dlls) y la usaremos como carpeta de trabajo durante la compilación. </p>
<p>La carpeta <code>results</code> contendrá en resultado final del proceso. En nuestro caso será un paquete NuGet y un fichero xml con los resultados de la ejecución de los tests.</p>
<p>En la carpeta raíz del proyecto tendremos el script de compilación propiamente dicho (<code>sample.build</code>) y un fichero <code>build.cmd</code> para lanzar el proceso cómodamente.</p>
<h3>MSBuild: Targets y Tasks</h3>
<p>MSBuild utiliza archivos XML para configurar el proceso de compilación. Estos ficheros se organizan alrededor del concepto de <a href="http://msdn.microsoft.com/en-us/library/ms171462.aspx" target="_blank"><code>Target</code>s</a>. Un <code>Target</code> representa un proceso que se puede invocar de forma independiente y que, a su vez, puede depender de otros procesos.</p>
<p>En nuestro ejemplo, cada una de las fases de la compilación (limpiar, compilar, empaquetar, etc.) será un <code>Target</code>. Además crearemos un <code>Target</code> que dependa de todos los demás de manera que al invocarlo se ejecute el proceso completo.</p>
<p>La estructura del fichero incluyendo sólo los <code>Target</code>s es la siguiente:</p>
<pre class="brush:xml">
&lt;Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Default"&gt;
  
  &lt;Target Name="Default" DependsOnTargets="
          Clean;
          Build;
          RunTests;
          CreatePackage"/&gt;
    
  &lt;Target Name="Clean"&gt;...&lt;/Target&gt;
  &lt;Target Name="Build"&gt;...&lt;/Target&gt;
  &lt;Target Name="RunTests"&gt;...&lt;/Target&gt;
  &lt;Target Name="CreatePackage"&gt;...&lt;/Target&gt;

&lt;/Project&gt;
</pre>
<p>Para invocar un <code>Target</code> concreto por línea de comandos, debemos usar el parámetro <code>/t</code>. Si no indicamos nada, se ejecutará el <code>Target</code> por defecto (en este caso <code>Default</code>). Esto nos permite probar el script paso a paso:</p>
<pre>
msbuild.exe sample.build &larr; Esto ejecuta el target por defecto
msbuild.exe sample.bulid /t:RunTests &larr; Esto sólo ejecutaría el target RunTests
</pre>
<p>Para definir las acciones a realizar en cada <code>Target</code> se utilizan las <a href="http://msdn.microsoft.com/en-us/library/7z253716.aspx" target="_blank"><code>Task</code>s</a>. Las <code>Task</code>s son operaciones que nos ofrece MSBuild para manejar archivos y directorios, compilar proyectos, ejecutar comandos externos, etc. Además de la que incluye MSBuild puedes crear tus propias <code>Task</code>s o usar alguna de las librerías existentes, como <a href="http://msbuildextensionpack.codeplex.com/" target="_blank">MSBuild Extension Pack</a> o <a href="https://github.com/loresoft/msbuildtasks" target="_blank">MSBuild Community Tasks</a>).</p>
<p>Al crear el script podemos definir propiedades y grupos de ficheros usando los elementos <code>Property</code> e <code>ItemGroup</code>. Las propiedades funcionan de manera similar a las variables, y podemos utilizarlas para almacenar la ruta hasta ficheros, parámetros de compilación, etc. Los grupos de ficheros sirven, como era de esperar, para indicar un conjunto de ficheros que luego podremos referenciar en las <code>Task</code>s.</p>
<p>Aunque no voy a entrar en detalles para no alargar mucho el post, veamos cómo se implementa uno de los pasos: la ejecución de los tests:</p>
<pre class="brush:xml">
&lt;PropertyGroup&gt;
  &lt;BuildDir&gt;$(MSBuildProjectDirectory)\build\&lt;/BuildDir&gt;
  &lt;ResultsDir&gt;$(MSBuildProjectDirectory)\results\&lt;/ResultsDir&gt;
  &lt;NUnit&gt;$(MSBuildProjectDirectory)\src\packages\NUnit.Runners.2.6.2\tools\nunit-console.exe&lt;/NUnit&gt;
&lt;/PropertyGroup&gt;  
  
&lt;Target Name="RunTests"&gt;
  &lt;Exec Command='"$(NUnit)" "$(BuildDir)\Tests.dll"' WorkingDirectory='$(ResultsDir)'/&gt; 
&lt;/Target&gt;
</pre>
<p>En el <code>PropertyGroup</code> declaramos una serie de propieades con la ruta hasta el ejecutable de NUnit-Console.exe que se encargará de lanzar los tests, la carpeta donde se encuentran los ficheros compilados y la carpeta donde se almacenan el resultado de los tests. </p>
<p>El <code>Target RunTests</code> utiliza la <code>Task Exec</code> para ejecutar NUnit-Console.exe pasándole como parámetros el assembly con los tests e indicando como carpeta de trabajo la carpeta de resultados. Como podéis ver, podemos usar <em>string interpolation</em> con las propiedades que hemos definido antes para construir los argumentos de la <code>Task</code>.</p>
<p>En el <a href="https://github.com/jmhdez/msbuild-sample/blob/master/sample.build" target="_blank">script de compilación completo</a> podéis ver cómo se implementan el resto de <code>Target</code>s.</p>
<h3>Resumen</h3>
<p>Espero que este post haya servidor para desmitificar un poco el uso de MSBuild, podéis encontrar el <a href="https://github.com/jmhdez/msbuild-sample" target="_blank"><strong>código completo del proyecto</strong></a> en mi cuenta de github para jugar con él y ver cómo funciona.</p>
<p>Es importante tener una buena estructura de carpetas que podamos reutilizar de proyecto a proyecto, porque eso nos ayudará también a reutilizar el propio script de compilación. Lo normal es acabar con un script bastante genérico que luego se pueda adaptar a otros proyectos mediante la definición de propiedades y nuevos targets.</p>
<p>MSBuild es una herramienta muy potente y con él podemos automatizar muchas más cosas de las que se ven en este ejemplo. El mayor inconveniente que tiene (para mi gusto) es el uso de XML, que hace que resulte todo un poco más lioso, pero una vez que te acostumbras merece la pena.</p>
<p><strong>Posts relacionados:</strong></p><ol>
<li><a href='http://blog.koalite.com/2012/06/testear-javascript-con-phantomjs-qunit-y-msbuild/' rel='bookmark' title='Testear Javascript con PhantomJS, QUnit y MSBuild'>Testear Javascript con PhantomJS, QUnit y MSBuild</a></li>
</ol><img src="http://feeds.feedburner.com/~r/KoalitesBlog/~4/GAzg5Egjcis" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.koalite.com/2013/05/automatizar-la-compilacion-con-msbuild/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.koalite.com/2013/05/automatizar-la-compilacion-con-msbuild/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=automatizar-la-compilacion-con-msbuild</feedburner:origLink></item>
		<item>
		<title>Servidor de Integración Continua, una buena inversión</title>
		<link>http://feedproxy.google.com/~r/KoalitesBlog/~3/VNaycY-t8_k/</link>
		<comments>http://blog.koalite.com/2013/05/servidor-de-integracion-continua-una-buena-inversion/#comments</comments>
		<pubDate>Mon, 13 May 2013 05:06:56 +0000</pubDate>
		<dc:creator>Juanma</dc:creator>
				<category><![CDATA[development]]></category>
		<category><![CDATA[agile]]></category>
		<category><![CDATA[continuous integration]]></category>
		<category><![CDATA[software development]]></category>

		<guid isPermaLink="false">http://blog.koalite.com/?p=2997</guid>
		<description><![CDATA[Siempre he pensado que las herramientas que usamos en el desarrollo de software deben estar seleccionadas y adaptadas en función del tipo de desarrollo que realizamos, el equipo, la metodología, etc. Sin embargo, hay tres herramientas básicas que uso en todos los proyectos: un sistema de control de versiones (desde git hasta subversion), un gestor...  <a href="http://blog.koalite.com/2013/05/servidor-de-integracion-continua-una-buena-inversion/" class="more-link" title="Read Servidor de Integración Continua, una buena inversión">Leer más &#187;</a>
No hay posts relacionados.]]></description>
				<content:encoded><![CDATA[<p>Siempre he pensado que las herramientas que usamos en el desarrollo de software deben estar seleccionadas y adaptadas en función del tipo de desarrollo que realizamos, el equipo, la metodología, etc. </p>
<p>Sin embargo, hay tres herramientas básicas que uso en todos los proyectos: un sistema de control de versiones (desde git hasta subversion), un gestor de bugs/tareas (aunque sea una hoja Excel) y un servidor de integración continua. </p>
<p>Las dos primeras herramientas de la lista están muy extendidas y no conozco ningún equipo de desarrollo que trabaje sin ellas, pero lo del servidor de <a href="http://en.wikipedia.org/wiki/Continuous_integration" target="_blank">integración continua</a> es menos conocido y no se usa tanto.</p>
<h3>¿Qué es la integración continua?</h3>
<p>La integración continua es una practica ligada a la <a href="http://en.wikipedia.org/wiki/Extreme_programming" target="_blank">programación extrema</a> que consiste en automatizar el proceso de integración de código para poder realizarlo de la manera más continuada posible.</p>
<p>Cuando llega el momento de liberar una nueva versión de una aplicación hay que realizar un proceso de integración de todos los componentes que forman parte de la aplicación. Esto implica realizar varios pasos, como obtener el código fuente, compilarlo, ejecutar los tests, etc.</p>
<p>En muchos proyectos este es <strong>un proceso completamente manual</strong>, en el mejor de los casos documentado en forma de <em>checklist</em> en alguna parte, pero a fin de cuentas, siempre que haya pasos manuales, antes o después habrá algún error y pondremos en producción una aplicación con el número de versión incorrecto, que no ha pasado las pruebas automatizadas o que no estará correctamente etiquetada en el control de código fuente.</p>
<p>Si queremos mejorar este proceso, <strong>el primer paso es automatizarlo</strong>. Para ello contamos con diferentes herramientas, generalmente basadas en algún tipo de <em>script de compilación</em>. En .NET se suele utilizar <a href="http://msdn.microsoft.com/en-us/library/wea2sca5%28v=vs.90%29.aspx" target="_blank">MSBuild</a>, en Javascript hay opciones como <a href="http://gruntjs.com/" target="_blank">Grunt</a>, en Ruby existe <a href="http://rake.rubyforge.org/" target="_blank">Rake</a>&#8230; Al final todas se basan en lo mismo, poder definir de una manera más o menos cómoda las tareas a ejecutar para poder lanzarlas en un único paso.</p>
<p>Un <strong>ejemplo de script</strong> de compilación para una aplicación de escritorio podría contar con los siguientes pasos:</p>
<ol>
<li>Obtener la última versión del código fuente.</li>
<li>Actualizar la información de versión en el fichero <em>AssemblyInfo.cs</em> basándose en la convención que se haya establecido (número de compilación, fecha, etc.).</li>
<li>Ejecutar una herramienta de análisis estático como <a href="http://msdn.microsoft.com/en-us/library/bb429476%28v=vs.80%29.aspx" target="_blank">FxCop</a> o <a href="http://www.campwoodsw.com/sourcemonitor.html" target="_blank">SourceMonitor</a> para detectar defectos en el código.
<li>Compilar los proyectos.</li>
<li>Ejecutar las suites de tests automatizados.</li>
<li>Generar la documentación (manuales, guías de instalación, etc.).</li>
<li>Crear los paquetes de instalación.</li>
<li>Etiquetar en el control de código fuente la versión del código usada para generar estos instaladores, de forma que luego podamos trazar <em>exactamente</em> qué codigo fuente se uso para generar cada versión de la aplicación.</li>
</ol>
<p>Preparar este script puede llevar un tiempo y no es una tarea fácil la primera vez que lo haces, pero una vez que has aprendido es bastante sencillo adaptarlo para nuevos proyectos, por lo que la inversión de tiempo se recupera rápidamente.</p>
<h3>¿Qué aporta un servidor de integración continua a este proceso?</h3>
<p>Una vez que contamos con este script, cada vez que queramos realizar una integración completa (potencialmente liberable) del código, podremos hacerlo en un sólo paso ejecutándolo desde cualquier equipo; entonces, ¿para qué hace falta un servidor de integración continua?</p>
<p>El servidor de integración continua se encarga de ejecutar este script automáticamente según la programación que establezcamos, por ejemplo cada vez que se se realiza un <em>commit/checkin/push</em> al control de código fuente. </p>
<p>Además, podemos establecer distintas configuraciones para un mismo proyecto. Por ejemplo, podemos crear una configuración que realice una compilación &#8220;rápida&#8221;, ejecutando sólo los test unitarios cada vez que realizamos un <em>commit</em>, y programar una compilación &#8220;completa&#8221;, que ejecuta también los tests de integración y genera los instaladores todas las noches (las típicas <em>nightly builds</em>).</p>
<p>Realizar el proceso de integración de continuamente en un servidor tiene varias <strong>ventajas</strong>:</p>
<p>Por una parte, <strong>evita discrepancias entre las versiones</strong> utilizadas para generar los entregables. Al realizar la compilación en el servidor se garantiza que siempre se usa la misma versión del compilador, SDKs, librerías de terceros, etc. Eso es difícil de conseguir si la compilación se realiza cada vez en equipo distintos donde podría haber distintas versiones de cosas instaladas globalmente (assemblies en el GAC, módulos node instalados con <code>npm install -g</code>, etc.), provocando cambios en el comportamiento final de la aplicación dependiendo del equipo en que se ha compilado. Este tipo de errores son complicados de diagnosticar y pueden hacerte perder mucho tiempo.</p>
<p>Además, permite <strong>detectar rápidamente errores</strong> introducidos por cambios en el código. Aunque se supone que antes de hacer un <em>commit</em> cada desarrollador debería asegurarse de que todo funciona y ejecutar los tests en su equipo, a veces las suites de tests tardan más tiempo del que nos gustaría en ejecutarse (especialmente si tenemos tests de integración) o directamente al desarrollador se le olvida. Al hacer que el código se compile cada vez que se hace el <em>commit</em> en el servidor de integración continua, los errores se detectan en cuestión de minutos en lugar de hacerlo varios días después cuando alguien intenta liberar una nueva versión.</p>
<p>Otra ventaja de usar un servidor de integración continua es que podemos <strong>mantener un histórico</strong> de los resultados de las compilaciones. Dependiendo de los análisis que estemos realizando sobre nuestro código, esto nos permite conocer como ha evolucionado la cobertura de código de los tests, la complejidad ciclomática media y todas esas métricas que tanto nos gustan (otra cosa es que sirvan para algo, pero eso lo dejamos para otro día).</p>
<p>En teoría, si este proceso se lleva al extremo cada vez que se hace un <em>commit</em> al control de código fuente el servidor de integración continua sería capaz de detectar si todo es correcto y en ese caso hacer un despliegue automático. Eso es lo que se conoce como entrega continua (<em>continuous delivery o continuous deployment</em>) y hay proyectos que son capaces de hacerlo, aunque no siempre es viable (ni recomendable).</p>
<h3>Conclusiones</h3>
<p>Montar un servidor de integración continua puede resultar un poco complicado al principio. Hay <a href="http://en.wikipedia.org/wiki/Comparison_of_continuous_integration_software" target="_blank">muchas opciones disponibles</a>, algunas más sencillas y otras más complejas, pero donde realmente reside la complicación es en estructurar tu proyecto para que todas las tareas sean fácilmente automatizables. </p>
<p>Aunque pueda parecer que este tipo de técnicas sólo son aplicables a equipos muy grandes que hacen aplicaciones muy complejas, no es así. Yo lo he utilizado en proyecto con un único desarrollador en los que lo único que se hacía era compilar el código y generar un instalador, y aun así merece la pena. Tener la seguridad de que lo que has compilado es lo que se debía compilar, que la versión está correctamente asignada y que el instalador lo has generado con los binarios correctos (y no con otros que compilaste dos horas atrás), te permite vivir mucho más tranquilo.</p>
<p>Es verdad que el coste inicial es alto, pero lo bueno es que las técnicas necesarias son muy fáciles de reutilizar de un proyecto a otro, por lo que una vez que has automatizado la integración del primer proyecto, si sigues una estructura común en todos tus proyectos, el resto es cuestión de ajustar un par de rutas en los scripts de compilación y los tienes listos en minutos (literalmente).</p>
<p>No hay posts relacionados.</p><img src="http://feeds.feedburner.com/~r/KoalitesBlog/~4/VNaycY-t8_k" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.koalite.com/2013/05/servidor-de-integracion-continua-una-buena-inversion/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://blog.koalite.com/2013/05/servidor-de-integracion-continua-una-buena-inversion/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=servidor-de-integracion-continua-una-buena-inversion</feedburner:origLink></item>
		<item>
		<title>Open Source en un mundo Microsoft</title>
		<link>http://feedproxy.google.com/~r/KoalitesBlog/~3/hX9Fjofg0bU/</link>
		<comments>http://blog.koalite.com/2013/05/open-source-en-un-mundo-microsoft/#comments</comments>
		<pubDate>Mon, 06 May 2013 05:06:58 +0000</pubDate>
		<dc:creator>Juanma</dc:creator>
				<category><![CDATA[opinion]]></category>
		<category><![CDATA[open source]]></category>

		<guid isPermaLink="false">http://blog.koalite.com/?p=2982</guid>
		<description><![CDATA[Hace poco me entretenía con la enésima discusión en twitter sobre las maravillas y desastres de node.js y acabó saliendo un tema que hacía tiempo que no veía: el uso de librerías y plataformas de código abierto. Sobre esto del código abierto hay posiciones muy extremas, tanto en un sentido como en otro (me atrevería...  <a href="http://blog.koalite.com/2013/05/open-source-en-un-mundo-microsoft/" class="more-link" title="Read Open Source en un mundo Microsoft">Leer más &#187;</a>
No hay posts relacionados.]]></description>
				<content:encoded><![CDATA[<p>Hace poco me entretenía con la enésima discusión en twitter sobre las maravillas y desastres de node.js y acabó saliendo un tema que hacía tiempo que no veía: el uso de librerías y plataformas de código abierto.</p>
<p>Sobre esto del código abierto hay posiciones muy extremas, tanto en un sentido como en otro (me atrevería a decir que hay mayor extremismo entre los defensores del código abierto), pero dejando a un lado fanatismos, creo que es posible realizar un análisis más pragmático del asunto.</p>
<p><strong>OJO</strong>: no voy a entrar en discusiones ético-filosóficas sobre las bondades de uno u otro sistema. Tampoco voy a meterme en las diferencias entre código abierto, software libre y software gratis, porque aunque creo que son importantes, prefiero mantener un enfoque más &#8220;práctico&#8221; en este post.</p>
<h3>Un mundo guiado por un único fabricante</h3>
<p>Los que trabajamos con plataformas de Microsoft hemos estado muy acostumbrados a utilizar únicamente lo que nos proporcionaba Microsoft que, por otra parte, no era poco y cubría bastante bien la mayoría de situaciones a las que nos teníamos que enfrentar.</p>
<p>Si necesitabas hacer una aplicación web, tirabas de WebForms (o ahora de ASP.NET MVC). Si querías un ORM, Entity Framework. Para bases de datos, SQL Server, y si tenía que ser embebida, SQL CE. Esa era <em>la forma de hacer las cosas</em> y mucha gente no se la cuestionaba.</p>
<p>Recuerdo que hace unos 6 años empecé a introducir en mi trabajo del mundo real librerías &#8220;no Microsoft&#8221;. Primero log4net, luego Castle Windsor, después NHibernate, &#8230; </p>
<p>Al principio tuve que vencer cierta reticencia entre algunos compañeros de trabajo, pero el tiempo me ha dado la razón y hoy en día usamos muchas librerías &#8220;de terceros&#8221;, la mayoría de ellas open source, y debo decir que han mejorado considerablemente nuestros procesos de desarrollo (tanto a nivel de productividad como a nivel de calidad).</p>
<p>Aún hoy hay empresas en que plantear <strong>usar tecnologías no Microsoft dentro de un proyecto .NET se considera una mala idea</strong> y existen directores técnicos que directamente vetan el uso de estas tecnologías. </p>
<p>Es como el viejo dicho de &#8220;<a href="http://corporatevisions.com/blog/2007/06/11/no-one-ever-got-fired-for-buying-ibm/" target="_blank">nunca despidieron a nadie por comprar IBM</a>&#8220;, parece que si te ciñes al uso de tecnologías soportadas por Microsoft, nada puede salir mal, o al menos si sale mal, la culpa no será de tu elección tecnológica.</p>
<p>Sin embargo, gracias a la exposición constante que tenemos los desarrolladores a <a href="http://blog.koalite.com/2013/04/lo-mejor-de-javascript/" title="Lo mejor de Javascript" target="_blank">otras comunidades</a> y a la mezcla de ideas procedentes de otros lenguajes, ya no es tan raro emplear herramientas de código abierto en proyectos de .NET.</p>
<p>De hecho, en los últimos años la propia Microsoft ha abrazado ese concepto con herramientas con Nuget y las últimas librerías desarrolladas por Microsoft están siguiendo este modelo de desarrollo (ahí tenemos Entity Framework aceptando pull requests de desarrolladores externos como <a href="http://geeks.ms/blogs/unai/archive/2013/04/25/ef-6-nuevas-peque-241-as-grandes-cosas.aspx" target="_blank">Unai</a>).</p>
<h3>Una cuestión de confianza</h3>
<p>En realidad, el problema que tiene mucha gente con el software de código abierto no tiene nada que ver con que el código sea abierto o cerrado o con que la licencia y el modelo de desarrollo sea más o menos libre, sino con <strong>quién está detrás del código</strong>.</p>
<p>Existe una sensación demasiado habitual de que un proyecto de código abierto que no está dirigido por una organización comercial es algo en lo que no se puede confiar, pero el tiempo nos ha enseñado que esto no es cierto.</p>
<p>Hay proyectos realizados por voluntarios que llevan mucho tiempo funcionando bien y tienen bases de usuarios tan grandes que los convierten en soluciones mucho más sólidas que sus equivalentes comerciales. Los más extendidos han conseguido además el apoyo de grandes empresas, lo que les da ese plus de confianza que parece necesario para usarlos en ciertos entornos (estoy pensando en casos como jQuery).</p>
<p>Al final, lo más importante para que una librería o plataforma tenga un buen soporte es que cuente con un número suficiente de usuarios. Si una tecnología alcanza el suficiente grado de adopción, siempre será más fácil encontrar alguien dispuesto a soportarla, ya sea de manera altruista respondiendo preguntas en Stack Overflow o de forma comercial cobrando por servicios de consultoría.</p>
<p>En ese sentido, a la hora de decidir si una librería determinada o una plataforma concreta son confiables, me parece más importante <strong>tener en cuenta la base de usuarios</strong> que quién está detrás de ella. De hecho, hay ocasiones en que tener una empresa detrás puede llegar a ser contraproducente porque puede que mantener esa tecnología viva vaya en contra de los objetivos económico/estratégicos de la empresa (preguntádselo a los que decidieron usar Linq2SQL para ver cómo en poco tiempo era descontinuado y reemplazado por Entity Framework).</p>
<p>También es cierto que existen empresas capaces de garantizar la supervivencia de un producto y el soporte del mismo durante un tiempo prefijado. Ahí están casos como Canonical (una empresa tan &#8220;comercial&#8221; como Microsoft) y sus <a href="https://wiki.ubuntu.com/LTS" target="_blank">releases de Ubuntu con soporte extendido</a> o los ciclos de vida que ofrece Microsoft para productos como <a href="http://support.microsoft.com/lifecycle/search/?sort=PN&amp;alpha=SQL" target="_blank">SQL Server</a>.</p>
<h3>Conclusiones</h3>
<p>Este post no pretende ser un alegato a favor del movimiento Open Source y en contra de Microsoft. Nada más lejos de mi intención. Como he dicho al principio, creo que hay demasiado fanatismo en ambos bandos y se tiende a perder de vista el objetivo real: <strong>generar valor desarrollando software</strong>.</p>
<p>A la hora de elegir sobre qué plataforma desarrollar o qué librería utilizar hay muchos factores a tener en cuenta y, sin duda, el soporte que podamos obtener es uno de ellos, pero también lo es la facilidad para desarrollar sobre ella, el rendimiento que podamos conseguir y la disponibilidad de buenos desarrolladores.</p>
<p>Los típicos argumentos de &#8220;código cerrado malo porque no lo puedo tocar&#8221;, &#8220;código abierto malo porque nadie me lo va a mantener&#8221; suelen caerse por su propio peso. Todos conocemos ejemplos de productos comerciales que han sido descontinuados dejando de dar soporte a sus usuarios, y todos usamos un montón de código abierto que no sabríamos tocar ni en un millón de años.</p>
<p>Lo que cuenta es resolver un problema y <strong>buscar las mejores herramientas para ello</strong>, que a veces serán open source y a veces no. No dejes que eso sea lo único que te guíe a la hora de elegir las herramientas más adecuadas para tu próximo proyecto. El código (abierto o cerrado) importa, pero el contexto más.</p>
<p>No hay posts relacionados.</p><img src="http://feeds.feedburner.com/~r/KoalitesBlog/~4/hX9Fjofg0bU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.koalite.com/2013/05/open-source-en-un-mundo-microsoft/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://blog.koalite.com/2013/05/open-source-en-un-mundo-microsoft/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=open-source-en-un-mundo-microsoft</feedburner:origLink></item>
		<item>
		<title>Geolocalizando direcciones IP con C#</title>
		<link>http://feedproxy.google.com/~r/KoalitesBlog/~3/AyX3MePU62k/</link>
		<comments>http://blog.koalite.com/2013/05/geolocalizando-direcciones-ip-con-csharp/#comments</comments>
		<pubDate>Thu, 02 May 2013 05:06:24 +0000</pubDate>
		<dc:creator>Juanma</dc:creator>
				<category><![CDATA[development]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[geolocation]]></category>

		<guid isPermaLink="false">http://blog.koalite.com/?p=2966</guid>
		<description><![CDATA[Conocer a nuestros usuarios es cada vez más importante para poder ofrecerles servicios más ajustados a sus necesidades. Cuando estamos trabajando con una aplicacion web existen herramientas como Google Analytics que nos permiten recabar todo tipo de información (también podemos usar Google Analytics con aplicaciones de escritorio) , pero hay veces que necesitamos conocer detalles...  <a href="http://blog.koalite.com/2013/05/geolocalizando-direcciones-ip-con-csharp/" class="more-link" title="Read Geolocalizando direcciones IP con C#">Leer más &#187;</a>
No hay posts relacionados.]]></description>
				<content:encoded><![CDATA[<p>Conocer a nuestros usuarios es cada vez más importante para poder ofrecerles servicios más ajustados a sus necesidades. </p>
<p>Cuando estamos trabajando con una aplicacion web existen <strong>herramientas como Google Analytics</strong> que nos permiten recabar todo tipo de información (también podemos usar <a href="http://blog.koalite.com/2012/03/seguimiento-de-una-aplicacion-de-escritorio-con-google-analytics/" title="Seguimiento de una aplicación de escritorio con Google Analytics" target="_blank">Google Analytics con aplicaciones de escritorio</a>) , pero hay veces que necesitamos conocer detalles como la ubicación del usuario en el momento de interactuar con él, y no sólo a posteriori para realizar análisis estádísticos.</p>
<p>Una de las cosas que nos puede ayudar a mejorar la experiencia de usuario es conocer el lugar en el que se encuentra el usuario. </p>
<p>En HTML5 existe un <a href="http://www.w3schools.com/html/html5_geolocation.asp" target="_blank">api de geolocalización</a>, pero no siempre está disponible y, además, requiere del consentimiento del usuario. </p>
<p>Otra opción es utilizar lo que se conoce como geolocalización de IP, que consisten en tratar de averiguar la ubicación del usuario basándonos en su dirección IP. Esto no es completamente fiable porque el usuario puede acceder a través de un proxy o usar una IP que está físicamente alejada de su ubicación real (la IP está realmente asociada al ISP no al equipo del usuario), pero en muchas ocasiones es suficiente.</p>
<h3>Geolocalizando una IP</h3>
<p>Para conocer la ubicación del usuario existen muchos servicios, pero en este post vamos a ver uno muy simple y, además, gratuito (con ciertos límites): <a href="http://ipinfodb.com/index.php" target="_blank">IPInfoDB</a>.</p>
<p>El servicio ofrecido por IPInfoIDB requiere que nos registremos para conseguir un <em>API KEY</em>, pero este registro es completamente gratuito.</p>
<p>Una vez completado el registro, el código necesario para geolocalizar una IP en C# es muy sencillo:</p>
<pre class="brush:csharp">
public Location GeoLocate(string ip)
{
    const string API_KEY = "YOUR_API_KEY";

    var url = "http://api.ipinfodb.com/v3/ip-city/?key={0}&amp;ip={1}&amp;format=xml";
	
    var doc = XDocument.Load(string.Format(url, API_KEY, ip));

    return new Location
    {
        CountryCode = doc.Descendants("countryCode").First().Value,
        CountryName = doc.Descendants("countryName").First().Value,
        Region = doc.Descendants("regionName").First().Value,
        City = doc.Descendants("cityName").First().Value,
        ZipCode = doc.Descendants("zipCode").First().Value,
        Latitude = decimal.Parse(doc.Descendants("latitude").First().Value, CultureInfo.InvariantCulture),
        Longitude = decimal.Parse(doc.Descendants("longitude").First().Value, CultureInfo.InvariantCulture)
    };
}
</pre>
<p>Como véis no hay mucha complicación, cargamos en un documento XML los datos devueltos por el servicio y construimos un objeto <code>Location</code> a partir de la información contenida en el documento XML.</p>
<h3>No tan rápido</h3>
<p>Antes de empezar a usar este código en tu próxima aplicación, hay que tener en cuenta algunas limitaciones:</p>
<ul>
<li>El código anterior es <strong>código de demo</strong>. No hay ningún tipo de control de errores, y lo último que querrías es que tu aplicación dejase de funcionar porque el servicio de IPInfoDB está caído. Una buena opción cuando uno se integra con este tipo de servicios es aplicar el <a href="http://blog.koalite.com/2012/08/patron-disyuntor-circuit-breaker/" title="El Patrón Disyuntor (Circuit Breaker)" target="_blank">patrón disyuntor (<em>circuit breaker</em>)</a>.</li>
<li>Utilizar esta técnica para geolocalizar IPs requiere una llamada a un servidor externo, y esa llamada puede ser más lenta de lo que nos gustaría. Es importante tenerlo en cuenta y sería muy recomendable realizarla de forma asíncrona (y con un timeout, por cierto) para evitar bloquear nuestra aplicación eternamente.</li>
</ul>
<h3>Conclusiones</h3>
<p>Geolocalizar una IP usando C# es muy sencillo con servicios como IPInfoDB y puede ayudarnos a hacer <strong>aplicaciones más inteligentes</strong> que resulten más agradables de utilizar para nuestros usuarios, pero no hay que olvidar que estamos introduciendo una <strong>dependencia sobre un servicio externo</strong> y hay infinidad de cosas que pueden salir mal, por lo que nuestra aplicación deberá estar preparada para tratar con estas contingencias.</p>
<p>No hay posts relacionados.</p><img src="http://feeds.feedburner.com/~r/KoalitesBlog/~4/AyX3MePU62k" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.koalite.com/2013/05/geolocalizando-direcciones-ip-con-csharp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.koalite.com/2013/05/geolocalizando-direcciones-ip-con-csharp/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=geolocalizando-direcciones-ip-con-csharp</feedburner:origLink></item>
	</channel>
</rss>
