<?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>Artesanos de Software</title>
	
	<link>http://artesanos.de/software</link>
	<description>El lugar d' los q' desarrollan buen software</description>
	<lastBuildDate>Wed, 22 Feb 2012 20:00:17 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/ArtesanosDeSoftware" /><feedburner:info uri="artesanosdesoftware" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Podcast de ViveCodigo00x14 : Entrevista con Agustín Ramos</title>
		<link>http://feedproxy.google.com/~r/ArtesanosDeSoftware/~3/xejxhabAxDE/</link>
		<comments>http://artesanos.de/software/2012/02/22/podcast-de-vivecodigo00x14-entrevista-con-agustin-ramos/#comments</comments>
		<pubDate>Wed, 22 Feb 2012 20:00:17 +0000</pubDate>
		<dc:creator>neodevelop</dc:creator>
				<category><![CDATA[Sin categoría]]></category>

		<guid isPermaLink="false">http://artesanos.de/software/?p=284</guid>
		<description><![CDATA[Desde el sitio de ViveCodigo nos complace presentar en esta ocasi&#243;n a Agust&#237;n Ramos(@MachiesAreUs), un experimentado desarrollador que ha venido impulsando el concepto de Artesan&#237;a de Software. En esta entrevista Agust&#237;n nos explica &#191;Qu&#233; es y como se compone la Artesan&#237;a?, as&#237; tambi&#233;n, nos platica acerca de su experiencia al impulsar y practicar los principios [...]]]></description>
			<content:encoded><![CDATA[<p>
	<embed flashvars="audioUrl=http://s3.amazonaws.com/media.vivecodigo.org/podcast/temporada0/ViveCodigo00x14.mp3" height="27" quality="best" src="http://www.google.com/reader/ui/3523697345-audio-player.swf" type="application/x-shockwave-flash" width="400"></embed></p>
<div>
	Desde el sitio de ViveCodigo nos complace presentar en esta ocasi&oacute;n a Agust&iacute;n Ramos(@MachiesAreUs), un experimentado desarrollador que ha venido impulsando el concepto de Artesan&iacute;a de Software.</div>
<div>
	En esta entrevista Agust&iacute;n nos explica &iquest;Qu&eacute; es y como se compone la Artesan&iacute;a?, as&iacute; tambi&eacute;n, nos platica acerca de su experiencia al impulsar y practicar los principios que la rigen.</div>
<div>
	Sin lugar a dudas, el contenido de esta entrevista es fundamental para quienes nos dedicamos a desarrollar software.</div>
<div>
	El art&iacute;culo completo:</div>
<div>
	<a href="http://vivecodigo.org/2012/02/22/podcast-14-de-la-temporada-0/">http://vivecodigo.org/2012/02/22/podcast-14-de-la-temporada-0/</a></div>
<p>
	<iframe frameborder="0" height="253" src="http://player.vimeo.com/video/37228434?color=ff9933" width="450"></iframe></p>
<p>
	&nbsp;</p>
<p><!--break--></p>
<img src="http://feeds.feedburner.com/~r/ArtesanosDeSoftware/~4/xejxhabAxDE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://artesanos.de/software/2012/02/22/podcast-de-vivecodigo00x14-entrevista-con-agustin-ramos/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://artesanos.de/software/2012/02/22/podcast-de-vivecodigo00x14-entrevista-con-agustin-ramos/</feedburner:origLink></item>
		<item>
		<title>TDD Cómo y porqué: Una guía para los no iniciados</title>
		<link>http://feedproxy.google.com/~r/ArtesanosDeSoftware/~3/jkAiFuQkWpE/</link>
		<comments>http://artesanos.de/software/2012/02/13/tdd-como-y-porque-una-guia-para-los-no-iniciados/#comments</comments>
		<pubDate>Mon, 13 Feb 2012 22:28:16 +0000</pubDate>
		<dc:creator>Alfredo Chavez</dc:creator>
				<category><![CDATA[Sin categoría]]></category>

		<guid isPermaLink="false">http://artesanos.de/software/?p=273</guid>
		<description><![CDATA[Introducción Esta es mi primera contribución para Artesanos de Software. Soy un desarrollador de software &#8220;de la vieja escuela&#8221;, por decirlo de alguna manera. Hace años, pensaba que tenía bastante dominado este asunto de la programación, hasta que me topé con Extreme Programming y todo el ecosistema de Métodos Ágiles que se ha desarrollado desde [...]]]></description>
			<content:encoded><![CDATA[<div>
<h2>Introducción</h2>
<p>Esta es mi primera contribución para <em>Artesanos de Software</em>.</p>
<p>Soy un desarrollador de software &#8220;de la vieja escuela&#8221;, por decirlo de alguna manera. Hace años, pensaba que tenía bastante dominado este asunto de la programación, hasta que me topé con <a title="An agile software development resourse" href="http://xprogramming.com/" target="_blank"><em>Extreme Programming</em></a> y todo el ecosistema de Métodos Ágiles que se ha desarrollado desde entonces. Para mi, todo cambió desde entonces y me dí cuenta de lo poco que sé en realidad. He estado practicando la disciplina del Desarrollo Dirigido por Pruebas o <acronym title="Test Driven Development">TDD</acronym> ahora si y ahora no por los últimos ocho años. Quienes me conozcan, sabrán que no ha sido ni por mucho un proceso fácil ni mucho menos rápido. Sin embargo, si solo pudiera lograr que todos los desarrolladores de mi equipo adoptaran una sola práctica de <acronym title="Extreme Programming">XP</acronym>, esa sería <acronym title="Test Driven Development">TDD</acronym>.</p>
<p>Las excusas abundan, es simplemente demasiado fácil ceder y dejar de hacerlo. Desde los clásicos <em>&#8220;en mi empresa no me lo permiten&#8221;</em> y <em>&#8220;mi jefe dice que me pagan por escribir funcionalidad, no pruebas&#8221;</em> hasta los no tan infrecuentes <em>&#8220;las pruebas son trabajo de QA, no mio&#8221;</em> o <em>&#8220;esta porquería es una mi3rd@, ¡es imposible de probar!&#8221;</em>. Lo sé porque yo mismo he estado en esas situaciones, he dado las mismas excusas y ni una sola vez puedo decir que el resultado haya sido positivo para mi o para el proyecto.</p>
<p>El propósito de este blog es allanar un poco el camino para aquellos que estén considerando aprender <acronym title="Test Driven Development">TDD</acronym> y posiblemente utilizarlo en su trabajo o en proyectos personales. Para mi no ha sido fácil y aún estoy aprendiendo. Si alguien puede sacar algo en claro de mis propias experiencias pasadas, creo que eso será más que suficiente para compensar el tiempo invertido en el mismo.</p>
<p>Este blog debe considerarse un trabajo en progreso. La idea del mismo comenzó hace probablemente tres o cuatro meses. Simplemente hay demasiados temas y ángulos para cubrir de una sola vez. El material disponible en la red, las anécdotas personales, las técnicas, los &#8220;pitfalls&#8221; (alguien, español por favor?), los &#8220;tips&#8221;, etc. son suficientes como para llenar uno o varios libros así que no puedo esperar cubrir todas las bases en un solo post. Debido a ello, en este post me concentraré exclusivamente en el tema de las pruebas unitarias. Solo el tiempo dirá si soy capaz de llevar este proyecto a buen término <tt> <img src='http://artesanos.de/software/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </tt></p>
</div>
<div>
<h2>¿Qué es <acronym title="Test Driven Development">TDD</acronym>?</h2>
<p><acronym title="Test Driven Development">TDD</acronym> es una criatura extraña. Es simple de definir, pero su definición parece ir en contra del sentido común. Es sencilla de explicar, pero difícil de llevar a cabo. Y una vez que superas la resistencia intelectual inicial (the &#8220;<acronym title="¿Qué carajos?">WTF</acronym> factor&#8221;) y lo entiendes, es difícil de dominar.</p>
<dl>
<dt>Definición:</dt>
<dd>Es una disciplina que promueve el desarrollo de software con altos niveles de calidad, simplicidad de diseño y productividad del programador, mediante la utilización de una amplia gama de tipos de pruebas automáticas a lo largo de todo el ciclo de vida del software. El principio fundamental es que las pruebas se escriben antes que el software de producción y estas constituyen la especificación objetiva del mismo.</dd>
</dl>
<p>La primera parte de la definición suena todo miel sobre hojuelas. ¿Quién no quiere software confiable, bien diseñado y producido rápidamente?. Sin embargo, todo esto no viene gratuitamente; la palabra clave aquí es <em>disciplina</em>.</p>
<dl>
<dt>Disciplina:</dt>
<dd>Doctrina, instrucción de una persona, especialmente en lo moral. Observancia de las leyes y ordenamientos de la profesión o instituto.</dd>
</dl>
<p>Esto nos lleva a la conclusión de que si <acronym title="Test Driven Development">TDD</acronym> es en efecto una disciplina, entonces no es algo que aplicamos &#8220;según nos vayamos sintiendo&#8221;, más bien, es algo que debe formar parte integral de nuestra profesión o arte (según la perspectiva de cada quien).</p>
<p>La segunda parte de la definición viene con el primer &#8220;<acronym title="¿Qué carajos?">WTF</acronym>&#8221; para muchos: Las pruebas se deben escribir <em>antes</em> que el software mismo. La primera impresión de muchos (incluyendo a <em>yours truely</em>) es &#8220;¿eh?, ¿y cómo demonios escribo una prueba para software que todavía no existe?&#8221;.</p>
<p>Cuando aprendemos a programar, los más afortunados comienzan con algún lenguaje interpretado como Basic, Logo o Scheme (para los más veteranos) o Ruby y Python. Normalmente comenzamos con cosas simples como por ejemplo, sumar 2 y 3:</p>
<pre style="background-color: black;color: silver;border: double silver 3px;padding: 3pt 1em">&gt;&gt;&gt; 2 + 3
5</pre>
<p>Intuitivamente pensamos <em>&#8220;debe dar cinco&#8221;</em>, incluso <em>antes</em> de oprimir la tecla <tt>ENTER</tt>; y normalmente funciona o si no, entonces hay algo definitivamente mal con el lenguaje o con nuestro entendimiento del mismo. Posteriormente pasamos a cosas más complejas y/o sofisticadas, como por ejemplo:</p>
<pre style="background-color: black;color: silver;border: double silver 3px;padding: 3pt 1em">&gt;&gt;&gt; a = 2
&gt;&gt;&gt; a + 3
5
&gt;&gt;&gt; b = 3
&gt;&gt;&gt; a + b
5
&gt;&gt;&gt; def sum(a, b):
...   return a + b
...
&gt;&gt;&gt; sum(2, 3)
5</pre>
<p>Etcétera. Todo el tiempo verificamos que el resultado es el que esperamos, aunque &#8220;sabemos&#8221; que así debería ser. Cada vez que vemos el resultado que esperamos aparecer en la pantalla, aumenta nuestra autoconfianza, lo que nos motiva a seguir aprendiendo, a seguir programando. Este podría tal vez ser el ejemplo más básico de <acronym title="Test Driven Development">TDD</acronym>.</p>
<p>Sin embargo, una vez que tomamos mayor confianza en nuestro dominio del lenguaje o la programación misma, comenzamos a escribir cantidades cada vez mayores de código entre una comprobación y la siguiente del resultado. Como &#8220;sabemos&#8221; &#8211;en realidad, creemos&#8211; que nuestro código &#8220;esta bien&#8221;, comenzamos a &#8220;optimizar el tiempo&#8221; escribiendo más y más código de una vez. Al poco tiempo, nos olvidamos de estas primeras experiencias, incluso tachándolas como &#8220;cosas de novatos&#8221;.</p>
</div>
<div>
<h2>Aprendiendo <acronym title="Test Driven Development">TDD</acronym></h2>
<p>Fast forward al presente y nos encontramos a nosotros mismos tratando de aprender <acronym title="Test Driven Development">TDD</acronym>. Nos conseguimos una copia de <a href="http://junit.org/" target="_blank">JUnit</a>, <a href="http://www.nunit.org/" target="_blank">NUnit</a>, o el framework de moda para nuestro lenguaje de elección y comenzamos a seguir el tutorial que seguramente encontraremos en el sitio de este último. Los más afortunados probablemente tendrán integrada la funcionalidad directamente en su IDE.</p>
<p>A partir de aquí, estamos en la parte sencilla de nuestra curva de aprendizaje. En los próximos días comenzaremos a producir grandes cantidades de pruebas y no tardaremos en sentirnos cómodos con el proceso. Esto es lo más lejos que la mayoría llegamos en la curva y es aquí justamente donde comienzan los problemas.</p>
<p>Conforme comenzamos a intentar escribir pruebas para proyectos más complejos o incluso en el trabajo nos topamos con varios obstáculos en el camino:</p>
<ul>
<li>Las pruebas se tornan difíciles de escribir, por lo que sentimos una desaceleración importante.</li>
<li>Corren lentamente, lo que nos volvemos renuentes a ejecutarlas frecuentemente.</li>
<li>Son frágiles, por lo que cambios aparentemente sin importancia en el código provocan que un montón de pruebas fallen.</li>
<li>Mantenerlas en forma y funcionando se vuelve complejo y consume tiempo.</li>
</ul>
<p>Finalmente nos damos por vencido y abandonamos completamente nuestras mejores intenciones y pensamos &#8220;Simplemente no vale la pena&#8221;.</p>
<p>Estamos en la parte más pronunciada de nuestra curva de aprendizaje. Tal vez estamos produciendo muchas pruebas, y estamos obteniendo verdadero valor de las mismas. Sin embargo el esfuerzo para escribir/mantener estas mismas parece desproporcionado. Sin embargo, como cualquier otra habilidad que valga la pena adquirir, si en lugar de rendirnos seguimos adelante, eventualmente aprenderemos a cruzar a la parte de nuestra gráfica donde la pendiente de la curva se invierte y comenzamos a escribir pruebas más efectivas con un menor esfuerzo y a cosechar los beneficios de nuestra perseverancia.</p>
<p>Aprender a escribir bien y de mantener las pruebas toma tiempo y práctica. El propósito de este blog es, en parte para ayudar a acelerar un poco este proceso, de forma que no se tenga que escribir muchas pruebas basura, imposible de mantener antes de comenzar a ver la luz al final del túnel.</p>
</div>
<div>
<h2>Las reglas de <acronym title="Test Driven Development">TDD</acronym></h2>
<p>Robert C. Martin (también conocido como &#8220;Tío Bob&#8221;), es una de las autoridades en <acronym title="Test Driven Development">TDD</acronym>. En varias ocasiones ha descrito el proceso en base a tres simples reglas:</p>
<ol>
<li>No está permitido escribir ningún código de producción sin tener una prueba que falle.</li>
<li>No está permitido escribir más código de prueba que el necesario para fallar (y no compilar es fallar).</li>
<li>No está permitido escribir más código de producción que el necesario para pasar su prueba unitaria.</li>
</ol>
<p>Esto significa que antes de poder escribir cualquier código, debemos pensar en una prueba apropiada para él. Pero por la regla número dos, ¡tampoco podemos escribir mucho de dicha prueba! En realidad, debemos detenernos en el momento en que la prueba falla al compilar o falla un <tt>assert</tt> y comenzar a escribir código de producción. Pero por la regla número tres, tan pronto como la prueba pasa (o compila, según el caso), debemos dejar de escribir código y continuar escribiendo la prueba unitaria o pasar a la siguiente prueba.</p>
<p>Creo que esto se verá mejor con un pequeño ejemplo:</p>
<ul>
<li>Escribimos suficiente de nuestra primera prueba para que falle
<pre style="border: solid blue 1px;background-color: #ddf;padding: 3pt 1em"><span style="color: #606">import</span> unittest

<span style="color: #606">class</span> <span style="color: teal">TestPrimeFactors</span><span style="color: #606">(</span>unittest.TestCase<span style="color: #606">):</span>

    <span style="color: #606">def</span> <span style="color: teal">testPrimesOf_0</span><span style="color: #606">(</span>self<span style="color: #606">):</span>
        self.assertEquals<span style="color: #606">([],</span> factorsOf<span style="color: #606">[</span><span style="color: #c00">0</span><span style="color: #606">])</span>

<span style="color: #606">if</span> __name__ <span style="color: #606">==</span> <span style="color: navy">'__main__'</span><span style="color: #606">:</span>
    main<span style="color: #606">()</span></pre>
<pre style="background-color: black;color: silver;border: double silver 3px;padding: 3pt 1em">E
======================================================================
ERROR: testPrimesOf_0 (__main__.TestPrimeFactors)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "&lt;stdin&gt;", line 3, in testPrimesOf_0
NameError: global name 'factorsOf' is not defined

----------------------------------------------------------------------
Ran 1 test in 0.001s

<span style="color: red">FAILED (errors=1)</span></pre>
</li>
<li>Podemos ver obtenemos el error &#8220;NameError: global name &#8216;factorsOf&#8217; is not defined&#8221;. Esta es nuestra señal para detenernos y escribir la definición de <tt>factorsOf</tt>:
<pre style="border: solid blue 1px;background-color: #ddf;padding: 3pt 1em"><span style="color: #606">def</span> <span style="color: teal">factorsOf</span><span style="color: #606">(</span>n<span style="color: #606">):</span>
    <span style="color: #606">return []</span></pre>
<pre style="background-color: black;color: silver;border: double silver 3px;padding: 3pt 1em">.
----------------------------------------------------------------------
Ran 1 test in 0.000s

<span style="color: lime">OK</span></pre>
</li>
<li><tt>testPrimesOf_0</tt>pasa. Podemos continuar escribiendo código de prueba:
<pre style="border: solid blue 1px;background-color: #ddf;padding: 3pt 1em">    <span style="text-decoration: line-through"><span style="color: #606">def</span> <span style="color: teal">testPrimesOf_0</span><span style="color: #606">(</span>self<span style="color: #606">):</span></span>
    <span style="color: #606">def</span> <strong><span style="color: teal">testPrimesOf_0_to_1</span></strong><span style="color: #606">(</span>self<span style="color: #606">):</span>
        self.assertEquals<span style="color: #606">([],</span> factorsOf<span style="color: #606">(</span><span style="color: #c00">0</span><span style="color: #606">))</span>
        <strong>self.assertEquals<span style="color: #606">([],</span> factorsOf<span style="color: #606">(</span><span style="color: #c00">1</span><span style="color: #606">))</span></strong></pre>
<pre style="background-color: black;color: silver;border: double silver 3px;padding: 3pt 1em">.
----------------------------------------------------------------------
Ran 1 test in 0.000s

<span style="color: lime">OK</span></pre>
</li>
<li>Bien hasta aquí. Siguiente prueba:
<pre style="border: solid blue 1px;background-color: #ddf;padding: 3pt 1em">    <span style="color: #606">def</span> <span style="color: teal">testPrimesOf_2</span><span style="color: #606">(</span>self<span style="color: #606">):</span>
        self.assertEquals<span style="color: #606">([</span>2<span style="color: #606">],</span> factorsOf<span style="color: #606">(</span>2<span style="color: #606">))</span></pre>
<pre style="background-color: black;color: silver;border: double silver 3px;padding: 3pt 1em">.F
======================================================================
FAIL: testPrimesOf_2 (__main__.TestPrimeFactors)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "~/blog/tdd-rules.py", line 12, in testPrimesOf_2
    self.assertEquals([2], factorsOf(2))
AssertionError: Lists differ: [2] != []

----------------------------------------------------------------------
Ran 2 tests in 0.029s

<span style="color: red">FAILED (failures=1)</span></pre>
</li>
<li>Ahora <tt>testPrimesOf_2</tt>falla. Hora de escribir código:
<pre style="border: solid blue 1px;background-color: #ddf;padding: 3pt 1em"><span style="color: #606">def</span> factorsOf<span style="color: #606">(</span>n<span style="color: #606">):</span>
    <strong><span style="color: #606">if</span> n <span style="color: #606">&gt;</span> <span style="color: #c00">1</span><span style="color: #606">:</span></strong>
        <strong><span style="color: #606">return [</span>n<span style="color: #606">]</span></strong>
    <span style="color: #606">return []</span></pre>
<pre style="background-color: black;color: silver;border: double silver 3px;padding: 3pt 1em">..
----------------------------------------------------------------------
Ran 2 test in 0.000s

<span style="color: lime">OK</span></pre>
</li>
<li><tt>testPrimesOf_2</tt>pasa. Siguiente prueba:
<pre style="border: solid blue 1px;background-color: #ddf;padding: 3pt 1em">    <span style="text-decoration: line-through"><span style="color: #606">def</span> <span style="color: teal">testPrimesOf_2</span><span style="color: #606">(</span>self<span style="color: #606">):</span></span>
    <span style="color: #606">def</span> <strong><span style="color: teal">testPrimesOf_2_to_3</span></strong><span style="color: #606">(</span>self<span style="color: #606">):</span>
        self.assertEquals<span style="color: #606">([</span><span style="color: #c00">2</span><span style="color: #606">],</span> factorsOf<span style="color: #606">(</span><span style="color: #c00">2</span><span style="color: #606">))</span>
        <strong>self.assertEquals<span style="color: #606">([</span><span style="color: #c00">3</span><span style="color: #606">],</span> factorsOf<span style="color: #606">(</span><span style="color: #c00">3</span><span style="color: #606">))</span></strong></pre>
<pre style="background-color: black;color: silver;border: double silver 3px;padding: 3pt 1em">..
----------------------------------------------------------------------
Ran 2 test in 0.000s

<span style="color: lime">OK</span></pre>
</li>
<li>También pasa sin modificación. Pasamos a la siguiente prueba:
<pre style="border: solid blue 1px;background-color: #ddf;padding: 3pt 1em">    <span style="color: #606">def</span> <span style="color: teal">testPrimesOf_2_to_4</span><span style="color: #606">(</span>self<span style="color: #606">):</span>
        self.assertEquals<span style="color: #606">([</span><span style="color: #c00">2</span><span style="color: #606">],</span> factorsOf<span style="color: #606">(</span><span style="color: #c00">2</span>))
        self.assertEquals<span style="color: #606">([</span><span style="color: #c00">3</span><span style="color: #606">],</span> factorsOf<span style="color: #606">(</span><span style="color: #c00">3</span>))
        <strong>self.assertEquals<span style="color: #606">([</span><span style="color: #c00">2</span><span style="color: #606">,</span> <span style="color: #c00">2</span><span style="color: #606">],</span> factorsOf<span style="color: #606">(</span><span style="color: #c00">4</span><span style="color: #606">))</span></strong></pre>
<pre style="background-color: black;color: silver;border: double silver 3px;padding: 3pt 1em">.F
======================================================================
FAIL: testPrimesOf_2_to_4 (__main__.TestPrimeFactors)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "~/blog/tdd-rules.py", line 16, in testPrimesOf_2_to_4
    self.assertEquals([2,2], factorsOf(4))
AssertionError: Lists differ: [2, 2] != [4]

----------------------------------------------------------------------
Ran 2 tests in 0.001s

<span style="color: red">FAILED (failures=1)</span></pre>
</li>
<li>Falla de nuevo. Hora de modificar el código de nuevo:
<pre style="border: solid blue 1px;background-color: #ddf;padding: 3pt 1em"><span style="color: #606">def</span> factorsOf(n<span style="color: #606">):</span>
    <strong>result<span style="color: #606">,</span> factor</strong> <span style="color: #606">= []</span><strong><span style="color: #606">,</span> <span style="color: #c00">2</span></strong>
    <span style="text-decoration: line-through"><span style="color: #606">if</span> n <span style="color: #606">&gt;</span> <span style="color: #c00">1</span>:</span>
    <strong><span style="color: #606">while</span></strong> n <span style="color: #606">&gt;</span> <span style="color: #c00">1</span><span style="color: #606">:</span>
        <span style="text-decoration: line-through"><span style="color: #606">return [</span>n<span style="color: #606">]</span></span>
        <strong><span style="color: #606">while</span> n <span style="color: #606">%</span> factor <span style="color: #606">==</span> <span style="color: #c00">0</span>:</strong>
            <strong>result.append<span style="color: #606">(</span>factor<span style="color: #606">)</span></strong>
            <strong>n <span style="color: #606">/=</span> factor</strong>
        <strong>factor <span style="color: #606">+=</span> <span style="color: #c00">1</span></strong>
    <span style="text-decoration: line-through"><span style="color: #606">return []</span></span>
    <strong><span style="color: #606">return</span> result</strong></pre>
<pre style="background-color: black;color: silver;border: double silver 3px;padding: 3pt 1em">..
----------------------------------------------------------------------
Ran 2 test in 0.000s

<span style="color: lime">OK</span></pre>
</li>
<li>Pasa.</li>
</ul>
<p>Obviamente he resumido el proceso un poco debido a limitaciones de espacio, pero creo que el proceso es claro.</p>
<p>Podemos ver que en realidad nunca escribimos mucho código de una sola vez. ¡Y de eso se trata precisamente! Es mucho muy similar al proceso descrito al principio de este post, cuando probábamos nuestro código interactivamente en el intérprete. Una iteración completa por todo el ciclo toma solo unos segundos o máximo un par de minutos. La retroalimentación se mantiene alta y esto nos motiva a seguir adelante con confianza y determinación. ¿Porqué? Simple: en todo momento, si seguimos este proceso durante todo el día, sabemos que nuestro sistema está funcionando. Incluso si comentemos un error <em>hace solo un momento el sistema funcionaba correctamente</em>. Si introducimos un bug, único que hace falta es oprimir <tt>Ctrl-Z</tt> unas cuantas veces y podremos regresar a nuestra barra verde. Y creo firmemente que eso es algo valioso.</p>
<p>Uno de los problemas fundamentales a los que me he enfrentado a través de los años al desarrollar software, es el no entender bien lo que estoy haciendo en un momento dado. Hay veces que simplemente estoy tratando de entender una nueva API o sistema y debo escribir código para implementar nueva funcionalidad. Así que copio y pego código que encuentro en algún libro o sitio de internet y trato de hacerlo funcionar. Un cambio aquí, otro allá hasta que aparentemente funciona. El problema es que no entiendo lo que acabo de hacer. Si el código falla en QA o incluso un par de semanas después de haberlo escrito, realmente no tengo mucha idea de porqué. De hecho, no tengo idea de porqué funcionó cuando lo puse ahí en primer lugar.</p>
<p>Al seguir de forma disciplinada estas tres simples reglas, nunca paso demasiado tiempo sin saber si lo que hago funciona o no. Y como nunca escribo demasiado código, puedo entender plenamente cómo y porqué funciona.</p>
</div>
<div>
<h2>Escribiendo pruebas unitarias efectivas</h2>
<p>Roy Osherove en <a href="http://www.manning.com/osherove/" target="_blank"><em>The Art of Unit Testing</em></a> dice que las buenas pruebas tienen tres propiedades comunes: son legibles, confiables y fáciles de mantener. Una cuarta propiedad que yo agregaría es &#8220;rapidez&#8221;, por razones que discutiremos más adelante.</p>
<div>
<h3>Legibilidad</h3>
<p>Una prueba legible es aquella que revela su propósito o razón de ser de forma clara. Básicamente, qué es lo que la prueba ha de demostrar. Una parte importante de la legibilidad de una prueba consiste simplemente en darle un nombre apropiado. Si está probando una pila, por ejemplo, entonces no llamemos nuestras pruebas <tt>testStack_01</tt>, <tt>testStack_02</tt>, etc. No solo son nombres bobos (por decir lo menos) sino que lo único que revelan es que en alguna parte debe haber algún objeto o función llamado &#8220;Stack&#8221; involucrado. En cambio, elegir nombres que reflejen el comportamiento útil observable que el código debiera exhibir. Por ejemplo, <tt>testElementosGuardadosSonRegresadosEnOrdenInverso</tt> es un nombre que describe un comportamiento observable de las pilas: los elementos colocados al principio son los últimos en ser devueltos.</p>
<p>Es conveniente considerar que los nombres de las pruebas forman parte de la documentación del comportamiento de la <em>Unidad de Código Bajo Prueba</em>. Cuando llega el momento de implementar una nueva clase, a menudo encuentro útil comenzar con una lista inicial de las pruebas que quiero escribir (no siempre lo hago, pero a veces resulta indispensable). Puedo usar esta lista como un primer borrador de la especificación de la clase en cuestión, por ejemplo:</p>
<ul>
<li>No debe ser posible crear una <em>flootsam</em> sin una <em>jetsam</em> asociada.</li>
<li>Si la <em>flootsam</em> no es persistente, no puede contener hijos.</li>
<li>Una <em>flootsam</em> con hijos no puede ser cancelada.</li>
<li>etc.</li>
</ul>
<p>Esta lista más adelante puede convertirse en la base de los nombres de nuestras pruebas.</p>
<p>Cuando las pruebas llevan el nombre de una conducta observable, esta tiende naturalmente a reflejar unicamente este aspecto del código. Es aceptable tener más de un <tt>assert</tt>, siempre que estos se refieran a una sola cosa, generalmente a un solo objeto.</p>
<p>Encontrar el justo equilibrio entre tener el código de inicialización dentro de las pruebas, en una fábrica o en un método <tt>setup</tt> dedicado, es también un elemento importante de la legibilidad. Es importante reducir el volumen del código en las pruebas, pero también queremos que sea evidente lo que la prueba está haciendo. Es fácil caer en la trampa de ocultar muchos detalles en los métodos de inicialización o de fábrica, por lo que un lector tiene que buscar estos métodos para poder entender la prueba. El principio <acronym title="Don't Repeat Yourself">DRY</acronym>, a veces se encuentra firmemente grabado en la consciencia de los buenos programadores. Sin embargo, es perfectamente aceptable tener un poco más de redundancia, mientras que el propósito se mantenga claro.</p>
<p>Esto último no quiere decir que podemos ignorar las reglas y escribir nuestras pruebas de forma descuidada. Nuestras pruebas son parte esencial de nuestro código. Son tan importantes como el código de producción (o de acuerdo con Robert C. Martin, son aún más importantes). Por lo tanto es necesario poner tanto esmero en su manufactura como el que pondríamos en la demo que haremos la próxima semana frente al cliente.</p>
</div>
<div>
<h3>Confiabilidad</h3>
<p>Una prueba confiable es la que falla o pasa de forma determinista. Las pruebas que dependen si la computadora está configurada correctamente, o cualquier otro tipo de variables externas, no son confiables, porque no es posible saber si una falla significa que el equipo no está configurado correctamente, o si el código contiene errores.</p>
<p>Estas pruebas que dependen de variables externas son en realidad pruebas de integración, y se deben poner en un proyecto por separado, junto con alguna documentación sobre la forma de ponerse en marcha. Esto es deseable, ya que este tipo de pruebas normalmente se ejecutan mucho más lentamente que las pruebas unitarias típicas, por lo que al estar separadas, no impedirán que ejecutemos nuestras pruebas unitarias tan frecuentemente como deseemos/necesitemos.</p>
<p>Una variable externa es cualquier cosa sobre la que no tenemos control directo: el sistema de archivos, bases de datos, el tiempo, el código de terceros, etc.</p>
<p>En cuanto al tiempo, basta con crear algunas instancias tipo fecha con un instante fijo, en lugar un indeterminado &#8220;tiempo actual&#8221; y olvidarnos del asunto. En una prueba unitaria, deberíamos utilizar exactamente los mismos datos de prueba cada vez, pero si la prueba dependiera de un valor como <tt>DateTime.Now</tt>, entonces efectivamente sería una prueba diferente cada vez que se ejecute.</p>
<p>En algunas ocasiones especiales, es imposible evitar el tener una prueba indeterminable sin importar cuanto nos esforcemos. Martin Fowler y otros recomiendan en primer lugar, aislar estas pruebas. Lo último que queremos es acostumbrarnos a ver fallar pruebas en nuestra suite. Una barra roja para nosotros siempre debe ser una señal de alarma. No importa que podamos reconocer la prueba por su nombre. El punto de usar pruebas automáticas es precisamente no tener que inspeccionar visualmente los resultados para darlos o no por buenos. Si esto sucede, ¡podemos pasar por alto un fallo real sin notarlo! Otro punto es el analizar si una aproximación probabilística es útil en estos casos. Si los resultados de la prueba se encuentran acotados dentro de un margen de tolerancia, es posible eliminar la incertidumbre hasta un grado aceptable para nuestros propósitos.</p>
</div>
<div>
<h3>Mantenibilidad</h3>
<p>Una prueba fácil de mantener es aquella que no &#8220;se rompe&#8221; fácilmente cuando se les da mantenimiento. Un bajo acoplamiento es probablemente el factor más importante para la facilidad de mantenimiento. El uso de <em>Métodos de fábrica</em> nos permite desacoplar nuestras pruebas de los constructores de clase, que tienden sufrir cambios en sus listas de parámetros más a menudo que otros métodos.</p>
<p>Dar nombres significativos a nuestras pruebas también es importante para el mantenimiento, así como la legibilidad. Cuando se puede deducir a partir del nombre lo que la prueba está tratando de comprobar, se puede ver si en realidad el código hace lo que se dice que está haciendo. Puede asegurarse que las pruebas mantienen su comportamiento, incluso cuando hay cambios en el API que utiliza.</p>
<p>Cuando las pruebas se pueden leer, entonces se vuelven más fáciles de mantener. Cuando las pruebas se pueden mantener, entonces es probable que en de hecho, se les dé mantenimiento. Cuando se sabe que las pruebas se mantienen, y se puede inferir lo que están comprobando, entonces es posible confiar en ellas como en la red de seguridad que se supone que son.</p>
</div>
<div>
<h2>Rapidez</h2>
<p>Una prueba unitaria efectiva debería ejecutarse en milisegundos, <strong>no en segundos</strong>. Si a una prueba tarda más que algunos cientos de milisegundos en ejecutar, es probable que debamos considerarla demasiado lenta. Como en todo, hay excepciones, pero esta es una buena regla a seguir. A continuación explico porqué.</p>
<p>Una suite de pruebas puede llegar a contener decenas o incluso cientos de pruebas, organizadas en clases, cada una enfocándose a un aspecto particular del código. Si una prueba se ejecuta en un segundo (1000 milisegundos) y tenemos cien de ellas, tendremos que esperar más de dos minutos para conocer el resultado de las mismas. Correr la suite se convierte en si mismo en una interrupción que altera nuestro ritmo de trabajo: La mente se distrae y para cuando finalmente tenemos los resultados, debemos de &#8220;vaciar la pila&#8221; nuevamente y reingresar el contexto que teníamos unos segundos antes de ejecutar la suite.</p>
<p>Si hacemos esto una y otra vez en el transcurso del día (a la mayoría de los desarrolladores se les complica mantener su atención por más de algunos segundos antes de perder el interés), entonces comenzaremos a evitar el correr nuestras pruebas, lo cual deberíamos hacer cada vez que cambiamos &#8220;algo&#8221; en el código. Y si esto es así, entonces perdemos la confianza en nuestros cambios y en nosotros mismos. Regresamos al ritmo &#8220;tradicional&#8221; y finalmente puede llegar a parecernos &#8220;más fácil&#8221; abrir el depurador de nuestro IDE que dar un par de pasos hacia atrás hasta el punto en que todo aun funcionaba bien.</p>
<p>Todo ello sin considerar el tiempo perdido. No solo el tiempo de ejecución de las pruebas mismas, sino el tiempo que nos toma volver a entrar en el contexto mental que teníamos justo antes.</p>
<p>Una sesión de <acronym title="Test Driven Development">TDD</acronym> en realidad debería transcurrir como los ejemplos interactivos al principio de este post. Escribimos algo de código y deberíamos obtener retroalimentación casi inmediatamente. Cada vez que corremos la suite &#8220;en verde&#8221;, aumenta nuestra confianza, en nuestro código, en nuestra suite y en nosotros mismos, lo cual nos mantiene altamente motivados para seguir adelante.</p>
<p>Volver al ciclo tradicional de modificar/compilar/debuguear destruye esa motivación. Si probar un cambio de una sola linea nos lleva 5 minutos de en el depurador, nuestra motivación se va a los suelos y se convierte en una excusa para alargar los tiempos de desarrollo casi infinitamente.</p>
<p>Un componente fundamental en la construcción de una suite de pruebas es la habilidad de construirla a partir de subconjuntos más pequeños y enfocados. Es importante ser capaz de probar el sistema completo oprimiendo solo un botón (o con un solo comando en la shell del sistema), pero igualmente importante es poder ejecutar únicamente las pruebas para la clase o el sub-sistema que estamos probando en este momento. La mayoría de los frameworks de la familia XUnit tienen esta capacidad. Se pueden crear suites pequeñas y estas a su vez, incluirlas en suites mayores.</p>
</div>
</div>
<div>
<h2>Cookbook</h2>
<div>
<h3>Aprender</h3>
<ul>
<li>Escribe muchas pruebas (tantas como puedas). Familiarizate con el ritmo y las reglas de <acronym title="Test Driven Development">TDD</acronym>. Comienza con algo sencillo (¡pero no te detengas ahí!)</li>
<li>Cuando encuentres algo que no sabes como probar, apóyate en un compañero. Si no programas en parejas, consulta con un colega. Recolecta ideas de diversas fuentes.</li>
<li>Sé persistente y no te rindas. Si quieres obtener los frutos, debes primero poner el trabajo duro.</li>
<li>Nunca dejes de aprender. Lee libros (una lista al final de este post), blogs, revistas, etc. Los proyectos de <em>Código Abierto</em> son una excelente fuente de aprendizaje.</li>
<li>Conforme escribas más y más pruebas, comienza a organizarlas en suites y asegúrate que estas puedan ejecutarse de forma individual o colectiva, según sea necesario. ¡La organización también es una habilidad que hay que aprender!</li>
</ul>
</div>
<div>
<h3>Prácticas para el día a día</h3>
<ul>
<li>Es recomendable probar una unidad de código solo a través de su API pública (y en términos prácticos, &#8220;protegido&#8221; es efectivamente público). Al hacer esto, obtenemos un mejor aislamiento de los detalles específicos de la implementación.</li>
<li>Evita a toda cosa colocar lógica en el código de prueba (<tt>if</tt>-<tt>then</tt>, <tt>switch</tt>/<tt>case</tt>, etc). Donde hay lógica, hay la probabilidad de introducir <em>bugs</em>, ¡y definitivamente no queremos <em>bugs</em> en nuestras pruebas!</li>
<li>Evita los <em>&#8220;números mágicos&#8221;</em>. Esto te permitirá entender porqué en una prueba particular un método regresa un valor dado o porque se pasa un cierto valor como parámetro y no otro diferente.</li>
<li>Evita calcular el valor esperado, ya que podríamos terminar duplicando el código del producción, incluyendo cualquier error que este pudiera tener. Preferiblemente, calcula el resultado esperado manualmente (y revisalo por lo menos un par de veces) y colócalo como una constante.</li>
<li>Evita compartir estado entre pruebas. Debe ser posible ejecutar las pruebas en cualquier orden o incluso, ejecutar una prueba dentro de otra prueba. Mantener las pruebas aisladas de las demás también es un factor indispensable para la confiabilidad y mantenibilidad de las mismas.</li>
<li>Sin importar como lo veas, ninguna cantidad de comentarios puede sustituir un código claro. Si una prueba se convierte en un desastre, reescríbela.</li>
<li>Si no es posible determinar lo que una prueba está haciendo, es probable que en realidad esté verificando múltiples cosas: hazla pedazos y convierte cada uno en su propia prueba individual.</li>
<li>Frecuentemente los errores en el código de pruebas se esconden en los métodos de inicialización. Mantener este código simple y compacto puede ser un gran paso para la mantenibilidad del código.</li>
<li>Una unidad de código puede necesitar operar en circunstancias escenarios variables. Esto puede llevar a que el código de inicialización se convierta rápidamente en un desastre. Crea <tt>fixtures</tt> o incluso casos de prueba especializados para cada escenario.</li>
<li>Nunca escatimes en claridad. Si es necesario, convierte cada escenario en una clase de prueba individual.</li>
<li>Si al probar una parte de tu código parece que requieres tener la mitad o más del sistema presente, verifica el alcance de la misma. ¿Estás probando una sola cosa?</li>
<li>Si una parte del código es particularmente resistente a tus esfuerzos de probarla, voltea al código en busca de problemas en el diseño del mismo. Un código fácil de probar frecuentemente está débilmente acoplado con el resto del sistema, es altamente cohesivo y sigue los principios fundamentales del diseño de software.</li>
</ul>
</div>
<p>Espero como siempre que haya sido de utilidad.</p>
</div>
<img src="http://feeds.feedburner.com/~r/ArtesanosDeSoftware/~4/jkAiFuQkWpE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://artesanos.de/software/2012/02/13/tdd-como-y-porque-una-guia-para-los-no-iniciados/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://artesanos.de/software/2012/02/13/tdd-como-y-porque-una-guia-para-los-no-iniciados/</feedburner:origLink></item>
		<item>
		<title>Documentación y Nombre de Clases en Java</title>
		<link>http://feedproxy.google.com/~r/ArtesanosDeSoftware/~3/NktwaqD0XSg/</link>
		<comments>http://artesanos.de/software/2012/01/25/documentacion-y-nombre-de-clases-en-java/#comments</comments>
		<pubDate>Wed, 25 Jan 2012 23:27:16 +0000</pubDate>
		<dc:creator>ivan</dc:creator>
				<category><![CDATA[Idea]]></category>

		<guid isPermaLink="false">http://artesanos.de/software/?p=187</guid>
		<description><![CDATA[Lo que se busca en este artículo es proponer una forma de documentar y a la vez nombrar clases en Java. Al final de este artículo se tiene como objetivo el entender las ventajas y mejoras de documentar clases y a la vez elegir nombres apropiados para las clases apoyandonos en esta sencilla práctica. Sería [...]]]></description>
			<content:encoded><![CDATA[<p>Lo que se busca en este artículo es proponer una forma de documentar y a la vez nombrar clases en Java. Al final de este artículo se tiene como objetivo el entender las ventajas y mejoras de documentar clases y a la vez elegir nombres apropiados para las clases apoyandonos en esta sencilla práctica.<br />
</br><br />
Sería bueno empezar por mostrar aquello que se intenta mejorar. Es muy común que al aprender un nuevo patrón de diseño, un framework, o bien al implantar una arquitectura de referencia nuestra primera tendencia sea hacer lo siguiente:  Si estamos aprendiendo Spring Framework:<br />
</br></p>
<pre class="brush:java;">public class UsuarioPOJO {
// código de la clase
}</pre>
<p></br><br />
Si se está aprendiendo algún patrón de diseño para que ciertos componentes se expongan como servcios o similares intenciones:<br />
</br></p>
<pre class="brush:java;">public class BusquedaUsuariosFacade{
// código de la clase
}</pre>
<p></br><br />
Si se tiene un estilo de diseño de responabilidades y roles, o aplicar un DDD, que indica que necesitamos ciertos colaboradores como:<br />
</br></p>
<pre class="brush:java;">public class UsuarioBuilder{
// código de la clase
}</pre>
<p></br><br />
Por el momento, es de esperar que basten estos ejemplos. El punto aquí es que los nombres que se asignan a las clases son algunas veces bastante atados al Framework que se utiliza, a algún patrón de diseño, o bien sólo a un rol o responsabilidad. Todo esto son detalles técnicos y en verdad hacen que el programador se olvide del dominio específico para el que realiza la aplicación. Uno podría aventurarse a decir que este mecanicismo es parte de que pocos sean críticos en cuanto a su diseño y que realmente se aprecie el problema en su escencia. Y en analogía con lo que indica Uncle Bob el código deberían gritar el dominio del problema y no una tecnología específica, es decir, Hibernate, Spring o ese nuevo patrón o tecnicismo que acabamos de aprender o que aplicamos como receta de cocina.<br />
</br><br />
No está de más decir que algunos desarrolladores se olvidan del dominio o contexto del aplicativo que están resolviendo y simplemente le llaman a sus clases: FactoryEntitiyBean, CrudServiceBean, AuditLoggerBean,  EventDispatcherBean, LoginStrategyBean, ThreadPoolImpl . Y el dominio del problema se desvanece.<br />
</br><br />
Para efectos de aprendizaje está muy bien nombrar a las classes así, pero para la práctica no. Los ejemplos de diversas fuentes nombran sus clases haciendo clara referencia a las partes del tema que quieren aclarar pero al final pocos dicen que no se debe seguir al pie de la letra los nombres del ejemplo.<br />
</br><br />
Con tales antecedentes presentemos a la propuesta de mejora. En UML muchos de estas palabras que agregamos como sufijo (o prefijo) a las clases son los llamados stereotypes que comunmente aparecen en los diagramas de clases o de secuencia. Y son bastante eficaces en mostrar la responsabilidad o rol que juegan en el diseño de la solución. A nivel de código estos stereotypes se pueden conservar y mantener el código documentado con el uso de una anotación. Que al final servirá como una marca (o tag) bastante útil.<br />
</br></p>
<pre class="brush:java;">@Stateless
@Remote(BusquedaUsuarios.class)
@Facade(responsability="Ejemplo de responsabilidad descrita",
documentationLink="http://wiki.artesanos.de/software")
public class BusquedaUsuariosAdscritos implements BusquedaUsuarios { ... } </pre>
<p></br><br />
Tal y como se observa el nombre de nuestra clase ha quedado más limpio y sólo hace referencia al dominio/negocio. Admás  se ha logrado mediante el uso de anotaciones a la medida documentar y plasmar  ese rol o responsabilidad que anteriormente adjuntabamos a manera de sufijo (o prefijo).<br />
</br><br />
Ahora bien, analicemos que ventajas nos reporta esta práctica. Hemos observado que se utilizan anotaciones y es necesario responder ¿por qué?  Las anotaciones tienen algunas ventajas sobre el JavaDoc, ya que este metadata permanece en en el byte code y es accesible via reflection. Este tipo de documentación puede ser inclusive aprovechada durante el proceso de build o con heramientas de análisis estático de código.<br />
</br><br />
La declaración de la anotación tipo marca para identificar un Facade como pieza de la solución, es el siguiente:<br />
</br></p>
<pre class="brush:java;">@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Facade {
/**
* Un link a documentación existente,
* o "user story" o "use case".
*/
String documentationLink() default "";
/**
* La intención escencial y responsabilidad(es)
* de la Facade que se implementa
*/
String responsibility();
}</pre>
<p></br><br />
En este ejemplo podemos observar que el atributo &#8220;documentationLink&#8221; es opcional, en el bien podría hacerse referencia a un sitio donde haya información de la decisión de diseño o proporcione la &#8220;user story&#8221; o el &#8220;use case&#8221; asociado a este componente. Para el caso de &#8220;responsability&#8221; por el contrario no es opcional. Algo interesante es que el uso de anotaciones puede forzar al desarrollador a proveer algún tipo de información escencial, lo cual sería el caso para este atributo. Adicionalmente podemos agregar cuantas anotaciones necesitemos para definir roles o responsabilidades de la clase, aunque lo mejor sería condensarlo en una sola anotación que exprese toda la idea.<br />
</br><br />
Supongamos que nuestra clase ha dejado de ser un &#8220;Facade&#8221; protagonista al exterior y ahora simplemente es un &#8220;Provider&#8221; al interior de la implementación. Este cambio sin modificar el nombre de la clase se lograría facilmente colocando su nuevo Rol/Responsabilidad mediante la anotación correspondiente dentro de nuestra arquitectura propuesta. Es muy cierto que el cambio quizá involucre un cambio de paquete o algún otro refactor pero el punto es que la clase con su nombre dentro del dominio del problema sigue intacto, sólo ha rotado en su posición dentro de la estructura sin haberse preconcebido con un prefijo/sufijo a un Rol/Responsabilidad definitivo o por la tecnología en uso.<br />
</br></p>
<pre class="brush:java;">@Stateless
@Local(BusquedaUsuarios.class)
@Provider(responsability="Ejemplo de nueva responsabilidad descrita",
documentationLink="http://wiki.artesanos.de/software")
public class BusquedaUsuariosAdscritos implements BusquedaUsuarios { ... } </pre>
<p></br><br />
Este tipo de anotaciones pueden inclusive ser más formalizadas y proveer más información que sea utilizada como meta-data para ser consumida por un Interceptor de los proporcionados por EJB3.x  o alguna estrategia similar de AOP. Esta última sería la gran ventaja de adoptar esta propuesta ya que además de fomentar la claridad en los nombres de clases permitirá habilitar o deshabilitar comportamientos en las clases marcadas con anotaciones.</p>
<p>En resumen: Es mejor generar anotaciones propias (derivados de la arquitectura propuesta) que generen documentación útil y adicionen compotamiento en tiempo de ejecución (mediante interceptores, AOP); y con ello  dejar los nombres de clases limpios y enfocados al dominio del problema.</p>
<img src="http://feeds.feedburner.com/~r/ArtesanosDeSoftware/~4/NktwaqD0XSg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://artesanos.de/software/2012/01/25/documentacion-y-nombre-de-clases-en-java/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://artesanos.de/software/2012/01/25/documentacion-y-nombre-de-clases-en-java/</feedburner:origLink></item>
		<item>
		<title>Video podcast de ViveCodigo 00×10 – Coding Dojo</title>
		<link>http://feedproxy.google.com/~r/ArtesanosDeSoftware/~3/zd8gUexaLAQ/</link>
		<comments>http://artesanos.de/software/2011/12/26/video-podcast-de-vivecodigo-00x10-coding-dojo/#comments</comments>
		<pubDate>Mon, 26 Dec 2011 16:34:03 +0000</pubDate>
		<dc:creator>neodevelop</dc:creator>
				<category><![CDATA[Sin categoría]]></category>

		<guid isPermaLink="false">http://artesanos.de/software/?p=256</guid>
		<description><![CDATA[Se ha publicado un nuevo episodio de ViveCodigo, en donde se llev&#243; a cabo un Coding Dojo. Una de las actividades que practican los artesanos de software. Si s&#243;lo deseas escucharlo entonces: El video del podcast: La liga del art&#237;culo con los v&#237;nculos y dem&#225;s informaci&#243;n: http://vivecodigo.org/2011/12/21/podcast-10-de-la-temporada-0/ Que lo disruten!!]]></description>
			<content:encoded><![CDATA[<p>
	Se ha publicado un nuevo episodio de ViveCodigo, en donde se llev&oacute; a cabo un Coding Dojo.<br />
<strong>Una de las actividades que practican los artesanos de software.</strong></p>
<p>
	Si s&oacute;lo deseas escucharlo entonces:</p>
<p>
	<embed flashvars="audioUrl=http://s3.amazonaws.com/media.vivecodigo.org/podcast/temporada0/ViveCodigo00x10.mp3" height="27" quality="best" src="http://www.google.com/reader/ui/3523697345-audio-player.swf" type="application/x-shockwave-flash" width="400"></embed></p>
<p>
	El video del podcast:</p>
<p>
	<iframe frameborder="0" height="253" src="http://player.vimeo.com/video/34008369?color=ff9933" width="450"></iframe></p>
<p>
	La liga del art&iacute;culo con los v&iacute;nculos y dem&aacute;s informaci&oacute;n:</p>
<p>
	<a href="http://vivecodigo.org/2011/12/21/podcast-10-de-la-temporada-0/">http://vivecodigo.org/2011/12/21/podcast-10-de-la-temporada-0/</a></p>
<p>
	Que lo disruten!!</p>
<p><!--break--></p>
<img src="http://feeds.feedburner.com/~r/ArtesanosDeSoftware/~4/zd8gUexaLAQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://artesanos.de/software/2011/12/26/video-podcast-de-vivecodigo-00x10-coding-dojo/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://s3.amazonaws.com/media.vivecodigo.org/podcast/temporada0/ViveCodigo00x10.mp3" length="26528623" type="audio/mpeg" />
		<feedburner:origLink>http://artesanos.de/software/2011/12/26/video-podcast-de-vivecodigo-00x10-coding-dojo/</feedburner:origLink></item>
		<item>
		<title>¿Qué significa ser un aprendiz?</title>
		<link>http://feedproxy.google.com/~r/ArtesanosDeSoftware/~3/5olBpnqlCG0/</link>
		<comments>http://artesanos.de/software/2011/11/22/%c2%bfque-significa-ser-un-aprendiz/#comments</comments>
		<pubDate>Tue, 22 Nov 2011 19:31:56 +0000</pubDate>
		<dc:creator>neodevelop</dc:creator>
				<category><![CDATA[Sin categoría]]></category>

		<guid isPermaLink="false">http://artesanos.de/software/?p=184</guid>
		<description><![CDATA[&#8220;Supongo que significa básicamente tener la actitud de que hay siempre una forma mejor/inteligente/rápida de hacer lo que hicimos y de lo que estamos haciendo actualmente. El aprendizaje es el estado/proceso de evolucionar y buscar por mejores maneras y encontrando gente, compañías y situaciones que te fuerzan a aprender esas mejores/inteligentes/rápidas formas&#8221; &#8211; Marten Gustafson(http://mgustafson.wordpress.com/) [...]]]></description>
			<content:encoded><![CDATA[<p>&#8220;Supongo que significa básicamente tener la actitud de que hay siempre una forma mejor/inteligente/rápida de hacer lo que hicimos y de lo que estamos haciendo actualmente. El aprendizaje es el estado/proceso de evolucionar y buscar por mejores maneras y encontrando gente, compañías y situaciones que te fuerzan a aprender esas mejores/inteligentes/rápidas formas&#8221; &#8211; Marten Gustafson(<a href="http://mgustafson.wordpress.com/">http://mgustafson.wordpress.com/</a>)</p>
<p>&#8220;La situación fundamental de aprendizaje es una en la cual una persona aprende ayudando a quien realmente sabe que es lo que esta haciendo&#8221; Cristopher Alexander en <em>&#8216;A Pattern Language&#8217;</em></p>
<img src="http://feeds.feedburner.com/~r/ArtesanosDeSoftware/~4/5olBpnqlCG0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://artesanos.de/software/2011/11/22/%c2%bfque-significa-ser-un-aprendiz/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://artesanos.de/software/2011/11/22/%c2%bfque-significa-ser-un-aprendiz/</feedburner:origLink></item>
		<item>
		<title>La lista…</title>
		<link>http://feedproxy.google.com/~r/ArtesanosDeSoftware/~3/9GtBMXiTOzg/</link>
		<comments>http://artesanos.de/software/2011/10/07/la-lista/#comments</comments>
		<pubDate>Fri, 07 Oct 2011 21:53:39 +0000</pubDate>
		<dc:creator>neodevelop</dc:creator>
				<category><![CDATA[Sin categoría]]></category>

		<guid isPermaLink="false">http://artesanos.de/software/?p=176</guid>
		<description><![CDATA[Si bien hace tiempo comencé a desarrollar software con la premisa incluida de que cualquier persona puede desarrollar software, también he de agregar el entusiasmo de hacer algo que me gusta con la parte creativa en ello; pero llegó un punto educacional/laboral(ojo que no puse profesional) en donde necesitaba algo más que creatividad, ganas y experiencia. [...]]]></description>
			<content:encoded><![CDATA[<div id="_mcePaste">Si bien hace tiempo comencé a desarrollar software con la premisa incluida de que cualquier persona puede desarrollar software, también he de agregar el entusiasmo de hacer algo que me gusta con la parte creativa en ello; pero llegó un punto educacional/laboral(ojo que no puse profesional) en donde necesitaba algo más que creatividad, ganas y experiencia. Pero, ¿qué era lo que me hacía falta?, sabía que algo me hacía falta pero no sabía exactamente que era, de a poco empecé a conocer más herramientas que implicaban más conocimientos tanto técnicos como tecnológicos y metodológicos, pero nunca me puse a analizar la importancia de todos ellos en conjunto, ni me puse a concentrar todos esos puntos, simplemente los usaba o aplicaba según se fueran necesitando, pero incluso en algunas situaciones pecaba mucho del desconocimiento de otros conceptos fundamentales para resolver o atacar un problema de &#8216;la manera correcta&#8217;.Y aún así, ¿cuál es la manera correcta?, esa tal vez sea nota de otra entrada en este blog&#8230;.</div>
<div id="_mcePaste">Hace ya un par de semanas encontré en una lectura de <strong>Robert C. Martin(Clean coder) </strong>la lista mínima de cosas que cada Profesional de Software(su concepto de Profesional es muy interesante) debe saber, y aquí lo pongo:</div>
<div id="_mcePaste">
<ul>
<li><strong>Patrones de Diseño </strong>
<ul>
<li>Debemos ser capaces de conocer y describir los 24 patrones descritos en el libro GoF(<a href="http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612">Gang of Four</a>) y tener conocimiento de muchos de los patrones del libro(s) POSA(<a href="http://www.cs.wustl.edu/~schmidt/POSA/">Pattern-Oriented Software Architecture</a>)</li>
</ul>
</li>
<li><strong>Principios de Diseño </strong>
<ul>
<li>Debemos conocer acerca del principio <a href="http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod">SOLID</a> y comprenderlos también</li>
</ul>
</li>
<li><strong>Métodos </strong>
<ul>
<li>Debemos entender XP, Scrum, Lean, Kanban, Cascada, Analisis estructurado y diseño estructurado</li>
</ul>
</li>
<li><strong>Disciplinas </strong>
<ul>
<li>Debemos practicar TDD, diseño Orientado a Objetos, programación estructurada, Integración Continua, y programación en pares</li>
</ul>
</li>
<li><strong>Artefactos </strong>
<ul>
<li>Debemos saber como usar: UML, DFD&#8217;s, diagramas de estructura, Redes de Petri, diagramas de transición de estados y tablas, diagramas de flujo y tablas de decisión</li>
</ul>
</li>
</ul>
</div>
<div id="_mcePaste">Echando una revisión a esta lista he de admitir que no soy un Profesional del Software, sin embargo, el aprendizaje continuo como el lo marca debe llevar a ese fin, lo interesante será el camino para llegar a esa meta.</div>
<div id="_mcePaste">Dejo esta lista por que se que muchos de ustedes si conocen al respecto de cada uno de estos conceptos y puede compartir con nosotros de una forma simple su experiencia al aplicarlos o aprenderlos.</div>
<img src="http://feeds.feedburner.com/~r/ArtesanosDeSoftware/~4/9GtBMXiTOzg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://artesanos.de/software/2011/10/07/la-lista/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://artesanos.de/software/2011/10/07/la-lista/</feedburner:origLink></item>
		<item>
		<title>Tareas Vs. Hilos en C#</title>
		<link>http://feedproxy.google.com/~r/ArtesanosDeSoftware/~3/g7fEbDw_nI4/</link>
		<comments>http://artesanos.de/software/2011/10/04/tareas-vs-hilos-en-c-3/#comments</comments>
		<pubDate>Tue, 04 Oct 2011 02:55:13 +0000</pubDate>
		<dc:creator>clausia</dc:creator>
				<category><![CDATA[Sin categoría]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[concurrencia]]></category>
		<category><![CDATA[hilos]]></category>

		<guid isPermaLink="false">http://artesanos.de/software/?p=157</guid>
		<description><![CDATA[Hace algunos meses comencé en un nuevo trabajo, prometía muchos retos y sobre todos un gran cambio a lo que estaba acostumbrada. Para empezar, se trataba de programar aplicaciones de escritorio y ya no más aplicaciones web, que es lo que había hecho desde siempre; otro gran cambio fue el tener que programar (inicialmente) en [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify">Hace algunos meses comencé en un nuevo trabajo, prometía muchos retos y sobre todos un gran cambio a lo que estaba acostumbrada. Para empezar, se trataba de programar aplicaciones de escritorio y ya no más aplicaciones web, que es lo que había hecho desde siempre; otro gran cambio fue el tener que programar (inicialmente) en C#, toda mi carrera profesional he programado en Java, desde la escuela incluso y aunque muchos decimos que C# es la mala copia de Java, debo decir que ahora que lo conozco un poco más, tiene sus detalles agradables.</p>
<p style="text-align: justify">Una de ellos fue el manejo de hilos. Los nuevos requerimeintos que debía satisfacer, requieren que se hagan cálculos con millones de datos, la velocidad es crucial, ya que se obtiene el siguiente dato en la orden de cien milésimas de segundo, y no es que el cálculo en sí tarde más que esa pequeña ventana de tiempo, sino que esperamos que se disparen varios eventos por cada dato, de tal modo que el hilo principal siga teniendo la oportunidad de manejar todos los eventos sin esperarse a que alguno de estos termine, incluyendo el pintado de la interfaz gráfica. Lo primero que me vino a la mente para esto fueron los hilos (gracias hilos por existir), pero comencé a toparme con detallles, uno de ellos es que todos los hilos se ejecutaban en algunos <em>cores </em>solamente, a pesar de que el server tiene 24 núcleos, trabajaban como locos los <em>cores </em>elegidos al azar, mientras se desperdiciaban los demás. Una búsqueda en la red me llevó al descubrimiento de las Tareas del .NET Framework 4.0 las cuales se encargan de generar los hilos, ¿cuántos y cómo? solo el CLR lo sabe, pero lo que también sabe es cuántos <em>cores </em>hay disponibles y la caga de trabajo que ya tienen, de tal modo que balancea los hilos generados y los ditribuye entre todos los núcleos. Problema resuelto para mi aplicación de escritorio.</p>
<p style="text-align: justify">Veamos la diferencia entre el uso de hilos y el uso de tareas con C# (a partir de la versión 4.0 del .NET Framework necesariamente). Primero el ejemplo con hilos:</p>
<pre class="brush:c#;">
class Program
{
   static void Main(string[] args)
   {
       DateTime inicio = DateTime.Now;
       for (int i = 0; i &lt; 100000; i++)
       {
           int temp = i;
           Thread t = new Thread(() =&gt; method1(temp));
           t.Start();
       }
       DateTime fin = DateTime.Now;
       TimeSpan diff = fin - inicio;
       Console.WriteLine("Inicio= {0} - Fin= {1} - Diferencia= {2}:{3}:{4}.{5}",
                          inicio.ToString("yyyy/MM/dd HH:mm:ss.fffffff"),
                          fin.ToString("yyyy/MM/dd HH:mm:ss.fffffff"),
                          diff.Hours, diff.Minutes, diff.Seconds,
                          diff.Milliseconds;
       Console.ReadLine();
   }

   static void method1(int i)
   {
       for (int j = 0; j &lt; 10000; j++)
       {
           double d = 45345 / 6546 * 7989 / 0.2254;  //cualquier procesamiento...
       }
   }
}</pre>
<p style="text-align: justify">La ejecución de este código muestra en su salida:</p>
<pre>
<pre>Inicio= 2011/09/29 21:39:33.6400926 - Fin= 2011/09/29 21:53:23.1265365 -
Diferencia= 0:13:49.486</pre>
</pre>
<p style="text-align: justify">Como podemos ver, se tardó casi 14 minutos en lanzar los hilos, <strong>solamente en generarlos</strong>, cuando descubrí esto, vi que no me servía la utilización directa de muchos hilos, ya que hubiera tenido que idear una manera (sofisticada) de adminsitrar su generación para que fuese gradual.</p>
<p style="text-align: justify">Afortunadamente, los creadores del .NET Framework se preocuparon por proveer mecanismos eficientes para el manejo de concurrencia, apartír de la versión 4.0, entre esos mecanismos, existe la clase Task, la cual para fines prácticos, es como tener hilos ya que permite ejecutar procesos en paralelo. Veamos el mismo ejemplo con tareas:</p>
<pre class="brush:c#;">
class Program
{
   static void Main(string[] args)
   {
       DateTime inicio = DateTime.Now;
       for (int i = 0; i &lt; 100000; i++)
       {
           int temp = i;
           Task t = Task.Factory.StartNew(() =&gt; method1(temp));
       }
       DateTime fin = DateTime.Now;
       TimeSpan diff = fin - inicio;
       Console.WriteLine("Inicio= {0} - Fin= {1} - Diferencia= {2}:{3}:{4}.{5}",
                          inicio.ToString("yyyy/MM/dd HH:mm:ss.fffffff"),
                          fin.ToString("yyyy/MM/dd HH:mm:ss.fffffff"),
                          diff.Hours, diff.Minutes, diff.Seconds,
                          diff.Milliseconds;
       Console.ReadLine();
   }

   static void method1(int i)
   {
       for (int j = 0; j &lt; 10000; j++)
       {
           double d = 45345 / 6546 * 7989 / 0.2254;  //cualquier procesamiento...
       }
   }
}</pre>
<p style="text-align: justify">Con la siguiente salida:</p>
<pre>Inicio= 2011/09/29 21:39:07.0425713 - Fin= 2011/09/29 21:39:07.0975745 -
Diferencia= 0:0:0.133</pre>
<p style="text-align: justify">
<p style="text-align: justify">Como podemos notar, la diferencia entre lanzar hilos y tareas es abismal, lanzar las tareas ha tomado solamente 133 milisegundos!.</p>
<p style="text-align: justify">¿Por qué es tan grande la diferencia? Resulta que las tareas, en algún momento se convierten el hilos, pero nosotros no somos los encargados de decidir cúantos ni cuándo serán lanzados, quien se encarga es el CLR (<em>Common Language Runtime</em>). Para mi sorpresa, el CLR se entera bien de cúantos núcleos existen y de cuánta carga de trabajo tienen, y en base a eso, es que decide cómo repartir las unidades de procesamiento (Tasks) en los hilos, los cuales son reutilizados una vez que terminan de hacer su trabajo. Al parecer esta pequeña, pero importante diferencia, le ahorra mucho tiempo al sistema operativo en cuestión de adminsitrar los hilos de ejecución.</p>
<p style="text-align: justify">Esto fue solo el inicio del desarrollo de aplicaciones paralelas que he comenzado a programar, existen muchas monerias que se pueden explotar en cuanto a paralelo en .NET 4.0 se refiere, como se puede apreciar en la siguiente imagen, las características que se incorporaron en esta versión están enfocadas principalmente al paralelo.</p>
<p style="text-align: center"><img src="http://upload.wikimedia.org/wikipedia/commons/thumb/d/d3/DotNet.svg/250px-DotNet.svg.png" alt="Evolución de las versiones del .NET Framework" width="250" height="292" /></p>
<p style="text-align: justify">He escuchado que en la versión 7 de Java existen las Tareas y en algunos meses desarrollaré el mismo tipo de aplicaciones, pero en Java, espero sinceramente que la JVM también se destaque en la administración de unidades de procesamiento, de lo contrario me tocará sufrir con este tema. Si alguien ha tenido la oportunidad de explotar esta característica de Java, le agradeceré que comparta su experiencia.</p>
<p style="text-align: justify">Como recomendación, pueden referirse al libro llamado &#8220;<a href="http://www.amazon.com/NET-Parallel-Programming-Experts-Voice/dp/1430229675" target="_blank">Pro .NET 4 Parallel Programming in C#</a>&#8221; del autor <em>Adam Freeman</em>, el cual me ha sido de mucha ayuda.</p>
<p style="text-align: justify">&#8212;&#8211;</p>
<p style="text-align: justify">Claudia (<a href="http://twitter.com/#!/clausia" target="_blank">@clausia</a>)</p>
<img src="http://feeds.feedburner.com/~r/ArtesanosDeSoftware/~4/g7fEbDw_nI4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://artesanos.de/software/2011/10/04/tareas-vs-hilos-en-c-3/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://artesanos.de/software/2011/10/04/tareas-vs-hilos-en-c-3/</feedburner:origLink></item>
		<item>
		<title>Pasar de la curiosidad al código.</title>
		<link>http://feedproxy.google.com/~r/ArtesanosDeSoftware/~3/Es6MHEA7zuA/</link>
		<comments>http://artesanos.de/software/2011/09/01/pasar-de-la-curiosidad-al-codigo/#comments</comments>
		<pubDate>Thu, 01 Sep 2011 07:05:54 +0000</pubDate>
		<dc:creator>rodrigo_salado</dc:creator>
				<category><![CDATA[Sin categoría]]></category>

		<guid isPermaLink="false">http://artesanos.de/software/?p=107</guid>
		<description><![CDATA[Pasar de la curiosidad al código. Para mí, pasar de una curiosidad por un nueva tecnología, a código que pueda usar para jugar un rato o usar en algún proyecto es complicado y requiere de mucho esfuerzo, aun así con el tiempo he pulido un poco este proceso. Quiero compartirles con un ejemplo como es [...]]]></description>
			<content:encoded><![CDATA[<p><!-- p { margin-bottom: 0.08in; }a:link {  } --><span style="color: #17365d"><span style="font-family: Cambria,serif"><span style="font-size: x-large">Pasar de la curiosidad al código.</span></span></span></p>
<p lang="es-MX">
<p>Para mí, pasar de una curiosidad por un nueva tecnología, a código que pueda usar para jugar un rato o usar en algún proyecto es complicado y requiere de mucho esfuerzo, aun así con el tiempo he pulido un poco este proceso. Quiero compartirles con un ejemplo como es que llego de una curiosidad por <em>Comet</em> a código.</p>
<p>Todo inicia con una simple pregunta, por ejemplo, ¿cómo podría pintar <em>logs</em> de mi aplicación en un <em>div</em> de <em>HTML</em> sin tener que recargar la página? Esta es la parte más difíciles, porque es en donde tengo que hacer preguntas con las palabras correctas, primero a Google y luego a uno que otro <em>Chapulin Colorado de la programación</em> para que me den la respuesta u orientación que deseo. Porque bien me pudo haber dicho cualquier fuente que <em>Ajax</em> me resolvía el problema, y en efecto me lo resuelve pero <em>Reverse Ajax </em>o<em> Ajax Push.</em> <em>Las preguntas adecuadas son la solución</em>.</p>
<p>Después de mucho investigar qué es lo que necesito aprender, logro saber la palabra clave, el inicio del la aventura, <em>Comet.</em> Es momento de empaparme en la filosofía de la tecnología, saber ¿para qué sirve?, si es lo que necesito en realidad, ¿por qué existe?, ¿que existía antes?, etc.</p>
<p>Esta parte abre muchas interrogantes, en este caso supe que no solo se llama <em>Comet</em>, también que existen otras formas de resolver el mismo problema, por ejemplo con W<em>ebSocket.</em></p>
<p>Bueno pues a escribir mas palabras en el buscador. Momento, que un error en el que cuido no caer, es en abarcar mucho y reducir mi visión en búsqueda de la de la solución. Este problema lo resuelvo viendo demos, leyendo más artículos, y si aun no puedo saber con certeza que tecnología es la adecuada, es momento de la <em>resignación</em>, no hay de otra más que empezar a ensuciarse los dedos y quemarse las pestañas, pero sin perder el enfoque y sin desesperarse. <em>La paciencia es una aliada</em>.</p>
<p>Me he dado cuenta que mucha de la información que circula es repetitiva, dice muchas veces lo mismo, solo diferentes autores, así que necesito distinguir de las fuentes que valen la pena el esfuerzo, pero esto es algo gradual. Después de leer varios artículos, veo la palabra <em>Bayeux Protocol</em> una y otra vez, también <em>CometD Bayeux Ajax Push</em>, bueno pues resulta que la mejor fuente para aprender una nueva tecnología es en …, pues en la fuente misa de la tecnología, en la página oficial y su documentación. <em>Soy capaz de leer 5 hojas con contenido técnico en media hora, y también soy capaz de releerlas y entender algo diferente de la última vez en varias ocasiones seguidas.</em> Nadie nos agradecerá ni dara premios por leer rápido y no entender nada de lo que dice la documentación, lamentablemente no siempre existen los ejemplos copy/paste, así que solo queda ponerse cómodo y disfrutar de la función, o del método, en fin.</p>
<p lang="es-MX">
<p>Al final de de todo esto, leo completamente la página <a href="http://cometd.org/documentation" target="_top"><em>http://cometd.org/documentation</em></a> y resulta que si existe un copy/paste sencillo <em>primer</em>, sigo las instrucciones a la <em>Maven Way</em> y guala, ya soy un experto en esta tecnología.</p>
<p>Pues no, resulta que no hice mi tarea y no tendré recreo, así que a revisar el código. Después de descargar el proyecto <em>mvn</em>, reviso y estudio el código, gano la confianza para hacer cambios al código y ver qué sucede. Este momento es muy importante porque es cuando adaptamos el código que nos dan de ejemplo a nuestras necesidades.</p>
<p>Modifico el archivo <em>application.js</em> para <em>adaptarlo al estilo en el que yo escribo código</em> y con esto estudio y entiendo más sobre <em>comet</em>, por  ejemplo:</p>
<pre class="brush:js;">
var cometd = $.cometd;

$(document).ready(function(){

    var _connected = false;
    function _metaConnect(message){
        if (cometd.isDisconnected()){
            _connected = false;
            _connectionClosed();
            return;
        }

        var wasConnected = _connected;
        _connected = message.successful === true;
        if (!wasConnected &amp;&amp; _connected){
            _connectionEstablished();
        }
        else if (wasConnected &amp;&amp; !_connected){
            _connectionBroken();
        }
    }
    // Function invoked when first contacting the server and
    // when the server has lost the state of this client
    function _metaHandshake(handshake){
        if (handshake.successful === true){
            cometd.batch(function(){
                cometd.subscribe('/hello', function(message){
                    $('#body').append('
<div>Server Says: ' + message.data.greeting + '</div>

');
                });
                // Publish on a service channel since the message is for the server only
                cometd.publish('/service/hello', { name: 'World' });
            });
        }
    }

    var cometURL = location.protocol + "//" + location.host + config.contextPath + "/cometd";
    cometd.configure({
        url: cometURL,
        logLevel: 'debug'
    });

    cometd.addListener('/meta/handshake', _metaHandshake);
    cometd.addListener('/meta/connect', _metaConnect);
    cometd.handshake();
});

// Disconnect when the page unloads
$(window).unload(function(){
    cometd.disconnect(true);
});

/*Funciones xyz*/
var  _connectionEstablished = function(){
    $('#body').append('
<div>CometD Connection Established</div>

');
}

var _connectionBroken = function(){
    $('#body').append('
<div>CometD Connection Broken</div>

');
}

var _connectionClosed = function (){
    $('#body').append('
<div>CometD Connection Closed</div>

');
}
</pre>
<p>Y para terminar modifico <em>HelloService.java</em> con una muy ligera modificación, quedando así:</p>
<pre class="brush:java;">public void processHello(ServerSession remote, Message message) throws InterruptedException{
        Map input = message.getDataAsMap();
        String name = (String)input.get("name");

        Map output = new HashMap();
        output.put("greeting", "Hello, " + name);
        remote.deliver(getServerSession(), "/hello", output, null);

        Thread.sleep(3000);

        output.put("greeting", "Hello, " + "artesanos.de/software");
        remote.deliver(getServerSession(), "/hello", output, null);
}

Salida:
Server Says: Hello, World
CometD Connection Established
CometD Connection Broken
CometD Connection Established
Server Says: Hello, artesanos.de/software
</pre>
<p><span style="font-family: Cambria,serif"><span style="font-size: x-small">Gracias por tu tiempo y saludos. Atentamente: </span></span><span style="font-family: Cambria,serif"><span style="font-size: x-small"><span style="text-decoration: underline">Rodrigo Salado Anaya</span></span></span></p>
<img src="http://feeds.feedburner.com/~r/ArtesanosDeSoftware/~4/Es6MHEA7zuA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://artesanos.de/software/2011/09/01/pasar-de-la-curiosidad-al-codigo/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://artesanos.de/software/2011/09/01/pasar-de-la-curiosidad-al-codigo/</feedburner:origLink></item>
		<item>
		<title>Meta-información: Gana y aprende con Artesanos de Software ( how-to)</title>
		<link>http://feedproxy.google.com/~r/ArtesanosDeSoftware/~3/DAX0d6HMI-k/</link>
		<comments>http://artesanos.de/software/2011/09/01/meta-informacion-gana-y-aprende-con-artesanos-de-software-how-to/#comments</comments>
		<pubDate>Thu, 01 Sep 2011 07:01:21 +0000</pubDate>
		<dc:creator>OscarRyz</dc:creator>
				<category><![CDATA[Sin categoría]]></category>
		<category><![CDATA[gana y aprende]]></category>
		<category><![CDATA[meta]]></category>

		<guid isPermaLink="false">http://artesanos.de/software/?p=111</guid>
		<description><![CDATA[Como crear un artículo para participar en "Gana y aprende con Artesanos de Software"]]></description>
			<content:encoded><![CDATA[<div><span style="font-family: 'trebuchet ms', geneva">Como todo mundo ya sabe&#8230; ehem y si no pues acá lo repito, este sitio está organizando una dinámica para compartir el conocimiento de los que nos dedicamos a esta industria y que consiste en escribir un artículo y tener la posibilidad de ganar ( además de la satisfacción de contribuir claro está ) algún premio como un libro.</span></div>
<div>
</div>
<div></div>
<div><span style="font-family: 'trebuchet ms', geneva">Para más información y detalles ver la convocatoria:</span></div>
<div><span style="font-family: 'trebuchet ms', geneva"><br />
</span></div>
<div><a href="http://artesanos.de/software/2011/08/09/gana-y-aprende-con-artesanos-de-software"><span style="font-family: 'trebuchet ms', geneva">Gana y aprede con Artesanos de Software</span></a></div>
<div><span style="font-family: 'trebuchet ms', geneva"><br />
</span></div>
<div><span style="font-family: 'trebuchet ms', geneva"><img src="http://i.stack.imgur.com/UXK3B.png" alt="Gana y aprende" width="600" height="411" /></span></div>
<div><span style="font-family: 'trebuchet ms', geneva"><br />
</span></div>
<div><span style="font-family: 'trebuchet ms', geneva"> </span></div>
<div>
<div><span style="font-family: 'trebuchet ms', geneva">Como existe la posibilidad que alguien no sepa como participar ( como yo no sabía por ejemplo )   aquí van los pasos:</span></div>
<div><span style="font-family: 'trebuchet ms', geneva"><br />
</span></div>
<div><span style="font-family: 'trebuchet ms', geneva"><br />
</span></div>
</div>
<div>
<ul>
<li><span style="font-family: 'trebuchet ms', geneva">El artículo debe de ser escrito aquí mismo en <a href="http://artesanos.de/software">Artesanos.de/Software</a></span></li>
<li><span style="font-family: 'trebuchet ms', geneva">Para ello es necesario crear una cuenta:</span></li>
</ul>
</div>
<div>
<div><span style="font-family: 'trebuchet ms', geneva"><img src="http://i.stack.imgur.com/cm8GN.png" alt="Donde dice &quot;meta&quot;  Registrase" width="372" height="227" /></span></div>
<div><span style="font-family: 'trebuchet ms', geneva"><br />
</span></div>
<div><span style="font-family: 'trebuchet ms', geneva"><br />
</span></div>
</div>
<div>
<ul>
<li><span style="font-family: 'trebuchet ms', geneva"> Luego hay que entrar y  si no aparece la opción para crear un artículo hay que <em>&#8220;Contactar al administrador del sitio&#8221; </em> <img src='http://artesanos.de/software/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </span></li>
<li><span style="font-family: 'trebuchet ms', geneva"><em> </em>Finalmente escribir el artículo y recordad que debe de ser licenciado como creative commons</span></li>
</ul>
</div>
<div></div>
<div></div>
<div><em><span style="font-family: 'trebuchet ms', geneva">Tips: </span></em></div>
<div>
<p><span style="font-family: 'trebuchet ms', geneva">Para escribir código se puede usar la marca</span></p>
<pre><span style="font-family: 'trebuchet ms', geneva">&lt;pre&gt;...&lt;/pre&gt;</span></pre>
<p><span style="font-family: 'trebuchet ms', geneva">ejemplo:</span></p>
</div>
<div>
<pre><span style="font-family: 'trebuchet ms', geneva">&lt;pre class="brush:groovy;"&gt;
//Tu codigo
&lt;/pre&gt;

Y en lugar de groovy pon el lenguaje que ocupes. <a href="https://twitter.com/#!/neodevelop/status/109150096763006977"> <img src='http://artesanos.de/software/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </a>

La referencia de "Brush" que se puede usar está en:</span></pre>
</div>
<div><a href="http://alexgorbatchev.com/SyntaxHighlighter/manual/brushes/"><span style="font-family: 'trebuchet ms', geneva"><br />
</span></a></div>
<div><a href="http://alexgorbatchev.com/SyntaxHighlighter/manual/brushes/"><span style="font-family: 'trebuchet ms', geneva">http://alexgorbatchev.com/SyntaxHighlighter/manual/brushes/</span></a></div>
<div><span style="font-family: 'trebuchet ms', geneva"><br />
</span></div>
<div><span style="font-family: 'trebuchet ms', geneva">Y listo!  ya estarán participando</span></div>
<div></div>
<div>========================</div>
<div></div>
<div><span style="font-family: 'trebuchet ms', geneva">Escrito por: Oscar Reyes ( <a href="http://twitter.com/#!/oscarryz">@OscarRyz</a> ) </span></div>
<div></div>
<div><span style="font-family: 'trebuchet ms', geneva"><a href="http://creativecommons.org/licenses/by/3.0/"><img src="http://i.creativecommons.org/l/by/3.0/80x15.png" alt="" width="80" height="15" /></a></span></div>
<img src="http://feeds.feedburner.com/~r/ArtesanosDeSoftware/~4/DAX0d6HMI-k" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://artesanos.de/software/2011/09/01/meta-informacion-gana-y-aprende-con-artesanos-de-software-how-to/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://artesanos.de/software/2011/09/01/meta-informacion-gana-y-aprende-con-artesanos-de-software-how-to/</feedburner:origLink></item>
		<item>
		<title>¿Qué nos ofrecen las comunidades?</title>
		<link>http://feedproxy.google.com/~r/ArtesanosDeSoftware/~3/5LTdd44SUDc/</link>
		<comments>http://artesanos.de/software/2011/08/31/%c2%bfque-nos-ofrecen-las-comunidades/#comments</comments>
		<pubDate>Wed, 31 Aug 2011 21:02:53 +0000</pubDate>
		<dc:creator>neodevelop</dc:creator>
				<category><![CDATA[Sin categoría]]></category>

		<guid isPermaLink="false">http://artesanos.de/software/?p=103</guid>
		<description><![CDATA[Hace ya mucho tiempo escribí una entrada acerca de este tema, que considero puede entrar de nuevo en este contexto, aquí les pongo el texto de lo que escribí en su momento: En los últimos meses hemos tenido la oportunidad de trabajar en proyectos internos, sin embargo, una de las cosas que nos motivan a [...]]]></description>
			<content:encoded><![CDATA[<p>Hace ya mucho tiempo escribí una entrada acerca de este tema, que considero puede entrar de nuevo en este contexto, aquí les pongo el texto de lo que escribí en su momento:</p>
<p>En los últimos meses hemos tenido la oportunidad de trabajar en proyectos internos, sin embargo, una de las cosas que nos motivan a continuar desarrollando es el hecho de compartir lo que aprendemos a través de eventos, ya sea organizados por nosotros y también a los que nos invitan; y precisamente, como comunidad hemos estado bastante activos presencialmente hablando, por lo tanto, me gustaría listar un par de eventos/lugares a los cuales hemos asistido…</p>
<ul>
<li><a href="http://www.upaep.mx/">UPAEP(Universidad Popular Autónoma del Estado de Puebla)</a>
<ul>
<li>En donde con ayuda de Jaime Castillo y María del Rocío Gpe. Morales, presentamos el tema de:
<ul>
<li>“Lenguajes dinámicos para la JVM” por <a href="http://twitter.com/neodevelop">@neodevelop</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="http://tequilavalley.pbworks.com/FlisolOrganizacion">FLISOL(Esime Culhuacán)</a>
<ul>
<li>Enrique Díaz(<a href="http://twitter.com/nRikeDiaz">@nRikeDiaz</a>) fue organizador de este evento en esta universidad y junto con él pudimos participar en dos charlas:
<ul>
<li>“<a href="http://www.slideshare.net/domingo.suarez/10-aos-en-la-industria-que-esperar-de-la-universidad">10 años en la industria, ¿Que esperar de la universidad?</a>” por <a href="http://twitter.com/domix">@domix</a></li>
<li>“Introducción a Groovy” por mí(<a href="http://twitter.com/neodevelop">@neodevelop</a>)</li>
<li>“Introducción a Grails” por <a href="http://twitter.com/domix">@domix</a> y yo(<a href="http://twitter.com/neodevelop">@neodevelop</a>)</li>
</ul>
</li>
</ul>
</li>
<li><a href="http://gulev.org.mx/eventos/gulev2010/">GULEV(Grupo de Usuarios Linux del Estado de Veracruz)</a>
<ul>
<li>Con lugar en el WTC de Veracruz y organizada por Miguel Angel López (<a href="http://twitter.com/GulevSL">@GulevSL</a>), presentamos las ponencias de:
<ul>
<li>“<a href="http://www.slideshare.net/domingo.suarez/estrategias-giles-para-incrementar-calidad-al-construir-y-probar-software">Estrategias ágiles para incrementar calidad al construir y probar software</a>” por<a href="http://twitter.com/domix">@domix</a></li>
<li>“<a href="http://www.slideshare.net/neodevelop/introduccin-a-groovy">Groovy: el lenguaje dinámico para la JVM</a>” por <a href="http://twitter.com/neodevelop">@neodevelop</a></li>
<li>“<a href="http://www.slideshare.net/domingo.suarez/java-poliglota">Desarrollo políglota en la plataforma Java</a>” por <a href="http://twitter.com/domix">@domix</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<p>De cada uno de estos nos hemos llevado muy buenas experiencias, y precisamente esa es una de las tantas cosas que me da el pertenecer a una comunidad como springhispano.org y grails.org.mx: la posibilidad de conocer a más personas interesadas en el uso de tecnologías similares, de darle rostro al timeline, de tener charlas fluidas y amenas, de conocer los intereses e inquietudes de alumnos, maestros, empresarios, desarrolladores…</p>
<p><strong>La comunidad me ha dado conocimiento, ya que cada vez que se realiza una reunión los ponentes despiertan la inquietud del uso de herramientas que no conocía o simplemente había escuchado de ellas…</strong></p>
<p><strong>La comunidad me permite expresarme, exponer mis dudas, tener otro punto de vista diferente, ampliar mi abanico de posibilidades para resolver un problema…</strong></p>
<p><strong>Inclusive, me dió la capacidad de darles a los miembros la posibilidad de asistir a un curso de certificación a través del proyecto #PCJ…</strong></p>
<p><strong>En realidad, hay demasiadas cosas que puedo mencionar que considero aportación mutua; la actividad dentro de las comunidades es algo que me da identidad y que le da un verdadero significado al concepto ‘social’</strong></p>
<p>Espero que al igual que yo, los lectores y desarrolladores encuentren un interés en ser parte de comunidades, y por supuesto, en springhispano.org y grails.org.mx serán siempre bienvenidos…</p>
<img src="http://feeds.feedburner.com/~r/ArtesanosDeSoftware/~4/5LTdd44SUDc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://artesanos.de/software/2011/08/31/%c2%bfque-nos-ofrecen-las-comunidades/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://artesanos.de/software/2011/08/31/%c2%bfque-nos-ofrecen-las-comunidades/</feedburner:origLink></item>
	</channel>
</rss>

