<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	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/"
	>

<channel>
	<title>El blog de Carlos Ble</title>
	<atom:link href="http://www.carlosble.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.carlosble.com</link>
	<description>BrainStream.Write(Posts)</description>
	<lastBuildDate>Thu, 05 Apr 2012 22:59:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Compartir la visión de equipo</title>
		<link>http://www.carlosble.com/2012/04/compartir-la-vision-de-equipo/</link>
		<comments>http://www.carlosble.com/2012/04/compartir-la-vision-de-equipo/#comments</comments>
		<pubDate>Thu, 05 Apr 2012 22:13:34 +0000</pubDate>
		<dc:creator>Carlos Ble</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Software Development]]></category>

		<guid isPermaLink="false">http://www.carlosble.com/?p=1203</guid>
		<description><![CDATA[Para que un grupo de desarrolladores trabaje como un equipo, tal vez sea importante que  todos sus miembros tengan el mismo concepto de equipo. ¿Cómo es el equipo que queremos ser? ¿cuáles son las características que nos gustaría que tuviese cada persona del equipo? Si tenemos una visión diferente de cómo debe funcionar el equipo, no conseguiremos llegar a ella porque cada uno rema [...]]]></description>
			<content:encoded><![CDATA[<p>Para que un grupo de desarrolladores trabaje como un equipo, tal vez sea importante que  todos sus miembros tengan el mismo concepto de equipo.<br />
<strong>¿Cómo es el equipo que queremos ser? ¿cuáles son las características que nos gustaría que tuviese cada persona del equipo?</strong></p>
<p><strong></strong>Si tenemos una visión diferente de cómo debe funcionar el equipo, no conseguiremos llegar a ella porque cada uno rema en una dirección distinta.</p>
<p>Puede que tan sólo sea cuestión de detenerse un momento, reflexionar y decidir qué significa ser integrante de este equipo. Consensuar con los demás los valores y principios que<br />
nos parecen claves. Y que de ese consenso busquemos prácticas que nos ayuden a ser el equipo que queremos y nos hagamos fuertes.</p>
<p>Un principio que me gusta aplicar es el de <strong>hacer con los demás lo mismo que me gustaría que hiciesen conmigo.</strong></p>
<p>Así que voy a pensar cómo me gustaría que fuese un compañero de mi equipo para poner yo mismo en practica esos hábitos.<br />
Voy a hacer mi propia lista de "me gustaría...", la cual podemos completar entre todos los miembros del equipo. Aquí va.</p>
<p><strong><em>Me gustaria que un compañero... (o compañera, por supuesto)</em></strong></p>
<ul>
<li>Me pudiese cubrir perfectamente cuando estoy enfermo o de vacaciones sin que me tengan que llamar por teléfono contínuamente o pedirme que me conecte remotamente cuando no me encuentro en condiciones para ello.</li>
<li>Se tomase el tiempo de explicarme lo que sabe para que cuando se marche de vacaciones o se ponga enfermo, no me sienta totalmente perdido.</li>
<li>Me pidiese ayuda o hiciese programación en pareja conmigo cuando conozco mejor el código o el negocio que él o ella, porque así ganamos tiempo y aprendemos todos a la vez.</li>
<li>Me pidiese ayuda o trabajásemos juntos cuando sabe que el código que tiene que modificar es complejo y prefiere estar seguro de que no rompemos nada.</li>
<li>Me enseñase técnicas y prácticas que conoce para ser mejor profesional.</li>
<li>No me hiciese contarle más de tres veces una técnica de desarrollo sin que la tenga anotada y estudiada.</li>
<li>Trate de asegurarse por todos los medios que los cambios que ha introducido en el código no rompen funcionalidad existente (no introduce defectos).</li>
<li>Ejecutase los tests antes de subir su código al repositorio para evitar que me tenga que poner a arreglar tests que se han roto con cambios que no he hecho yo.</li>
<li>Tuviese la iniciativa de arreglar un test que no ha roto él o ella, cuando el compañero que lo rompió por accidente, ha sido avisado, pero no se puede poner con ello en ese momento. (Si quien ha dejado el test roto no suele romperlos sino que se trata de un caso excepcional).</li>
<li>Revisase mi código para entenderlo, detectar mejoras o sugerirme alternativas.</li>
<li>Criticase mi código constructivamente para ayudarme a mejorarlo y a superarme yo mismo.</li>
<li>Usase las partes de la aplicación que he hecho yo, para darme feedback como usuario.</li>
<li>Me pudiese sustituir en cualquier momento dándome la seguridad de que lo va a intentar hacer igual de bien que lo intento yo.</li>
<li>Esté abierto a recibir críticas constructivas y a aprender cada día.</li>
<li>Reconozca sus errores y se esfuerce por no cometer el mismo muchas veces.</li>
<li>Se alegre por mi progreso profesional y me apoye para que siga mejorando.</li>
<li>Tenga la iniciativa de aplicar cambios sobre código que he escrito yo, cuando necesita ser ampliado funcionalmente y yo no lo pueda hacer en ese momento (porque esté ocupado con otra tarea). Que no me haga sentir que soy el cuello de botella sino que me ayude a quitarme la presión de encima. Y que cuando cambie el código se asegure de que todos los tests siguen pasando y ha puesto el mismo nivel de cuidado en el código que el que he puesto yo.</li>
<li>Cuando tiene que introducir deuda técnica porque no le queda más remedio, lo anote y vuelva al código a saldarla tan pronto como el momento de presión termine.</li>
<li>Cuando tiene que modificar código de baja calidad se esfuerza por mejorarlo y no sólo por añadir a trancas y barrancas la nueva funcionalidad sobre la maraña.</li>
<li>Se cuestione si está haciendo lo mejor posible en cada momento y rectifica para ir en esa dirección.</li>
<li>No haya que repetirle las cuestiones con las que ya en otra ocasión hemos acordado que nos vamos a comprometer.</li>
<li>Escriba código que puedo entender sin tener que preguntarle a nadie. Y además lo puedo ampliar y testear con facilidad.</li>
<li>Antes de tomar decisiones que tienen repercusión sobre los demás, las discuta con los implicados.</li>
<li>Si no está de acuerdo con algo que digo, tenga la sinceridad de decirmelo a la cara en el momento adecuado, mejor que a destiempo.</li>
<li>Por tanto el equipo que yo visualizo se mueve en bloque, es homogéneo porque comparte unos valores y principios.</li>
</ul>
<p>En mi visión de equipo no entra esto de "yo hago mi parte y tu la tuya", y cuando pasa algo en la parte que es "tuya" te llamamos para que la arregles tu. En una situación excepcional si, no hay reglas fijas ni matematicas puras para el día a día.</p>
<p>En esta visión tampoco hay tareas que siempre hace la misma persona porque es la única que sabe y parece que siempre va a seguir siendo así.<br />
<strong>No puede haber personas que parecen ser imprescindibles</strong>. En realidad nadie lo es por muy alto que sea su <a href="http://en.wikipedia.org/wiki/Bus_factor">bus factor</a>. La vida sigue aunque unos marchen y otros lleguen.</p>
<p>Pero mi visión de equipo no sirve si mis compañeros no la comparten.</p>
<p>El compañero al que recuerdo con una sonrisa es el que me lo pone fácil en el día a día. El que no me obliga a verme sometido a presión innecesaria por un trabajo que él o ella ha hecho con neglicencia. Que no me obliga a hacer horas extra por su falta de cuidado.</p>
<p>Ser un amigo no tiene por qué ser lo mismo que ser un buen compañero. Ser un tío majo y agradable no significa ser buen compañero. Es de agradecer tratar con compañeros agradables pero eso no hace un buen equipo por sí sólo.</p>
<p>Puedes rellenar este interesante cuestionario sobre el nivel de agilidad de tu equipo y reflexionar sobre los resultados: <a href="http://www.abetterteam.org/new">http://www.abetterteam.org/new</a></p>
<p>Animaría a los equipos a redactar su propia lista de cualidades de un miembro del equipo y a colgarla en una pared grande, donde siempre sea visible para todos. Que nuestro ego no se pase por el forro esa lista sin que se note, sino que de el cante y podamos poner a ese ego en su sitio en favor de los valores del grupo.</p>
<p>No es otro que el ego quien causa problemas a individuos y grupos. Hay que vigilarle.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.carlosble.com/2012/04/compartir-la-vision-de-equipo/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>¿De verdad necesitas estar a la última?</title>
		<link>http://www.carlosble.com/2012/03/de-verdad-necesitas-estar-a-la-ultima/</link>
		<comments>http://www.carlosble.com/2012/03/de-verdad-necesitas-estar-a-la-ultima/#comments</comments>
		<pubDate>Sat, 17 Mar 2012 20:21:43 +0000</pubDate>
		<dc:creator>Carlos Ble</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Software Development]]></category>

		<guid isPermaLink="false">http://www.carlosble.com/?p=1193</guid>
		<description><![CDATA[La mayor barrera a la que un equipo se enfrenta a la hora de practicar XP o cualquier método ágil, son las personas. La falta de madurez y de compromiso imposibilita la paz sostenible de la que tanto se habla. Ambas, madurez y compromiso pueden a veces inferirse por el nivel de consumismo de los [...]]]></description>
			<content:encoded><![CDATA[<p>La mayor barrera a la que un equipo se enfrenta a la hora de practicar XP o cualquier método ágil, son las personas. La falta de madurez y de compromiso imposibilita la paz sostenible de la que tanto se habla. Ambas, madurez y compromiso pueden a veces inferirse por el nivel de consumismo de los individuos.</p>
<p>Conozco demasiados programadores que van a la última en tecnología, pero que NO lo necesitan.</p>
<p>Probablemente cuando sacan de la funda el último móvil o el último portátil que acaban de comprar se sientan más importantes. Esto es lo que vende la televisión y la publicidad en general de las grandes marcas. Yo sin embargo no puedo evitar pensar que es una persona excesivamente consumista. A su vez eso puede significar que:</p>
<ul>
<li>Aún vive con sus padres. Sus niveles de madurez, iniciativa y responsabilidad son mediocres.</li>
<li>Nunca se ha parado a pensar en el impacto que la fabricación de ese hardware tiene sobre el planeta y sobre los pobres chinos que están explotados fabricandolo. Esto es falta de compromiso con el planeta, que lo está pidiendo a gritos.</li>
<li>Es muy probable que jamás haya donado dinero para ninguna causa social, animal o medio ambiental. Ni siquiera a su proyecto open source favorito. De nuevo, poco compromiso. Puede que resultase ser un compañero demasiado egoista como para hacer un buen equipo.</li>
<li>Es demasiado materialista como para importarle el crecimiento personal de sus compañeros lo suficiente.</li>
<li>Es una persona que compra compulsivamente porque no tiene claras sus metas, no sabe por qué razón se levanta cada mañana.</li>
</ul>
<p>No tienen que cumplirse todos los puntos, incluso puede que ninguno. Si los lees y te pica, entonces tu sabrás. Pero esto no es malo si te sirve para reflexionar sobre ello. Simplemente significa que tienes que deternete un momento y pensar más en lo que haces y en por qué lo haces. Que lo hagan todos tus amigos no significa que sea correcto. Has venido al mundo para hacerlo un sitio mejor, igual que mejoras el código legado cuando pasa por tu manos, aunque te llegue lleno de mierda hasta las trancas. Esos son los valores que necesitamos para practicar XP.</p>
<p>No necesitas mirar twitter cada 5 minutos. Piensa en la manera en que estas faltando el respeto a la persona que ha quedado para tomar café contigo, cuando estas escribiendo un tweet vació sobre el bonito uniforme del camarero. Los móviles que se vendían hacen pocos años tienen una batería que dura una semana entera. Se habla por telefono de puta madre y se pueden enviar mensajes SMS. ¿Necesitas poder consultar tu email en el tren? Ok, te vendrá bien un smartphone. ¿Pero de verdad no puedes esperar a gestionar tu email con tranquilidad? Seguramente el conductor del autobus se sentirá mejor si al subirte le das los buenos dias en vez de ir escribiendo en tu telefono nuevo. Puedes mandarle un tweet de buenos dias pero es más rápido que se los digas de boca a oreja.</p>
<p>No necesitas que tu portatil tenga 4 núcleos, 8gb de ram y una SSD de 200gb si trabajas con un pc de sobremesa que ya tiene las prestaciones suficientes. Si es tu herramienta de trabajo principal y realmente eres más productivo con ese hardware, adelante, se productivo. ¿Pero es de verdad tu necesidad? Los portátiles que fabricaban hace 6 años siguen corriendo perfectamente Linux y Windows. Con renovar la batería y ampliarle un poco la ram, van de lujo.</p>
<p>Ahora está de moda comprar un portatil Mac. Si vas a un evento y no tienes uno pareces un aficionado. Ya sabemos todos la polémica que hay con la fabricación de los Mac en cuanto al nivel de explotación en las fábricas y a pesar de ello... ¿es de culto tener uno?. Por desgracia pocas serán las marcas que se preocupen por las personas y el medio ambiente. Si eres más productivo con MacOS, está bien pero ¿no te vale con uno de segunda mano? ¿se van a reir de ti tus amigos? Yo no tengo un Mac, porque ahora mismo en el trabajo uso forzosamente Windows y en casa llevo una década usando Linux y encuentro que soy suficientemente productivo con el. Tengo Vim, Emacs y mucho mas! <img src='http://www.carlosble.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /><br />
Por cierto que el stack tecnologico del trabajo me obliga a usar un pc sobremesa del copon gracias a que Microsoft no repara en recursos con sus sistemas operativos. Intentaremos usar Windows 7 por 20 años porque para la siguiente version, nos va a hacer falta un reactor nuclear. Es otra opción que hay que barajar, no actualizar de version Windows hasta que no quede otro remedio. De hecho Windows XP va estupendo para todo lo que no sea Visual Studio 2010.</p>
<p>¿Esto significa ser antiprogreso? Solo significa tomar las decisiones por motivos bien claros y no por parecer mas geek. Ser más geek mina los proyectos, las relaciones con los clientes, la relación con los compañeros y hasta calidad del software. ¿A ti te pega que <a href="http://en.wikipedia.org/wiki/Marty_McFly">Martin McFly</a> llegase a casa con su skate volador y escribiese métodos de 5 lineas? A mí no.</p>
<p>¿Eres tu McFly con los aparatos mágicos? ¿tal vez el Inspector Gadget?</p>
<p>Si no te habías parado a pensarlo, ya sabes que eso no te hace más profesional a los ojos de todo el mundo. Para ser más profesional y una persona más integra, hay que prestar atención y practicar. En ello estamos. Si puedo ayudarte, grita, yo también estoy intentando aprender todo esto <img src='http://www.carlosble.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Aquí dejo un video que me parece fenomenal con Joán Melé hablando del dinero y la crisis. Yo la crisis no la estoy percibiendo economicamente en mi trabajo (sí en mi familia) pero sí que percibo una crisis tremenda en el sector por una falta de valores que nos permite ser ágiles de verdad.<br />
&nbsp;<br />
<object style="height: 390px; width: 640px"><param name="movie" value="http://www.youtube.com/v/UK3hC1xxHQM?version=3&feature=player_detailpage"><param name="allowFullScreen" value="true"><param name="allowScriptAccess" value="always"><embed src="http://www.youtube.com/v/UK3hC1xxHQM?version=3&feature=player_detailpage" type="application/x-shockwave-flash" allowfullscreen="true" allowScriptAccess="always" width="640" height="360"></object><br />
&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.carlosble.com/2012/03/de-verdad-necesitas-estar-a-la-ultima/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>RS: Sprint por historia de usuario</title>
		<link>http://www.carlosble.com/2012/02/rs-sprint-por-historia-de-usuario/</link>
		<comments>http://www.carlosble.com/2012/02/rs-sprint-por-historia-de-usuario/#comments</comments>
		<pubDate>Fri, 17 Feb 2012 23:02:44 +0000</pubDate>
		<dc:creator>Carlos Ble</dc:creator>
				<category><![CDATA[Retrospectivas]]></category>

		<guid isPermaLink="false">http://www.carlosble.com/?p=1191</guid>
		<description><![CDATA[Con una entrada de trabajo tremenda los sprints semanales se han ido terminando sin consecución de las metas esperadas. Cada semana con un poco más de atasco y menos objetivos cumplidos. Uno de los factores principales es que los criterios de aceptación no estaban claros y ello provoca trabajo en vano.  Por falta de análisis [...]]]></description>
			<content:encoded><![CDATA[<p>Con una entrada de trabajo tremenda los sprints semanales se han ido terminando sin consecución de las metas esperadas. Cada semana con un poco más de atasco y menos objetivos cumplidos. Uno de los factores principales es que <strong>los criterios de aceptación </strong>no estaban claros y ello provoca trabajo en vano.  Por falta de análisis se toman decisiones equivocadas que tienen un alto coste y una estimación imposible (estimar sin saber con precisión lo que se necesita es "duro"). Se hace muy difícil calcular el valor que se aporta al negocio y la prioridad de la tarea. Se invierte un tiempo en planificación y retrospectiva del sprint para que no se termine la tarea.</p>
<p>Así que hemos pensado que hasta estabilizar la situación, <strong>dejamos los sprints semanales</strong> y hacemos un sprint por cada historia de usuario. Lo primero que se hará con la historia es sacar con la máxima precisión los criterios de aceptación. Escribiremos<strong> tests end-to-end al inicio de la historia</strong> (siempre que el codigo legado nos lo permita) que validarán su consecución. Así sabremos con exactitud lo que está terminado y sabremos que funciona. Además la figura del middle-man que traduce las charlas con el cliente en historias y criterios de aceptación se diluye un poco y todo el equipo se encarga de analizar y conseguir esos criterios: <strong>Más cohesión entre análisis-negocio y desarrollo</strong>.</p>
<p><strong>El equipo de QA</strong> se convierte en un cuello de botella por deficiencia del proceso (o ausencia). Decidimos que los responsables de QA tendrán un pequeño meeting diario para ver cómo van las incidencias. Los jueves se hará especial esfuerzo en probar todo para confirmar que se puede desplegar en producción.</p>
<p>Además dedicaremos <strong>el último pomodoro del día a probar</strong> entre todos las tarjetas que están en estado "listo para UAT" para que lleguen más filtradas al equipo de QA.</p>
<p>Es prioritario reducir al mínimo la distancia entre el código que hay desplegado en producción y la rama principal del control de versiones. El ideal es poder desplegar en cualquier momento la rama principal, ya que usamos ramas para funcionalidades que están sin terminar. No obstante, a veces nos gustaria desplegar aunque haya funcionalidad a medias. Por eso vamos a intentar seguir <strong>puliendo la técnica de <a href="http://jamesmckay.net/2011/07/why-does-martin-fowler-not-understand-feature-branches/">feature branches</a> y </strong>además añadir en alguna ocasión<strong> feature toggles.</strong></p>
<p><strong>La información del kanban</strong> al final de la semana no va a parar a ningún documento histórico ni estadístico. Esto va a cambiar ya, para que tengamos el registro más fiable posible de costes en el corto, medio y largo plazo. Me encargo yo mismo. Esta información lógicamente no será pública <img src='http://www.carlosble.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p><strong>La mejora contínua</strong> sigue adelante y en estas semanas hemos avanzado con paso firme en lo siguiente:</p>
<ul>
<li>Hay menos interrupciones. Antes de interrumpirnos entre nosotros nos preguntamos por skype o email y al terminar el pomodoro hablamos entre nosotros.</li>
<li>Estamos más concienciados con probar a mano las tarjetas antes de pasarlas al equipo de QA.</li>
<li>Cada día nos preocupa más la deuda técnica y pensamos más antes de programar.</li>
<li>Las reuniones diarias (daily meeting) van cada vez más fluidas, tardamos entre 10 y 15 minutos.</li>
<li>Las reuniones de retrospectiva son más directas y nos dan más información.</li>
<li>El número de tests automáticos sigue creciendo y su calidad también. Hemos alcanzado ya los 500 tests con javascript.</li>
<li>Hemos hecho varias mejoras de arquitectura sin que el cambio sea muy costoso ni traumático.</li>
<li>Hablamos más unos con otros y discutimos sobre código y arquitectura en el proyector antes de lanzarnos a programar lo primero que se nos ocurre.</li>
</ul>
<p>El camino es largo, pero vamos mejorando hacia XP. Sólo hay que seguir vigilando para no retroceder y seguir practicando la <strong>honestidad</strong>, la <strong>valentía</strong> de hacer lo que es bueno para uno mismo (y eso será lo mejor para el equipo) y el <strong>sentido común</strong>. Ser consecuentes con lo que se hace y constantes con las prácticas.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.carlosble.com/2012/02/rs-sprint-por-historia-de-usuario/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Linq to Sql Horrors</title>
		<link>http://www.carlosble.com/2012/02/linq-to-sql-horrors/</link>
		<comments>http://www.carlosble.com/2012/02/linq-to-sql-horrors/#comments</comments>
		<pubDate>Fri, 10 Feb 2012 22:15:52 +0000</pubDate>
		<dc:creator>Carlos Ble</dc:creator>
				<category><![CDATA[Software Development]]></category>

		<guid isPermaLink="false">http://www.carlosble.com/?p=1172</guid>
		<description><![CDATA[Linq to Sql is a kind of ORM for .Net by Microsoft. Working with Linq to Sql can be a nightmare. The basics: In order to send or retrieve objects to or from the database, you need a DataContext instance. This is an instance of a class that inherits DataContext. It is created by Visual [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://msdn.microsoft.com/en-us/library/bb386976.aspx">Linq to Sql</a> is a kind of ORM for .Net by Microsoft. Working with Linq to Sql can be a nightmare.</p>
<ul>
<li><strong>The basics:</strong></li>
</ul>
<p>In order to send or retrieve objects to or from the database, you need a <a href="http://msdn.microsoft.com/en-us/library/system.data.linq.datacontext.aspx">DataContext </a>instance. This is an instance of a class that inherits DataContext. It is created by Visual Studio with drag and drop. One context is generated for every database you access to. This generated context is inside a <em>.cs file</em> which contains also the classes that map database tables. The mapping is contained in a <em>.dbml file (xml)</em> generated in the same folder. You should not change any of this generated files. If a table changes in the database you must regenerate with the IDE.</p>
<p><span style="text-decoration: underline;">Select example:</span><br />
If the name of the database is ProductionDB, the DataContext will be ProductionDBDataContext.</p>
<pre class="csharp">var context = <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> ProductionDBDataContext<span style="color: #000000;">&#40;</span>connectionString<span style="color: #000000;">&#41;</span>;
var userEntity = <span style="color: #000000;">&#40;</span>from user <span style="color: #0600FF;">in</span> context.<span style="color: #0000FF;">Users</span>
	where user.<span style="color: #0000FF;">name</span> == <span style="color: #808080;">&quot;carlos&quot;</span>
        select user<span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">First</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;</pre>
<p><span style="text-decoration: underline;">Insert example:</span></p>
<pre class="csharp">var context = <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> ProductionDBDataContext<span style="color: #000000;">&#40;</span>connectionString<span style="color: #000000;">&#41;</span>;
var user = <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> User<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;
user.<span style="color: #0000FF;">name</span> = <span style="color: #808080;">&quot;manolo&quot;</span>; 
context.<span style="color: #0000FF;">Users</span>.<span style="color: #0000FF;">InsertOnSubmit</span><span style="color: #000000;">&#40;</span>user<span style="color: #000000;">&#41;</span>;
context.<span style="color: #0000FF;">SubmitChanges</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;</pre>
<ul>
<li><strong>The main issue:</strong></li>
</ul>
<p><strong>The same context instance have to be used for all the operations performed on a relational object instance</strong>. This would throw an exception:</p>
<pre class="csharp">var context = <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> ProductionDBDataContext<span style="color: #000000;">&#40;</span>connectionString<span style="color: #000000;">&#41;</span>;
var userEntity = <span style="color: #000000;">&#40;</span>from user <span style="color: #0600FF;">in</span> context.<span style="color: #0000FF;">Users</span>
	where user.<span style="color: #0000FF;">name</span> == <span style="color: #808080;">&quot;carlos&quot;</span>
        select user<span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">First</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;
<span style="color: #008080; font-style: italic;">// Imagine this is part of another method in another place</span>
<span style="color: #008080; font-style: italic;">// but with the same userEntity instance that was passed through:</span>
userEntity.<span style="color: #0000FF;">age</span> = <span style="color: #808080;">&quot;30&quot;</span>;
var otherContextInstance = <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> ProductionDBDataContext<span style="color: #000000;">&#40;</span>connectionString<span style="color: #000000;">&#41;</span>;
otherContextInstance.<span style="color: #0000FF;">Users</span>.<span style="color: #0000FF;">InsertOnSubmit</span><span style="color: #000000;">&#40;</span>user<span style="color: #000000;">&#41;</span>;
otherContextInstance.<span style="color: #0000FF;">SubmitChanges</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;</pre>
<p>So you can't just pass relational objects from one method or layer to anoter, you have to always cope with the <em>"same context instance problem"</em>.</p>
<ul>
<li><strong> Solutions</strong></li>
</ul>
<ol>
<li>Pass the context instance along with the relational objects, in all the places where you need to perform database access:   <em>someMethod(user, context);<br />
<span style="text-decoration: underline;">Bad choice:</span> </em>This leads to <strong>spaguetti code</strong> quickly. Why  does my business layer have to know about a database context?</li>
<li>Ok so we can make a Singleton for the context instance and make sure it is the same for all the application:<br />
<em>public static ProductionDBDataContext AppContext = new ProductionDBDataContext(connString);</em><br />
<span style="text-decoration: underline;">Bad choice:</span> When more than one request hit the server at the same time you get <strong>concurrency problems</strong>. The context will be trying to insert in one thread while trying to update or select in other. Weird race conditions happens and exceptions are thrown.</li>
<li>Create a context for every thread. Every thread will have its own context Singleton. We found this solution thanks to Rick Strahl and <a href="http://www.west-wind.com/weblog/posts/2008/Feb/05/Linq-to-SQL-DataContext-Lifetime-Management">his great post</a>. However Rick's code can be simplified this way:</li>
</ol>
<pre class="csharp"><span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> ContextFactory
<span style="color: #000000;">&#123;</span>
	<span style="color: #000000;">&#91;</span>ThreadStatic<span style="color: #000000;">&#93;</span>
	<span style="color: #0600FF;">private</span> <span style="color: #0600FF;">static</span> ProductionDBDataContext context;
	<span style="color: #0600FF;">private</span> <span style="color: #FF0000;">string</span> connString = <span style="color: #808080;">&quot;settings to access the database ...&quot;</span>;
&nbsp;
	<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">static</span> DataContext Context<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#123;</span>
		<span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>context == <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span>
			context = <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> ProductionDBDataContext<span style="color: #000000;">&#40;</span>connString<span style="color: #000000;">&#41;</span>;
		<span style="color: #0600FF;">return</span> context;
	<span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre>
<p>The <a href="http://msdn.microsoft.com/en-us/library/system.threadstaticattribute.aspx">ThreadStatic attribute</a> ensures that every thread will access a different instance. So the "context" is not shared amont threads. This simplifies Ricks's code. But our problems didn't stop here unfortunatelly <img src='http://www.carlosble.com/wp-includes/images/smilies/icon_sad.gif' alt=':-(' class='wp-smiley' /> </p>
<p>You might expect the thread to die when the response is sent back to the client side, but it doesn't. Sometimes IIS reuses the thread for other requests, and the context is not a new, fresh instance. Moreover, <strong>the context caches</strong> some queries and that leads to several issues:</p>
<ol>
<li>The <a href="http://msdn.microsoft.com/en-us/library/bb399373.aspx">optimistic concurrency control</a> nightmare. The default behavior is for "Linq to Sql" to check every db column on update, to see if there are more than one simultaneous attemp to persist the entity. If so, it raises the <a href="http://msdn.microsoft.com/en-us/library/system.data.linq.changeconflictexception.aspx">ChangeConflictException</a>. This can be avoided by editing the dbml and marking every column with<em> "Never"</em> in the <em>UpdateCheck</em> property. Guess that.... when you regenerate the dbml file, this is overwritten and you loose your configuration. More information on <a href="http://msdn.microsoft.com/en-us/library/bb399389.aspx">conflicts here</a>.<br />
One way to deal with conflicts is to catch the exception and force the update:</p>
<pre class="csharp">var someEntity = ... <span style="color: #008080; font-style: italic;">// query here</span>
<span style="color: #0600FF;">try</span>
<span style="color: #000000;">&#123;</span>
    context.<span style="color: #0000FF;">SubmitChanges</span><span style="color: #000000;">&#40;</span>ConflictMode.<span style="color: #0000FF;">ContinueOnConflict</span><span style="color: #000000;">&#41;</span>;
<span style="color: #000000;">&#125;</span>
<span style="color: #0600FF;">catch</span> <span style="color: #000000;">&#40;</span>ChangeConflictException e<span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
   context.<span style="color: #0000FF;">Refresh</span><span style="color: #000000;">&#40;</span>RefreshMode.<span style="color: #0000FF;">KeepCurrentValues</span>, someEntity<span style="color: #000000;">&#41;</span>;
<span style="color: #000000;">&#125;</span></pre>
<p>However, this does not avoid the cache invalidation problem.</li>
<li><strong>The cache invalidation problem</strong>is the last one we have found and solved so far. The solution is to drop the cache as the new request enters the server. To refresh the cache just create a new instance of the context:
<pre class="csharp"><span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> ContextFactory
<span style="color: #000000;">&#123;</span>
	<span style="color: #000000;">&#91;</span>ThreadStatic<span style="color: #000000;">&#93;</span>
	<span style="color: #0600FF;">private</span> <span style="color: #0600FF;">static</span> ProductionDBDataContext context;
	<span style="color: #0600FF;">private</span> <span style="color: #FF0000;">string</span> connString = <span style="color: #808080;">&quot;settings to access to database ...&quot;</span>;
&nbsp;
	<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">static</span> DataContext Context<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#123;</span>
		<span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>context == <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span>
			context = <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> ProductionDBDataContext<span style="color: #000000;">&#40;</span>connString<span style="color: #000000;">&#41;</span>;
		<span style="color: #0600FF;">return</span> context;
	<span style="color: #000000;">&#125;</span>
	<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">static</span> <span style="color: #0600FF;">void</span> FlushContext<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#123;</span>
		context = <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> ProductionDBDataContext<span style="color: #000000;">&#40;</span>connString<span style="color: #000000;">&#41;</span>;
	<span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #000000;">&#125;</span></pre>
<p>Then, in the first layer of the server side (where the request is received) we call <em>FlushContext</em> to make sure it is new for this request. (For us is our JsonRpcController, a custom make controller hierarchy).</li>
</ol>
<p>For now, we can rest assured that our DataContext is:</p>
<ul>
<li>Unique for every thread so it is thread-safe.</li>
<li>Unique for every request so there are no cache problems among different requests.</li>
<li>If two different parts of the application need a context's instance in the same request, our factory gives a single reference (Singleton), making sure that only the first access initializes it (because we check whether it is null before instantiating).</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.carlosble.com/2012/02/linq-to-sql-horrors/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Un solo valor de retorno</title>
		<link>http://www.carlosble.com/2012/01/un-solo-valor-de-retorno/</link>
		<comments>http://www.carlosble.com/2012/01/un-solo-valor-de-retorno/#comments</comments>
		<pubDate>Fri, 27 Jan 2012 18:17:54 +0000</pubDate>
		<dc:creator>Carlos Ble</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Test Driven Development]]></category>

		<guid isPermaLink="false">http://www.carlosble.com/?p=1160</guid>
		<description><![CDATA[Hay un mal que se esta extendiendo por la aplicación en las últimas semanas. Es el ResponseDTO. Es un objeto plano, tiene un campo "success" de tipo boolean y un campo "message" de tipo string. Debía llamarse Response pero colisionaba, así que se quedó con un mal nombre. Si le hubiesemos llamado ControllerResponse seguramente no [...]]]></description>
			<content:encoded><![CDATA[<p>Hay un mal que se esta extendiendo por la aplicación en las últimas semanas. Es el <strong>ResponseDTO</strong>. Es un objeto plano, tiene un campo <strong>"success"</strong> de tipo<em> boolean</em> y un campo<strong> "message"</strong> de tipo <em>string</em>. Debía llamarse Response pero colisionaba, así que se quedó con un mal nombre. Si le hubiesemos llamado <strong>ControllerResponse</strong> seguramente no se hubiese usado en las otras capas de la aplicación porque hubiese dado más pistas a quienes lo fuesen usar, de que su lugar es la capa controller. Sin embargo se ha colado en muchas capas de backend y no es una buena práctica:</p>
<p><strong>Los metodos y funciones deben devolver un solo resultado</strong> y en ocasiones, ninguno (void). ResponseDTO se puede considerar "un solo resultado" cuando los campos "success" y "message" se necesitan el uno al otro, tal que no tiene sentido el objeto sin los dos campos. Es decir cuando el objeto es lo más atómico que la operación puede devolver. ResponseDTO se ideo para enviar a cliente (js) respuesta a determinados comandos que solicita al servidor pero no debería usarse en las otras capas de la aplicacion.</p>
<p>¿Dónde lo usamos mal? Tenemos métodos con un nombre interrogativo que denotan retorno boolean y sin embargo devuelven uno de estos ResponseDTO:</p>
<ul>
<li>IsExistingUser</li>
<li>DoesPolicyExists</li>
<li>IsValidInput</li>
</ul>
<p>Para cualquiera que lea la API, no es intuitivo. ¿Para qué sirve el "message" del objeto cuando el método "IsExistingUser" retorna? Para nada.</p>
<p>En la validación, puede tener sentido este objeto response dependiendo del contexto: Si el error de validación puede considerarse una circunstancia excepcional, entonces lo mejor es lanzar una excepción que alguien de nivel superior recogerá. Por tanto, sobra el objeto response ya que la excepción llevará el mensaje de validación particular. Si un problema de validación no se considera una circunstancia excepcional, entonces puede estar bien devolver el response con su success puesto  a false y su mensaje concreto.</p>
<p>Más sitios donde lo usamos mal: Métodos que disparan acciones hacia fuera de nuestro sistema</p>
<ul>
<li> SendEmail</li>
<li> SaveUser</li>
</ul>
<p>Los métodos que provocan acciones que salen de los límites de nuestro código (acceso a BD, a un servidor de correo, etc) no pueden garantizar la correcta consumación de la acción. Por tanto, jugar a devolver boolean para exito o fracaso es engañarnos.<br />
Es preferible un método <strong>void</strong> que funciona sin hacer ruido cuando todo va bien y que lanza excepciones cuando se encuentra con una situación inesperada. Por ejemplo, el método que solicita el envio de un email, puede defenderse de excepciones que provoque la libreria de SMTP y traducirlas en excepciones de nuestro dominio, tales como EmailSendFailure (una excepción nuestra que hereda de <a href="http://msdn.microsoft.com/en-us/library/system.applicationexception.aspx">ApplicationException</a>).</p>
<p>¿Y es tan grave que usemos el ResponseDTO? Sí que lo es porque el código que consume esos métodos se convierte en spaguetti:</p>
<pre class="csharp">var isNotValidData = !InputValidator.<span style="color: #0000FF;">ValidateUserData</span><span style="color: #000000;">&#40;</span>
                          policyHolder.<span style="color: #0000FF;">Person</span><span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">success</span>;
<span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>isNotValidData<span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	response.<span style="color: #0000FF;">message</span> = Strings.<span style="color: #0000FF;">T</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;Los datos son incorrectos.&quot;</span><span style="color: #000000;">&#41;</span>;
	<span style="color: #0600FF;">return</span> response;
<span style="color: #000000;">&#125;</span></pre>
<p>Del método "ValidateUserData" sólo nos interesa el campo "success", el mensaje lo está generando el llamador. No sólo es raro de leer sino que es un coñazo a la hora de escribir tests de interacción. Cuando queremos que en un test de colaboración, este método devuelva falso, tenemos que especificar que devuelva un objeto con un campo a falso. Si fuera boolean, no tendriamos que especificar nada porque el valor por defecto sería false. <a href="http://www.carlosble.com/2012/01/cleaner-interaction-tests/">Esto va al hilo del posts de los tests de interacción limpios</a>.</p>
<p>En el caso de métodos de acción como el envio de email, es incluso peor porque quien consume el método pensará que con un resultado verdadero el email ha llegado a su destino, como si eso lo pudiesemos asegurar de alguna manera.</p>
<p><strong>Para saber qué debe devolver un método, este debe tener una única responsabilidad y debemos saber cual es. Y la mejor manera de saberlo, para mi siempre es escribir el test antes que el código.</strong></p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.carlosble.com/2012/01/un-solo-valor-de-retorno/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Cleaner interaction tests</title>
		<link>http://www.carlosble.com/2012/01/cleaner-interaction-tests/</link>
		<comments>http://www.carlosble.com/2012/01/cleaner-interaction-tests/#comments</comments>
		<pubDate>Thu, 26 Jan 2012 15:12:12 +0000</pubDate>
		<dc:creator>Carlos Ble</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Test Driven Development]]></category>

		<guid isPermaLink="false">http://www.carlosble.com/?p=1144</guid>
		<description><![CDATA[Note: this post will probably evolve, the text will be updated as I need it. In order to write cleaner interaction tests (those which use test doubles; mocks, spies, stubs) you should understand how your test doubles framework works. Interaction tests can be extremely difficult to read and maintain and very fragile if you don't [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Note: this post will probably evolve, the text will be updated as I need it.</strong></p>
<p>In order to write cleaner interaction tests (those which use test doubles; <strong>mocks, spies, stubs</strong>) you should understand <strong>how your test doubles framework works</strong>. Interaction tests can be extremely difficult to read and maintain and very fragile if you don't pay enough attention. We will review <a href="http://mockito.org">Mockito</a>, <a href="http://code.google.com/p/moq/">Moq</a>, <a href="http://pivotal.github.com/jasmine/">Jasmine </a>and <a href="http://www.pydoubles.org">pyDoubles</a>.</p>
<p>Mockito and Moq create a double object by inheriting the original and overriding its methods. pyDoubles uses interception rather than inheritance. Jasmine is different because it does not double the whole object, but just the method you spy on. So there is a big difference: <strong>Mockito, Moq and pyDoubles replace the whole object while Jasmine replaces just one method</strong>.</p>
<p>So Jasmine leaves space for a <strong>bad testing practice</strong>: Spy on one method of the object while testing other method of the same object. Interaction tests are intentded for object collaboration.<strong> Testing that one method calls another method within the same object is not recommended</strong>. It means that the object has more than one responsibility or that you want to know more about the object's inner behavior than you should, so you are breaking encapsulation. This is not a Jasmine problem, the problem is yours if you don't use the tool properly.</p>
<p>There are three primary reasons to replace method calls on collaborators:</p>
<ol>
<li>You want to avoid a database call just to keep the test unit fast and repeatable (stub the method - use a stub object)</li>
<li>You want the method to return some value to simulate the response (stub the method - use a stub object)</li>
<li>You want to make sure that a call is made (spy or expect the call - use a spy or a mock object)</li>
</ol>
<p><span style="text-decoration: underline;">For case numer 1</span>, you don't have to specify the returned value. Just use the stub object and let the framework return whatever it wants. <strong>Mockito and Moq, return the default value for the method, when no other behavior is specified</strong>:</p>
<ul>
<li>If the method returns an integer, a call to that method in the stub object, will return cero (default value for integers)</li>
<li>If the method returns an object (reference type), a call to the stub method <strong>will return null</strong> (default for objects)</li>
<li>False for booleans and so on...</li>
</ul>
<p>However, be careful with Moq because in C#, if the original method is not virtual (contains the virtual keyword), Moq can't stub it out, so the original will be called. Moq fails if you specify a behavior on that method but if you don't, it calls the original instead of returning the default value.</p>
<p><strong>pyDoubles</strong> always returns <strong>None</strong> no matter the method signature.</p>
<p><span style="text-decoration: underline;">For case numer 2</span>, you define what the returned value should be. <a href="http://www.carlosble.com/2012/01/mockito-vs-moq/">Using "when" in Mockito and "Setup" in Moq</a>.</p>
<p><span style="text-decoration: underline;">For case numer 3</span>, you verify that a call was made:</p>
<ul>
<li>Mockito: <em>verify(double).method();</em></li>
<li>Moq: <em>double.Verify(x=&gt;x.method());</em></li>
<li>pyDoubles: <em>assert_that_method(double.method).was_called()</em></li>
<li>Jasmine: <em>expect(double.method).toHaveBeenCalled()</em></li>
</ul>
<p>You might want to know what parameters were passed in too. In this case you can use Matchers in Mockito, Moq and pyDoubles.</p>
<p><span style="text-decoration: underline;">Moq sample:</span></p>
<pre class="csharp">userRepository.<span style="color: #0000FF;">Verify</span><span style="color: #000000;">&#40;</span>x =&gt; x.<span style="color: #0000FF;">SaveNewUser</span><span style="color: #000000;">&#40;</span>
        It.<span style="color: #0000FF;">Is</span>&lt;Person&gt;<span style="color: #000000;">&#40;</span>
        p =&gt; p.<span style="color: #0000FF;">PersonalIdentificationCode</span> == <span style="color: #808080;">&quot;TEST_CODE&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>;
&nbsp;</pre>
<p><span style="text-decoration: underline;">pyDoubles sample:</span></p>
<pre class="python">assert_that_method<span style="color: black;">&#40;</span>double.<span style="color: black;">method</span>
         <span style="color: black;">&#41;</span>.<span style="color: black;">was_called</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">with_args</span><span style="color: black;">&#40;</span>obj_with_fields<span style="color: black;">&#40;</span><span style="color: black;">&#123;</span>
                            <span style="color: #483d8b;">'id'</span>: <span style="color: #ff4500;">20</span>,
                            <span style="color: #483d8b;">'test_field'</span>: <span style="color: #483d8b;">'OK'</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre>
<p>For Mockito samples I am waiting for my friend <a href="http://twitter.com/regiluze">@regiluze</a> to write a post on it <img src='http://www.carlosble.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  I will link it here when written.</p>
<p><span style="text-decoration: underline;">Jasmine sample:</span></p>
<pre class="javascript">spyOn<span style="color: #66cc66;">&#40;</span>double, <span style="color: #3366CC;">&quot;method&quot;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">andCallFake</span><span style="color: #66cc66;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#123;</span>
      expect<span style="color: #66cc66;">&#40;</span>arguments<span style="color: #66cc66;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #66cc66;">&#93;</span>.<span style="color: #000066;">name</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">toEqual</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">&quot;Carlos&quot;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>;</pre>
<h4>Test collaborations one to one:</h4>
<p>If the object under test has more than one collaborator, tests can be really hard to understand. I recommend expressing every collaboration in a single test:</p>
<ul>
<li>A talks to B (test 1)</li>
<li>A talks to C (test 2)</li>
</ul>
<ul>
<li>For test1, B will be a spy o mock (you use Verify at the end). Also for test1, you don't care about C, C is just a dummy. Calls to C don't need to be configured in the double, let the framework return the default value.</li>
</ul>
<ul>
<li>For test2, C is the spy or the mock, you verify interaction between A and C, and do't care about B. Calls to B don't need to be configured, let the framework return whatever.</li>
<li>For test1, if the value returned by C, is necessary for the collaboration between A and B, then Ok, specify the stub result for that call to C, and verify on B.</li>
</ul>
<h4>Group the tests by setup:</h4>
<p>Should I have a test class for every class in the production code? NO.<strong>  Tests must be grouped by their setup. </strong>This is, put those which have the same arrangement in the same test case (test class). If there are two or more interaction tests in a class, the creation of the SUT and the doubles, should not be in every test. It must be in the setup, along with the injection (doubles, are injected to the SUT as collaborator). So, if you find yourself injecting the test double to the SUT in more than one test, watch them again carefully.<strong><br />
</strong></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.carlosble.com/2012/01/cleaner-interaction-tests/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Apego a la herramienta</title>
		<link>http://www.carlosble.com/2012/01/apego-a-la-herramienta/</link>
		<comments>http://www.carlosble.com/2012/01/apego-a-la-herramienta/#comments</comments>
		<pubDate>Sun, 22 Jan 2012 21:43:28 +0000</pubDate>
		<dc:creator>Carlos Ble</dc:creator>
				<category><![CDATA[Software Development]]></category>

		<guid isPermaLink="false">http://www.carlosble.com/?p=1135</guid>
		<description><![CDATA[Cuandó programaba en Delphi arrastrando componentes gráficos para programar las aplicaciones de escritorio, me parecía tan potente y tan sencillo que no quería cambiar de herramienta (allá por 2001). Por motivos de trabajo tuve que saltar a Gnome, con Gtk (en un principio con C++ y Gtkmm) Me parecía un atraso volver a aprender nuevas [...]]]></description>
			<content:encoded><![CDATA[<p>Cuandó programaba en Delphi arrastrando componentes gráficos para programar las aplicaciones de escritorio, me parecía tan potente y tan sencillo que no quería cambiar de herramienta (allá por 2001). Por motivos de trabajo tuve que saltar a Gnome, con Gtk (en un principio con C++ y <a href="http://www.gtkmm.org">Gtkmm</a>) Me parecía un atraso volver a aprender nuevas herramentas para hacer cosas parecidas y se mi hizo dificil. Sin embargo, el cambio me trajo nuevos conocimientos, nuevas ideas para <strong>abrir la mente</strong>. En medio de todo estó también programé aplicaciones Java +<a href="http://en.wikipedia.org/wiki/Swing_%28Java%29"> Swing</a>, tanto cuando no había editores de GUI visuales como cuando los hubo. Pasé por <a href="http://www.mono-project.com/Main_Page">Mono</a> y Gtk#, luego a la web con <a href="http://www.castleproject.org/monorail/">Castle.MonoRail</a> y eso me llevó con el tiempo a MS .Net y <a href="http://en.wikipedia.org/wiki/Windows_Forms">Windows.Forms</a>.  Siempre por motivos de trabajo, un poco en contra de lo que me apetecía. Contínuamente a aprender y encima saltando a la plataforma propietaria de Microsoft, el "maligno" (yo que ?olo tenía Linux en mi maquina desde hacía años).<br />
Gracias a las herramientas de Microsoft pude aprender conceptos como el <a href="http://msdn.microsoft.com/en-us/library/ms752347.aspx#what_is_data_binding">Data Binding</a> que hoy en día <a href="http://martinfowler.com/eaaDev/PresentationModel.html">aplico en Javascript</a> y llegué a aprender y dominar los genéricos, que le dan mil vueltas a los de Java. Incluso <a href="http://desktoprails.osl.ull.es/doku.php">me hice un framework</a> para escritorio que me permitiese testear automaticamente mis aplicaciones.<br />
Después por motivos de trabajo, tuve que abandonar .Net y salté a Python + <a href="https://www.djangoproject.com/">Django</a>, para trabajar ya en la web. Nada que ver con lo anterior. Nada en absoluto. En todos estos años también he tenido que trabajar con Applets Java, con PlayFramework, con Weblogic, con Spring y en los últimos meses, muchísimo Javascript.</p>
<p>Cada cambio era una <strong>patada a mi ego</strong>, porque me sacaba de la zona de confort y me hacía sentir que perdía mi valía, la maestría de la herramienta que tanto me habia trabajado.</p>
<p>Y resulta que en lugar de perder, estaba ganando. Si no hubiese tenido que pasar obligado por todos estos cambios, no tendría la <strong>visión</strong> que tengo hoy en día sobre <strong>patrones, técnicas de programación, arquitecturas</strong> ... la tranquilidad de que me cuesta muy poco adaptarme a una nueva plataforma porque siempre contiene elementos de otras que ya conozco. Me da seguridad en mi mismo y me ha quitado por completo el apego a las herramientas. Programo en lo que sea y estoy deseando seguir aprendiendo lenguajes, frameworks.</p>
<p>Disfruto programando cualquier lenguaje y sé qué elementos me interesan usar de un framework y qué otras partes me puedo saltar. Solo porque he tenido que trabajar en muchos.</p>
<p>Ahora que estamos buscando gente para que se una a nuestro equipo, donde usamos mayormente .Net con C# y por otro lado Javascript, sé que mucha gente no tiene interes porque no quiere abandonar su stack tecnológico de siempre. Parece que programar .Net fuese lo peor del mundo, cuando es tan solo una copia de Java que lo mejora en muchos aspectos. Se van copiando el uno del otro. Además puedes usar <a href="http://en.wikipedia.org/wiki/F_Sharp_%28programming_language%29">F#</a>, IronPython, IronRuby, Boo, y <a href="http://ayende.com/blog">aprender de algunos</a> de los programadores más increibles del planeta.</p>
<p>Me parece muy bien que la gente tenga predilección por frameworks como, Django, <a href="http://www.symfony-project.org/">Symfony</a>, <a href="http://rubyonrails.org/">Rails</a> o <a href="http://grails.org/">Grails</a> pero la negativa a usar otra cosa, tal como yo lo veo, es una cuestión de apego  poco racional. En algunos casos, yo diría que inmadurez. Además, los proyectos no duran para siempre, son etapas, son transiciones como la vida misma.</p>
<p>Todos los que me habeis dicho personalmente (amigos mios) que nos veníais por el stack tecnológico, creo que aún teneis que seguir madurando profesionalmente.  Y yo tambien, por supuesto. Lo digo sin rencor ni enfado de ningun tipo.</p>
<p>Contínuamente me digo a mí mismo... <strong>no dejes que el ego frene tu aprendizaje</strong> <img src='http://www.carlosble.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.carlosble.com/2012/01/apego-a-la-herramienta/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Mockito Vs Moq</title>
		<link>http://www.carlosble.com/2012/01/mockito-vs-moq/</link>
		<comments>http://www.carlosble.com/2012/01/mockito-vs-moq/#comments</comments>
		<pubDate>Mon, 16 Jan 2012 18:27:29 +0000</pubDate>
		<dc:creator>Carlos Ble</dc:creator>
				<category><![CDATA[Test Driven Development]]></category>

		<guid isPermaLink="false">http://www.carlosble.com/?p=1128</guid>
		<description><![CDATA[Don't be confused, the title is just to get your attention. This is not a benchmark between Mockito and Moq. I need to  explain some differences to my teammates so that the transition between Mockito and Moq is softer for them. Typical way to stub out a method call with mockito: when(colaborator.method(argument1)).thenReturn(whateverIwant); Same with Moq: [...]]]></description>
			<content:encoded><![CDATA[<p>Don't be confused, the title is just to get your attention. This is not a benchmark between <a href="http://mockito.org">Mockito </a>and <a href="http://code.google.com/p/moq/">Moq</a>. I need to  explain some differences to my teammates so that the transition between Mockito and Moq is softer for them.</p>
<p>Typical way to stub out a method call with mockito:</p>
<p><strong><em>when(colaborator.method(argument1)).thenReturn(whateverIwant);</em></strong></p>
<p>Same with Moq:</p>
<p><strong><em>colaborator.Setup(x =&gt; x.method(argument1)).Returns(whateverIwant);</em></strong></p>
<p>Obviously, the mockito way is nicer. I believe this is because of Java capabilities but I am not sure. I would like to dig into mockito's source code to see how is this possible. I will do it and blog about it soon. I used to think that it was because of the kind ot<a href="http://en.wikipedia.org/wiki/Late_binding"> late binding</a> supported by Java, but I am not sure.</p>
<p>Moq uses a lambda expression (anonymous method inlined) to tell the framework which method and how is expected to be called). The reason I use "<em>x</em>" for the object in the anonymous method is because it refers to "<em>colaborator</em>" itself so there is no point in adding more names.</p>
<p>The other important difference relates to the<strong> "virtual" keyword in C#</strong>. Methods in C# are final by default. You can't override them unless they contain the keyword "virtual" on its signature. Both, Mockito and Moq create test doubles by subclassing on runtime, overriding methods and implementing the fake behavior on them (as far as I know). So, if the method you want to stub is not virtual, Moq will throw a runtime exception. If it is not virtual but you don't specify any fake behavior on it, it will not throw exceptions, but worse, <strong>it will call the actual implementation</strong>. So you might be hiting the database in your unit tests inadvertedly. What I do, is that all my methods are virtual by default (I write "virtual" on their signature).</p>
<p>There will be more posts on this topic <img src='http://www.carlosble.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.carlosble.com/2012/01/mockito-vs-moq/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>RS: Aprovechar la experiencia</title>
		<link>http://www.carlosble.com/2012/01/rs-aprovechar-la-experiencia/</link>
		<comments>http://www.carlosble.com/2012/01/rs-aprovechar-la-experiencia/#comments</comments>
		<pubDate>Sat, 14 Jan 2012 21:40:57 +0000</pubDate>
		<dc:creator>Carlos Ble</dc:creator>
				<category><![CDATA[Retrospectivas]]></category>

		<guid isPermaLink="false">http://www.carlosble.com/?p=1123</guid>
		<description><![CDATA[En el sprint de esta semana nos hemos dado cuenta de errores cometidos semanas atrás. Las acciones más importantes ahora para seguir mejorando, son: Que cuando reimplementemos una funcionalidad (o una similar a otra que ya tuviesemos), contemos con las personas que desarrollaron la primera versión. Lo ideal es que las personas que estuvieron en [...]]]></description>
			<content:encoded><![CDATA[<p>En el sprint de esta semana nos hemos dado cuenta de errores cometidos semanas atrás. Las acciones más importantes ahora para seguir mejorando, son:</p>
<ul>
<li>Que <strong>cuando reimplementemos</strong> una funcionalidad (o una similar a otra que ya tuviesemos), <strong>contemos con las personas que desarrollaron la primera versión</strong>. Lo ideal es que las personas que estuvieron en el primer desarrollo estén haciendo pareja con quienes se enfrentan al problema por primera vez. Si no es posible, al menos deben sentarse a hablar de las dificultades que surgieron con la primera implementación y las soluciones que se encontraron.<br />
Lo primero será tratar de evaluar si se puede <strong>reutilizar</strong> parte del código existente. No siempre es fácil tomar esta decisión pero por lo menos hacer un estudio rápido de la situación. En caso que se pueda reutilizar, estudiar qué se debe <strong>refactorizar</strong> y a qué se le pueden añadir <strong>tests</strong>. En caso que haya que reescribirlo todo por completo, tener presentes las <strong>ideas</strong> que ayudaron más al buen funcionamiento de la primera implementación. Esto es: aprovechar la experiencia que ya tenemos.</li>
<li><strong>Separar</strong> muy bien lo que es <strong>importante de lo que es urgente</strong>. Si todo es urgente, dejamos de saber lo que es importante. Nos ha pasado y nos ha perjudicado. Cuando digamos que algo es urgente, tendremos que saber que corremos peligro de dejar atrás lo imporante.</li>
<li>Tratar de evitar la entrada de <strong>imprevistos</strong> durante el sprint. Tiene que ver con lo anterior. Si surge una necesidad el jueves y no es bloqueante, debemos plantearnos esperar a abordarla el lunes, es decir, en el siguiente sprint. La idea es no romper la planificación semanal. Cuando la rompemos, nos distanciamos de los objetivos propuestos y entonces dejamos de ser predecibles. Ser predecibles es una de nuestras metas porque así sabremos cada vez mejor, cuánto podemos tardar en entregar funcionalidad con valor para el negocio.</li>
<li>Evitar hablar de "terminar tareas" y hablar más de poner en producción tareas que suman valor. <strong>No sirve querer terminar</strong>, sino querer desarrollar piezas que mejoran la <strong>experiencia del usuario</strong>. Cuando pensamos en terminar, es más fácil hacerlo mal (porque lo urgente quita de enmedio a lo importante). Rara es la semana que no se introducen nuevos requisitos en funcionalidad que estaba "terminada".</li>
</ul>
<p>Esta semana estoy muy contento con la labor técnica del equipo:</p>
<ul>
<li>Se ha respetado en todo momento que todos los tests pasen</li>
<li>Se han añadido tests para demostrar bugs</li>
<li>No recuerdo que se hayan escrito métodos nuevos de más de 10 líneas.</li>
<li>No se han introducido números mágicos ni código duplicado</li>
<li>Se ha prestado bastante atención a la code review y los commits han sido muy claros.</li>
</ul>
<p>Es importante vigilar bien que sigamos por el buen camino, porque estamos en un punto en que retroceder lo andado no es muy dificil.</p>
<p>Buen comienzo de semana a todos <img src='http://www.carlosble.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.carlosble.com/2012/01/rs-aprovechar-la-experiencia/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>RS: planificación de sprint</title>
		<link>http://www.carlosble.com/2012/01/rs-planificacion-de-sprint/</link>
		<comments>http://www.carlosble.com/2012/01/rs-planificacion-de-sprint/#comments</comments>
		<pubDate>Fri, 06 Jan 2012 15:29:19 +0000</pubDate>
		<dc:creator>Carlos Ble</dc:creator>
				<category><![CDATA[Retrospectivas]]></category>

		<guid isPermaLink="false">http://www.carlosble.com/?p=1118</guid>
		<description><![CDATA[Nuestros sprints son de una semana, empiezan el lunes y terminan el viernes. Planificamos en el daily standup meeting del lunes por la mañana. Pero el daily no queremos que pase de los 20 minutos (mejor seria no pasar de los 15). Asi que las últimas dos semanas, terminabamos el meeting sin haber cerrado la [...]]]></description>
			<content:encoded><![CDATA[<p>Nuestros sprints son de una semana, empiezan el lunes y terminan el viernes. Planificamos en el daily standup meeting del lunes por la mañana. Pero el daily no queremos que pase de los 20 minutos (mejor seria no pasar de los 15). Asi que las últimas dos semanas, terminabamos el meeting sin haber cerrado la planificacion semanal, sin tener las tareas estimadas y por tanto, sin conocer cuál era el objetivo a cumplir. Eso hace que al terminar la semana no sepamos si lo hemos hecho mejor o peor. Dejamos de ser predecibles cuando pasa esto.</p>
<p>Por este motivo, <strong>la reunion del lunes podrá estirarse hasta un máximo de una hora con tal de que todos podamos estimar y comprometernos a entregar determinada funcionalidad el viernes</strong>, o por lo menos a intentarlo.</p>
<p>Aunque nuestra hora de meeting son las 9.30am, el lunes desplazaremos la hora lo que haga falta para que estemos todos. Esta semana faltaron personas que al no estar en el meeting de planificación no pudieron aportar su conocimiento. Eso llevó a que <strong>yo escogiera como prioritaria una tarea que en realidad no lo era</strong>, porque ya teniamos una funcionalidad parecida, hecha en código existente pero no lo sabíamos. Era una funcionalidad que conocía la persona no estaba. La tarea que se ha implementado hacía falta pero no era tan prioritaria en el sprint de la semana que ha terminado.</p>
<p>Por otro lado existe preocupación porque no estamos colocando las clases en los <strong>namespaces más adecuados, ni los ficheros en las carpetas adecuadas</strong>. El problema es que si no están en un lugar intuitivo podemos repetir funcionalidad. Para esto la <strong>code review</strong> juega un papel importante, por lo que hay que seguir haciendo incapié en ella. A parte de eso, la persona que detecte que se ha puesto un fichero en el sitio incorrecto o un namespace que no corresponde, debe <strong>actuar de manera concreta</strong>, bien modificando el código o bien avisando por email a los compañeros, diciendo exáctamente por qué no es correcto y cómo solucionarlo.</p>
<p>En el código legado sigue habiendo horrores que nos están haciendo daño pero la preocupación por la ubicación de clases y ficheros es un tema recurrente así que vamos a intentarla solventar,<strong> tomando acciones concretas y constructivas</strong>.</p>
<p>Esta semana hemos <strong>resuelto graves problemas de concurrencia</strong> que teníamos. El trabajo ha sido duro porque hemos invertido mucho tiempo y escrito pocas líneas de código y eso da mala sensación, pero el resultado es muy bueno. Hemos aprendido bastante y sabemos qué cuestiones debemos considerar desde ya, para que nuestro código esté preparado para la concurrencia. Escribiré un post sobre nuestros descubrimientos con <a href="http://msdn.microsoft.com/en-us/library/bb425822.aspx">Linq2Sql</a> y concurrencia pronto.</p>
<p>En las últimas semanas hemos hecho muy poco <strong>pair programming</strong> porque buena parte del equipo pensaba que así avanzaríamos más teniendo la fecha de entrega muy cercana. La realidad es que no podemos cuantificar si ha salido adelante más trabajo o no, pero lo que sí hemos hecho es introducir <strong>deuda técnica</strong> y aumentar en desconocimiento de lo que los demás hacen, lo que lleva a la duplicidad del código. Falta comunicación. Sabemos que la próxima semana volvemos a nuestro ritmo habitual, intentando hacer las cosas lo mejor posible y sabiendo que cuando dos personas trabajan juntas y bien concentradas, nos acercamos más a ello.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.carlosble.com/2012/01/rs-planificacion-de-sprint/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

