<?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>La bitacora de laparca</title>
	<atom:link href="https://blog.laparca.es/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.laparca.es</link>
	<description>donde el conocimiento es nulo</description>
	<lastBuildDate>Mon, 13 Jan 2020 15:26:25 +0000</lastBuildDate>
	<language>es</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.4.2</generator>
	<item>
		<title>Curso de plantillas en C++: uso en funciones</title>
		<link>https://blog.laparca.es/2020/01/13/curso-de-plantillas-en-c-uso-en-funciones/</link>
					<comments>https://blog.laparca.es/2020/01/13/curso-de-plantillas-en-c-uso-en-funciones/#respond</comments>
		
		<dc:creator><![CDATA[laparca]]></dc:creator>
		<pubDate>Mon, 13 Jan 2020 15:26:25 +0000</pubDate>
				<category><![CDATA[Personal]]></category>
		<guid isPermaLink="false">https://blog.laparca.es/?p=899</guid>

					<description><![CDATA[Antes de continuar con las funciones quedó pendiente la sintaxis de las plantillas: Bueno, creo que está claro: se usa la palabra reservada template y entre brakets (los simbolitos &#8216;&#60;&#8216; y &#8216;>&#8216;) se pone la lista de cosas que queremos que se puedan hacer plantilla. Finalmente va la parte sobre la que vamos a aplicar &#8230; <a href="https://blog.laparca.es/2020/01/13/curso-de-plantillas-en-c-uso-en-funciones/" class="more-link">Seguir leyendo <span class="screen-reader-text">Curso de plantillas en C++: uso en funciones</span> <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<p>Antes de continuar con las funciones quedó pendiente la sintaxis de las plantillas:</p>



<pre class="wp-block-code"><code>template &lt; LISTA_DE_LA_PANTILLA > SOBRE_LO_QUE_APLICA_LA_PANTILLA</code></pre>



<p>Bueno, creo que está claro: se usa la palabra reservada <code><strong>template</strong></code> y entre <em>brakets</em> (los simbolitos &#8216;<code>&lt;</code>&#8216; y &#8216;<code>></code>&#8216;) se pone la lista de cosas que queremos que se puedan hacer plantilla. Finalmente va la parte sobre la que vamos a aplicar la plantilla, que puede ser una estructura o unión, una clase, una función, un renombrado de tipo con <strong><code>using</code></strong> (a partir del estándar de 2011) o una declaración de variable (a partir del estándar de 2014).</p>



<p>Y con esto se termina esta breve explicación. El resto lo iremos viendo con ejemplos.</p>



<h2 class="wp-block-heading">Ahora sí: Funciones</h2>



<p>En el momento en el que podemos tener tipos como plantillas surge el problema de poder usarlos en funciones. En este punto la lógica es sencilla, si tengo que pasar a una función un tipo que es una plantilla, la función también debe ser una plantilla.</p>



<pre class="wp-block-code"><code>template&lt;class T> struct mi_tipo {
   /* Da igual lo que vaya aquí para el ejemplo */
};

template&lt;class T>
void una_funcion(mi_tipo&lt;T> valor) {
   /* Esta funcion aceptará cualquier mi_tipo */
}</code></pre>



<p>De este modo, desde una_funcion tendríamos acceso a todas las funciones miembro y variables miembro de <code>mi_tipo</code>. A partir de aquí lo usaríamos de forma normal como cualquier otra variable.</p>



<p>Hay otra forma de crear la plantilla para que acepte cualquier cosa:</p>



<pre class="wp-block-code"><code>template&lt;class T>
void otra_funcion(T valor) {
   /* Esta funcion aceptara cualquier tipo, incluido mi_tipo */
}</code></pre>



<p>Con este código, <code>otra_funcion </code>acepta cualquier tipo de dato. Si intentamos acceder a alguna variable miembro o función miembro de valor el compilador dará error si no está implementada en el tipo <code>T</code>.</p>



<h2 class="wp-block-heading">Un ejemplo práctico</h2>



<p>Hasta ahora hemos visto un poco por encima cómo hacer plantillas sencillas, pero toca ver algo que tenga alguna utilidad. Por eso vamos hacer una clase que implemente un array que pueda devolver su tamaño con una función (como en java). </p>



<p>Actualmente ya existe una clase que hace eso en el estándar. Es <a href="https://en.cppreference.com/w/cpp/container/array">std::array</a>.</p>



<pre class="wp-block-code"><code>/* Este codigo es compatible C++03 */
#include &lt;iostream>
#include &lt;stdexcept>

template&lt;class Tipo, int Tam> class array {
   public:
      Tipo&amp; operator&#91;](int p) {
         if (p >= Tam) throw std::out_of_range(std::string("Te saliste del rango"));
         return valores_&#91;p];
      }
      int tam() const {
         return Tam;
      }
   private:
      Tipo valores_&#91;Tam];
};

int main() {
   array&lt;int, 5> valores;
   for (int i = 0; i &lt; valores.tam(); i++)
      valores&#91;i] = i*2;

   for (int i = 0; i &lt; valores.tam(); i++)
      std::cout &lt;&lt; valores&#91;i] &lt;&lt; std::endl;

   return 0;
}</code></pre>



<p>En las siguientes entregas profundizaremos más en lo que se puede hacer con las plantillas.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.laparca.es/2020/01/13/curso-de-plantillas-en-c-uso-en-funciones/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Curso de plantillas en C++: primeros pasos</title>
		<link>https://blog.laparca.es/2019/10/25/curso-de-plantillas-en-c-primeros-pasos/</link>
					<comments>https://blog.laparca.es/2019/10/25/curso-de-plantillas-en-c-primeros-pasos/#respond</comments>
		
		<dc:creator><![CDATA[laparca]]></dc:creator>
		<pubDate>Fri, 25 Oct 2019 20:56:10 +0000</pubDate>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[curso]]></category>
		<category><![CDATA[formacion]]></category>
		<category><![CDATA[introduccion]]></category>
		<category><![CDATA[software]]></category>
		<guid isPermaLink="false">https://blog.laparca.es/?p=895</guid>

					<description><![CDATA[En la entrada anterior introdujimos por encima las plantillas. Seguro que generó más dudas que otra cosa, así que vamos a empezar a ver chicha código. ¿Qué resuelven las plantillas? En lenguajes como C o Pascal implementamos algo tan básico como una lista enlazada tal que así: En el caso 1, el problema es que &#8230; <a href="https://blog.laparca.es/2019/10/25/curso-de-plantillas-en-c-primeros-pasos/" class="more-link">Seguir leyendo <span class="screen-reader-text">Curso de plantillas en C++: primeros pasos</span> <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<p>En la entrada anterior introdujimos por encima las plantillas. Seguro que generó más dudas que otra cosa, así que vamos a empezar a ver <s>chicha</s> código.</p>



<h2 class="wp-block-heading">¿Qué resuelven las plantillas?</h2>



<p>En lenguajes como C o Pascal implementamos algo tan básico como una lista enlazada tal que así:</p>



<pre class="wp-block-code"><code>/* Caso 1: Lista para un tipo concreto */
struct ListaPersona
{
   struct Lista* siguiente;
   /* El dato almacena un elemento de la lista puede ser un puntero (suele serlo */
   Persona dato;
};

/* Caso 2: Lista genérica para cualquier cosa */
struct Lista
{
   struct Lista* siguiente;
   void* dato;
};</code></pre>



<p>En el caso 1, el problema es que hay que hacer una implementación por cada tipo de dato que queramos. Esto es bastante esfuerzo y, sobre todo, mucho trabajo de mantenimiento en caso de problemas.</p>



<p>En el caso 2 podemos hacer cualquier cosa, lo que puede acarrear problemas. Estos problemas vendrían, principalmente, por no poder validar el tipo de los datos que almacenamos. Por ejemplo:</p>



<pre class="wp-block-code"><code>/* No hagáis esto en casa */
typedef void*(*crea_instancia_t)();
int i;
struct Lista* lista;
crea_instancia_t crea_instancia&#91;3] = { crea_persona, crea_pedido, crea_cualquier_cosa_guay };

for (i = 0; i &lt; 100; i++)
{
   lista = lista_agregar(lista, crea_instancia&#91;rand()%3]());
}
/* ¿Qué hay en cada entrada de la lista? */</code></pre>



<p>Vale, es muy cogido por los pelos, pero siempre puede pasarnos que nos despistemos al programar y metamos lo que no es. Y lo mejor, depura a ver qué ha pasado.</p>



<h2 class="wp-block-heading">¿Cómo resolvemos esto en C++?</h2>



<p>Esta sería la parte más sencillas de las plantillas de C++. En este caso, lo que podemos hacer es poner algo que identifique el tipo que queremos y se sustituya por el que queremos:</p>



<pre class="wp-block-code"><code>template&lt;typename T>
struct Lista
{
   Lista* siguiente;
   T dato;
};</code></pre>



<p>Ya está, ahora ya podemos aprovechar las ventajas del sistema de tipos para garantizar que metemos en la lista los tipos adecuados.</p>



<p>Ojo, a efectos prácticos es lo mismo que hacer una versión para cada tipo que le indiquemos a la lista. El compilador genera una versión para cada tipo.</p>



<p>En la próxima entrada empezaremos a ver cómo se integran los tipos de plantillas para pasarlos a funciones.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.laparca.es/2019/10/25/curso-de-plantillas-en-c-primeros-pasos/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Curso de plantillas en C++: qué son las plantillas y para qué sirven</title>
		<link>https://blog.laparca.es/2019/10/17/curso-de-plantillas-en-c-que-son-las-plantillas-y-para-que-sirven/</link>
					<comments>https://blog.laparca.es/2019/10/17/curso-de-plantillas-en-c-que-son-las-plantillas-y-para-que-sirven/#respond</comments>
		
		<dc:creator><![CDATA[laparca]]></dc:creator>
		<pubDate>Thu, 17 Oct 2019 08:09:12 +0000</pubDate>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[metaprogramacion]]></category>
		<category><![CDATA[plantillas]]></category>
		<category><![CDATA[templates]]></category>
		<guid isPermaLink="false">https://blog.laparca.es/?p=855</guid>

					<description><![CDATA[Las plantillas en C++ son un mecanismo que nos pertite crear tipos y funciones dependientes de otros tipos y valores no definidos. El mejor modo de entenderlo es pensando en un formulario, por ejemplo, el típico formulario de una administración pública, donde hay un montón de texto y huecos que rellenar. Cada hueco recibe un &#8230; <a href="https://blog.laparca.es/2019/10/17/curso-de-plantillas-en-c-que-son-las-plantillas-y-para-que-sirven/" class="more-link">Seguir leyendo <span class="screen-reader-text">Curso de plantillas en C++: qué son las plantillas y para qué sirven</span> <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<p>Las plantillas en C++ son un mecanismo que nos pertite crear tipos y funciones dependientes de otros tipos y valores no definidos. El mejor modo de entenderlo es pensando en un formulario, por ejemplo, el típico formulario de una administración pública, donde hay un montón de texto y huecos que rellenar. Cada hueco recibe un valor. La plantilla es parecido, es definir un tipo o función donde dejamos <em>huecos</em> para ser rellenados más tarde.</p>



<p>Según wikipedia:</p>


<blockquote>
<p><b>Templates</b> are a feature of the C++ programming language that allows functions and classes to operate with generic types. This allows a function or class to work on many different data types without being rewritten for each one.</p>
<p style="text-align: right;">Fuente: <a href="https://en.wikipedia.org/wiki/Template_%28C%2B%2B%29">Wikipedia</a></p>
</blockquote>


<p>La utilidad principal de las plantillas es poder crear código genérico. Un caso típico son los contenedores (listas, arrays, mapas, etc.). Sabemos que en C hay dos formas de desarrollar listas:</p>



<ol><li>Almacenando la información con un puntero tipo <code>void*</code> o</li><li>Haciendo una implementación nueva para cada tipo que necesitemos.</li></ol>



<p>El primer modo tiene la ventaja de poder contener cualquier cosa, pero a cambio, no hay control de tipos. Esto podría implicar problemas a largo plazo si no se programa con cuidado.</p>



<p>El segundo mecanismo tiene la ventaja del control de tipado, pero incrementa de forma lineal el tiempo de desarrollo y mantenimiento. Si tenemos un problema en una función y está implentada para 10 tipos, habría que cambiarla 10 veces&#8230;</p>



<p>Otra de las cosas que nos ofrecen las plantillas es la capacidad de metaprogramar y realizar acciones en tiempo de compilación.</p>



<p>En las prómimas entradas vamos a ir viendo en detalle ejemplos de plantillas en C++03 y, finalmente, veremos qué cambios se han ido introduciendo las versiones modernas.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.laparca.es/2019/10/17/curso-de-plantillas-en-c-que-son-las-plantillas-y-para-que-sirven/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>El desarrollador como impedimento de Scrum</title>
		<link>https://blog.laparca.es/2018/07/30/el-desarrollador-como-impedimento-de-scrum/</link>
					<comments>https://blog.laparca.es/2018/07/30/el-desarrollador-como-impedimento-de-scrum/#respond</comments>
		
		<dc:creator><![CDATA[laparca]]></dc:creator>
		<pubDate>Mon, 30 Jul 2018 04:00:42 +0000</pubDate>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[Scrum]]></category>
		<guid isPermaLink="false">https://blog.laparca.es/?p=843</guid>

					<description><![CDATA[No hace mucho tiempo que hemos empezado a utilizar Scrum como framework para los desarrollos que hacemos en el trabajo. En este corto periodo de tiempo he visto mucha información sobre los problemas en las grandes empresas en la adopción de Scrum (renombrado de roles, «flexibilización» de Scrum, etc.). No voy a entrar en detalles &#8230; <a href="https://blog.laparca.es/2018/07/30/el-desarrollador-como-impedimento-de-scrum/" class="more-link">Seguir leyendo <span class="screen-reader-text">El desarrollador como impedimento de Scrum</span> <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<p>No hace mucho tiempo que hemos empezado a utilizar Scrum como <em>framework</em> para los desarrollos que hacemos en el trabajo. En este corto periodo de tiempo he visto mucha información sobre los problemas en las grandes empresas en la adopción de Scrum (renombrado de roles, «flexibilización» de Scrum, etc.). No voy a entrar en detalles en esto porque ya hay mucho.</p>
<p>Un problema que he visto es que no sólo la empresa puede ser un obstáculo para la adopción de Scrum (y cualquier sistema ágil), sino que los propios desarrolladores pueden ser un obstáculo.</p>
<p>En las metodologías clásicas, lo desarrolladores suelen ser tratados como meros obreros que ponen ladrillos.  Concretamente, los desarrolladores suelen recibir instrucciones muy precisas de lo que deben hacer, sin posibilidad de intervención de ningún tipo. Con las metodologías ágiles, esto cambia y los programadores pasan a formar parte del proceso creativo. Este cambio de paradigma puede hacer que mucho programadores (especialmente lo que lleven más tiempo) se sientan incómodos ya que ahora tienen que hacer más funciones. Éstos desarrolladores, si no quieren adaptarse, pueden convertirse en un impedimento importante en la estrategia de paso a un modelo ágil.</p>
<p>Y tú, ¿has tenido algún problema similar?</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.laparca.es/2018/07/30/el-desarrollador-como-impedimento-de-scrum/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Como hacer que tu código sea legible</title>
		<link>https://blog.laparca.es/2017/01/31/como-hacer-que-tu-codigo-sea-legible/</link>
					<comments>https://blog.laparca.es/2017/01/31/como-hacer-que-tu-codigo-sea-legible/#comments</comments>
		
		<dc:creator><![CDATA[laparca]]></dc:creator>
		<pubDate>Tue, 31 Jan 2017 08:59:26 +0000</pubDate>
				<category><![CDATA[Desarrollo]]></category>
		<category><![CDATA[Personal]]></category>
		<category><![CDATA[clean code]]></category>
		<category><![CDATA[codigo limpio]]></category>
		<category><![CDATA[consejo]]></category>
		<category><![CDATA[consejos]]></category>
		<category><![CDATA[legibilidad]]></category>
		<category><![CDATA[legible]]></category>
		<category><![CDATA[readable]]></category>
		<guid isPermaLink="false">https://blog.laparca.es/?p=775</guid>

					<description><![CDATA[Reconozco que no soy el mejor programador del mundo, pero intento mejorar cada día. Puede sonar tonto, pero una de las mayores complicaciones del trabajo de un programador es conseguir que el código que escribes un día sea entendible por otras personas !y nosotros mismos! en el futuro. Casi todo lo que voy a contar &#8230; <a href="https://blog.laparca.es/2017/01/31/como-hacer-que-tu-codigo-sea-legible/" class="more-link">Seguir leyendo <span class="screen-reader-text">Como hacer que tu código sea legible</span> <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<p>Reconozco que no soy el mejor programador del mundo, pero intento mejorar cada día. Puede sonar tonto, pero una de las mayores complicaciones del trabajo de un programador es conseguir que el código que escribes un día sea entendible por otras personas !y nosotros mismos! en el futuro.</p>
<p>Casi todo lo que voy a contar a continuación lo he aprendido a partir de diversas lecturas y por propia experiencia.</p>
<p>Algunos de los consejos más útiles que creo que son importantes tener en cuenta son:</p>
<h2>Utiliza el inglés al programar</h2>
<p>Puede resultar extraño para algunos que dominando un idioma (español, portugués, francés, etc.) tengan que programar en inglés. El motivo es sencillo, la mayor parte de la documentación en nuestro sector está en inglés por lo que acabamos mezclando idiomas. ¿A quién no le ha pasado tener funciones llamadas <em>setPeso</em> o <em>getNombre</em>?</p>
<p>Por otra parte, el inglés permite abrirnos puertas en dos sentidos:</p>
<ul>
<li>Para empezar como programadores que dominemos el inglés podremos acceder a más puestos de trabajo. La globalización no es sólo para las empresas; nosotros también podemos aprovecharnos de ella.</li>
<li>Podemos contratar programadores extranjeros que no tendrán problemas al leer el código.</li>
</ul>
<h2>Utiliza normas de codificación</h2>
<p>Esto en algunas metodologías se llama <a href="https://es.wikipedia.org/wiki/Gesti%C3%B3n_de_configuraci%C3%B3n_de_software" target="_blank">gestión de configuración del software</a>. También se puede encontrar como convención de codificación (<em>code convention</em>) o guías de estilo. La idea es tener una serie de normas que indica cómo debe ser la nomenclatura de codificación y tabulación para que todo el desarrollo sea consistente. Con esto conseguimos un programa más homogéneo y fácil de entender.</p>
<p>Tampoco es necesario inventarse una propia porque ya existen muchas. A modo de ejemplo:</p>
<ul>
<li><a href="http://www.oracle.com/technetwork/java/codeconvtoc-136057.html" target="_blank">Convención de codificación de Java de Oracle</a>.</li>
<li><a href="https://google.github.io/styleguide/javaguide.html" target="_blank">Guía de estilo de Java de Google</a>.</li>
<li><a href="https://google.github.io/styleguide/cppguide.html" target="_blank">Guía de estilo de C++ de Google</a>.</li>
<li><a href="https://www.python.org/dev/peps/pep-0008/" target="_blank">Guía de estilo de Python de python.org</a>.</li>
</ul>
<h2>Elige bien los nombre</h2>
<p>La verdad es que el tema de los nombres es uno de los más complejos. Sobre todo para funciones y clases. Por norma los nombres de métodos, funciones, clases, etc. deben ser descriptivos y breves. Por ejemplo, un nombre como <em>ApplicationModelAbstractObjectFactory</em> quizá sea un poco largo, pero parece descriptivo. Igualmente, algo como <em>EntraSola</em> (caso real) es muy breve, pero no dice nada; no es posible determinar realmente su funcionalidad (además, puede inducir a tener pensamientos impuros).</p>
<h2>Utiliza comentarios</h2>
<p>Este punto es bastante controvertido porque mucho programadores piensan eso de «el código bien escrito se entiende solo». Y es verdad. El problema es cuando el código no hace lo que toca.</p>
<p>No hay que llenar el código de comentarios, deben ser lo mínimo posible y sólo para cosas que claramente lo necesiten. Esto suele ser para aquellas construcciones que sean muy abstractas y que cueste mas comprender.</p>
<h2>Se organizado</h2>
<p>Otro punto que quizá no sea obvio, pero es cierto que tener bien organizado el código ayuda mucho a su legibilidad. Es más fácil entender una función que está dividida en partes (preparación de datos, realización de acciones, generación de resultado) que otra en la que se vayan mezclando todas estas tareas.</p>
<h2>Refactoriza</h2>
<p>Por mucho que nos esforcemos en que nuestro código sea claro y legible, con el tiempo acabará por convertirse todo en algo caótico. Es normal, porque conforme evoluciona un software se añaden nuevas funcionalidades para las que no estaba inicialmente pensado.</p>
<p>Para evitar esto hay que hacer ciclos de refactorización que mantengan el código limpio y optimizado.</p>
<h2>Conclusiones</h2>
<p>Está claro que <del>una parte importante para evitar la deuda técnica reside en la calidad del código</del> un código más claro facilita el mantenimiento al poder ser entendido fácilmente (ojo, que a parte de esto es necesario un buen diseño del mismo). El uso de unas normas que permitan que éste sea entendible ayudan mucho para evitar este problema.</p>
<p>Finalmente me gustaría comentar que este artículo es meramente introductorio y faltan muchas cosas que contar. Estoy más que seguro que habrá discrepancias con algunas cosas; si es así, te animo a que dejes un comentario.</p>
<h2>Bibliografía</h2>
<p>La mayor parte de lo que he expuesto aquí procede del libro <a href="http://shop.oreilly.com/product/9780596802301.do" target="_blank">The Art of Readable Code </a>de O&#8217;Relly.</p>
<h2>Errata</h2>
<ul>
<li>2017-02-01: Corrijo la parte de la deuda técnica a sugerencia de Fioddor.</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.laparca.es/2017/01/31/como-hacer-que-tu-codigo-sea-legible/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Perezosidad</title>
		<link>https://blog.laparca.es/2016/05/11/perezosidad/</link>
					<comments>https://blog.laparca.es/2016/05/11/perezosidad/#respond</comments>
		
		<dc:creator><![CDATA[laparca]]></dc:creator>
		<pubDate>Wed, 11 May 2016 14:50:21 +0000</pubDate>
				<category><![CDATA[Personal]]></category>
		<guid isPermaLink="false">https://blog.laparca.es/?p=752</guid>

					<description><![CDATA[Algo que me ha sorprendido mucho de haskell y, que aún me cuesta mucho lidiar con ello, es el hecho de que sea perezoso. ¿Y eso qué significa? Significa que no va a ejecutar las cosas sin más, sino que se esperará hasta que no le quede más remedio. Por ejemplo, si tenemos algo como &#8230; <a href="https://blog.laparca.es/2016/05/11/perezosidad/" class="more-link">Seguir leyendo <span class="screen-reader-text">Perezosidad</span> <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<p>Algo que me ha sorprendido mucho de haskell y, que aún me cuesta mucho lidiar con ello, es el hecho de que sea perezoso.</p>
<p><strong>¿Y eso qué significa?</strong></p>
<p>Significa que no va a ejecutar las cosas sin más, sino que se esperará hasta que no le quede más remedio.</p>
<p>Por ejemplo, si tenemos algo como esto:</p>
<p><script src="https://gist.github.com/laparca/ebc3bdbfecf9e221cb663283cd18ae22.js?file=haskell.hs"></script></p>
<p>Como se puede ver, se «crea» una lista de infinitos elementos que empiezan en 1 (<em>intinite_list</em>). Como no accedemos a ningún elemento, el compilador en realidad no crea nada en memoria.</p>
<p>Luego indicamos que queremos elevar todos los elementos al cuadra para después quedarnos con aquellos que no son múltiplos de dos ni de tres. Eso lo almacenamos en <em>values</em>. En haskell esto significa que <em>values</em> representa esa operación, no que contenga dichos valores, así que aquí tampoco ha hecho nada: no ha elevado los infinitos elementos al cuadrado ni ha filtrado después.</p>
<p>Lo último que hacemos es un <em>take 10</em>. En este momento (si utilizamos <em>ghci</em>), en este momento intenta mostrar los 10 primeros elementos, lo que fuerza a hacer todo lo anterior. ¡Pero sólo lo hace sobre los 10 primeros! Ni elevamos la lista entera al cuadro, ni comprobamos los infinitos elementos. Sólo vamos a hacer esto las veces justas.</p>
<p>Esto lo hace todo el compilador por su cuenta.</p>
<p><strong>¿A dónde quieres ir a parar?</strong></p>
<p>Pues estaba hace poco mirando documentación de <a href="https://www.rust-lang.org/" target="_blank">Rust</a> y me he encontrado con algo muy parecido:</p>
<p><script src="https://gist.github.com/laparca/ebc3bdbfecf9e221cb663283cd18ae22.js?file=rust.rs"></script></p>
<p>Básicamente hace lo miso y me sorprendió mucho porque Rust no es un lenguaje que haga evaluación perezosa.</p>
<p><strong>¿Entonces cómo lo hace?</strong></p>
<p>Pues simulando la evaluación perezosa. Para ello lo que hace es jugar con <a href="https://doc.rust-lang.org/book/iterators.html" target="_blank">iteradores</a> personalizados. Cada iterador tiene información de qué es lo que va a hacer cuando se llame a su función <em>next</em>. Así que cuando llamamos a <em>map</em> lo que hace es crear en memoria la información necesaria para hacer la operación, pero no la ejecuta. Lo mismo sucede con los filtros. Cuando llamamos al <em>next</em> de iterador resultante, este ejecuta el <em>next</em> del iterador que contiene y luego comprueba o ejecuta la condición que tenga definida.</p>
<p><strong>Conclusión</strong></p>
<p>Sinceramente me ha encantado ver esta aproximación. Es una modo fantástico de lidiar con el problema de infinito de un modo sencillo. Esto permite tratar muchas cosas como iteradores que, aún dando listas potencialmente infinitas, no tengan un gran impacto en rendimiento (o sí, todo dependen de como esté diseñado).</p>
<p>Si quieres saber más sobre evaluación perezosa quizá te interese ver <a href="https://en.wikipedia.org/wiki/Lazy_evaluation" target="_blank">la entrada en Wikipedia</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.laparca.es/2016/05/11/perezosidad/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Aprendiendo haskell</title>
		<link>https://blog.laparca.es/2015/10/23/aprendiendo-haskell/</link>
					<comments>https://blog.laparca.es/2015/10/23/aprendiendo-haskell/#respond</comments>
		
		<dc:creator><![CDATA[laparca]]></dc:creator>
		<pubDate>Fri, 23 Oct 2015 11:10:26 +0000</pubDate>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[Desarrollo]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[programacion]]></category>
		<guid isPermaLink="false">https://blog.laparca.es/?p=739</guid>

					<description><![CDATA[Ya hace unos meses que, con tiempo que dispongo, estoy aprendiendo haskell. El motivo principal es que quería empezar con un lenguaje que fuera completamente distinto a los que ya conozco. Confieso que de momento me parece todo un galimatías. Si bien llego a resolver algunos problemas sencillos, aún me pierdo con cosas medianamente complejas. &#8230; <a href="https://blog.laparca.es/2015/10/23/aprendiendo-haskell/" class="more-link">Seguir leyendo <span class="screen-reader-text">Aprendiendo haskell</span> <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<p>Ya hace unos meses que, con tiempo que dispongo, estoy aprendiendo <a href="https://www.haskell.org/" target="_blank">haskell</a>. El motivo principal es que quería empezar con un lenguaje que fuera completamente distinto a los que ya conozco.</p>
<p>Confieso que de momento me parece todo un galimatías. Si bien llego a resolver algunos problemas sencillos, aún me pierdo con cosas medianamente complejas.</p>
<p>Además, para ir aprendiendo e ir estrujándome los sesos utilizo <a href="http://www.codewars.com/" target="_blank">codewars</a> para ir resolviendo ejercicios. Creo que es un buen modo para ir tomando contacto con el lenguaje.</p>
<h2>¿Qué me aporta haskell?</h2>
<p>La verdad es que no lo estoy estudiando porque sí. El objetivo es poder aprender nuevos mecanismos para afrontar los problemas. Haskell te obliga a afrontarlos desde una perspectiva completamente diferente a lo que es habitual en los lenguajes imperativos. Con ello espero que a futuro pueda incorporar nuevas formas para resolver problemas a mi día a día (siempre que valgan la pena).</p>
<h2>¿Por qué haskell?</h2>
<p>Porque al ser un lenguaje funcional puro me obliga a desconectar totalmente de lo que ya sé. Hay otros lenguajes funcionales, pero no llegan a la pureza de haskell¹ lo que me podría permitir desviarme de la intención de aprender programación funcional.</p>
<h2>¿Qué haré con él?</h2>
<p>Cuando tenga más claro como funciona y no me pierda tanto me pondré con <a href="http://www.yesodweb.com/" target="_blank">yesod</a>, un <em>framework</em> para desarrollo web. Creo que será toda una experiencia.</p>
<h2>¿Y después?</h2>
<p>Una vez que ya tenga haskell dominado espero poder ponerme con <a href="https://www.rust-lang.org/" target="_blank">Rust</a>. La verdad es que de un tiempo a esta parte ando muy desencantado con C. Cada día me parece peor lenguaje de programación, pero eso ya será otro artículo.</p>
<h2>Notas</h2>
<ol>
<li>Probablemente haya más lenguajes funcionales puros, pero haskell es de los que tiene la comunidad más amplia y, por tanto, en la que es más fácil encontrar documentación.</li>
</ol>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.laparca.es/2015/10/23/aprendiendo-haskell/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>La necesidad de invertir en herramientas</title>
		<link>https://blog.laparca.es/2015/10/22/la-necesidad-de-invertir-en-herramientas/</link>
					<comments>https://blog.laparca.es/2015/10/22/la-necesidad-de-invertir-en-herramientas/#respond</comments>
		
		<dc:creator><![CDATA[laparca]]></dc:creator>
		<pubDate>Thu, 22 Oct 2015 11:20:07 +0000</pubDate>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[Desarrollo]]></category>
		<category><![CDATA[herramientas]]></category>
		<category><![CDATA[inversion]]></category>
		<guid isPermaLink="false">https://blog.laparca.es/?p=729</guid>

					<description><![CDATA[Supongo que de una vez os habrá  pasado que ante ciertas tareas (tanto de desarrollo como de administración) repetís una y otra vez las mismas acciones o el mismo código. Otras veces, simplemente os encontráis que hay cosas que son fáciles de automatizar, pero no se hace (por ejemplo, rellenar cierto tipo de fichero en &#8230; <a href="https://blog.laparca.es/2015/10/22/la-necesidad-de-invertir-en-herramientas/" class="more-link">Seguir leyendo <span class="screen-reader-text">La necesidad de invertir en herramientas</span> <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<p>Supongo que de una vez os habrá  pasado que ante ciertas tareas (tanto de desarrollo como de administración) repetís una y otra vez las mismas acciones o el mismo código. Otras veces, simplemente os encontráis que hay cosas que son fáciles de automatizar, pero no se hace (por ejemplo, rellenar cierto tipo de fichero en donde hay patrones muy comunes).</p>
<p>En este punto surge un gran problema: no se quiere automatizar/desarrollar herramientas que faciliten dicha tarea. Sí, suena extraño y contraintuitivo, pero es así. Las razones pueden ser muchas:</p>
<ul>
<li>Sería otra herramienta a mantener y no hay recursos para ello.</li>
<li>Si el que hace la herramienta se va quién lo va a mantener.</li>
<li>Todo trabajo que no sea directamente la tarea asignada es tirar el dinero.</li>
<li>No lo hacemos porque no nos lo van a agradecer (sí, no siempre es cosa de la empresa no hacerlo).</li>
</ul>
<p>Seguro que hay más motivos, pero los anteriores los he oído más de una vez.</p>
<p>Es muy importante tener en cuenta que todo el tiempo que se utilice en automatizar (o simplificar) este tipo de tareas debe ser considerado inversión. Y es así porque se pueden llegar a ahorrar muchas horas de trabajo (pude hablarse, en algunos casos, de hasta cientos de horas anuales) y, por tanto, el retorno de la inversión será muy importante.</p>
<p>Como siempre, hay que ir con cuidado: para una tarea que se hace para un proyecto concreto que sabemos que no durará más de X tiempo puede que no compense la automatización. Por tanto hay que estudiar cada caso. Pero lo que está claro es que es necesario tener esto en cuenta.</p>
<p>En mi caso concreto, que estoy en desarrollo, veo como poco a poco se mejora el proceso de creación de software. Por una parte podemos escribir código menos propenso a errores, y, por otra parte, tenemos más tiempo para realizar las pruebas y ofrecer un mejor producto.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.laparca.es/2015/10/22/la-necesidad-de-invertir-en-herramientas/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Control de errores</title>
		<link>https://blog.laparca.es/2015/02/26/control-de-errores/</link>
					<comments>https://blog.laparca.es/2015/02/26/control-de-errores/#respond</comments>
		
		<dc:creator><![CDATA[laparca]]></dc:creator>
		<pubDate>Thu, 26 Feb 2015 10:11:45 +0000</pubDate>
				<category><![CDATA[Desarrollo]]></category>
		<category><![CDATA[control]]></category>
		<category><![CDATA[control errores]]></category>
		<category><![CDATA[develop]]></category>
		<category><![CDATA[error]]></category>
		<category><![CDATA[error control]]></category>
		<category><![CDATA[errores]]></category>
		<category><![CDATA[programacion]]></category>
		<guid isPermaLink="false">https://blog.laparca.es/?p=688</guid>

					<description><![CDATA[Uno de los grandes problemas al programar es realizar el control de los errores. Por diversos motivos me ha tocado hacer un trabajo de estudio sobre qué opciones tenemos para realizar el control de los errores de una aplicación. La verdad es que hubiese estado muy bien hacer una tormenta de ideas al respecto, pero &#8230; <a href="https://blog.laparca.es/2015/02/26/control-de-errores/" class="more-link">Seguir leyendo <span class="screen-reader-text">Control de errores</span> <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<p>Uno de los grandes problemas al programar es realizar el control de los errores. Por diversos motivos me ha tocado hacer un trabajo de estudio sobre qué opciones tenemos para realizar el control de los errores de una aplicación.</p>
<p>La verdad es que hubiese estado muy bien hacer una tormenta de ideas al respecto, pero en estos momentos estamos todos demasiado atareados.</p>
<p>El siguiente texto, sin pretender ser una guía exhaustiva de lo que es el control de errores, sí busca poner un punto de partida para todo aquel que quiera ver qué mecanismos hay para este fin.</p>
<p><span id="more-688"></span></p>
<h2>Control de errores desde el lenguaje</h2>
<p>Cuando empezamos a controlar errores lo único que tenemos son las propias herramientas del lenguaje. En lenguajes con C o Pascal tenemos <em>if</em>. Sí, esta sentencia de programación sirve para controlar errores. El <em>if</em> es una herramienta muy potente ya que puede ser utilizada con el retorno de las funciones, con variables o con expresiones. En el estándar POSIX es habitual que las funciones devuelvan valores negativos (normalmente un -1) en caso de error.</p>
<p><script src="https://gist.github.com/12b5a6220134041bbef7.js?file=if.c"></script></p>
<p>En algunos casos, en lugar de <em>if</em> se puede utilizar <em>switch/case/match</em> (depende del lenguaje). Es igual que concatenar sentencias<em> if-else</em> y permite hacer un tratamiento de error concreto a partir del retorno de la función:</p>
<p><script src="https://gist.github.com/12b5a6220134041bbef7.js?file=match.rs"></script></p>
<p>Muchos lenguajes orientados a objetos incorporan esquemas <em>try-catch</em> (o parecidos). Es parecido al <em>if</em>, pero permite separar el tratamiento de errores del código normal.</p>
<p><script src="https://gist.github.com/12b5a6220134041bbef7.js?file=try.cpp"></script></p>
<p>No tengo ninguna duda de que habrá lenguajes que dispongan de más tipos de tratamiento de error, pero también esto seguro que lo anterior abarca el 99% de lo que los lenguajes ofrecen para ese fin.</p>
<p>Por otra parte, algunos fabricantes pueden ofrecer extensiones al lenguaje. Por ejemplo, la versión de C de Microsoft soporta <em>try-catch</em> (aunque de forma algo fea).</p>
<p>Algunos lenguajes se aprovechan de la flexibilidad que ofrecen sus tipos para realizar un control de errores consistente. En concreto <a title="Lenguaje Haskell" href="https://www.haskell.org/" target="_blank">haskell</a> ofrece un tratamiento de errores usando <a title="mónada" href="http://www.lcc.uma.es/~blas/pfHaskell/gentle/monads.html" target="_blank">mónadas</a> como <a title="Uso de mónada Either" href="https://www.fpcomplete.com/school/starting-with-haskell/basics-of-haskell/10_Error_Handling" target="_blank">Either</a>. Este control de errores ha sido posteriormente utilizado en otros lenguajes como <a title="Lenguaje de programación Rust" href="http://rust-lang.org/" target="_blank">Rust</a>. Incluso Java 8 ofrece un tipo <a title="Optional en Java" href="http://docs.oracle.com/javase/8/docs/api/java/util/Optional.html" target="_blank">Optional&lt;T&gt;</a> que permite trabajar de forma parecida. En el caso de Rust, que es el que conozco algo más, se hace uso de <em>Option</em>, <em>Result</em> y algunos tipos más concretos dependiendo del caso (se puede ver más en le <a title="Manual de Rust" href="http://doc.rust-lang.org/book/" target="_blank">manual</a> en el <a title="Manejo de errores en Rust" href="http://doc.rust-lang.org/book/error-handling.html" target="_blank">capítulo de manejo de errores</a>). Podemos ver como se van concatenando las acciones ante un resultado:</p>
<p><script src="https://gist.github.com/12b5a6220134041bbef7.js?file=option.rs"></script></p>
<p>En la documentación de la API de Rust se puede ver <a title="Operaciones que pueden ser usadas con Option" href="http://doc.rust-lang.org/std/option/enum.Option.html" target="_blank">todas las operaciones que acepta Option</a>.</p>
<h2>Control de errores desde el sistema operativo</h2>
<p>Un mecanismo habitual en entornos Unix/Linux para indicar a una aplicación que algo ha pasado son las señales. La señal es un sistema que permite interrumpir el funcionamiento habitual de la aplicación a causa de alguna circunstancia. Estas pueden ser debidas a eventos normales (se ha muerto un proceso hijo, se ha pulsado CTRL+C, etc.) o a errores (se ha producido un fallo de acceso a memoria, se ha tratado de ejecutar una instrucción errónea, etc.):</p>
<p><script src="https://gist.github.com/12b5a6220134041bbef7.js?file=signal.c"></script></p>
<p><a title="Manejo de señales en MS Windows" href="https://msdn.microsoft.com/en-us/library/xdkz3x12.aspx" target="_blank">Las señales están parcialmente soportadas por los sistemas operativos MS Windows</a>.</p>
<p>En el caso de los sistemas operativos MS Windows, se hace uso de <a title="Excepciones en MS Windows" href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms680657%28v=vs.85%29.aspx" target="_blank">excepciones</a> (y por eso las extensiones de C para soportarlas en MS C):</p>
<p><script src="https://gist.github.com/12b5a6220134041bbef7.js?file=windows_exception.c"></script></p>
<h2>Control de errores desde API estándar</h2>
<p>En la API POSIX de C existe unas funciones que permite realizar recuperación de errores. Estas funciones son <a title="setjmp" href="http://es.wikipedia.org/wiki/Setjmp.h" target="_blank"><em>setjmp</em> y <em>longjmp</em></a>.</p>
<p><em>setjmp</em> permite guardar el estado de la aplicación en un punto (registros y pila) para que en caso de error volver a ese punto. <em>longjmp</em> permite volver al estado salvado por <em>setjmp</em> pasando un valor informativo.</p>
<p><script src="https://gist.github.com/12b5a6220134041bbef7.js?file=setjmp.c"></script></p>
<p>Estas funciones nos pueden permitir simular en C las excepciones de C++. En cualquier caso, estas funciones son complicadas de comprender y pueden ocasionar que se produzcan errores lógicos por dicho motivo.</p>
<p>Siento no poner ejemplos en otros lenguajes, pero C y C++ son los que en estos momentos domino más.</p>
<h2>Tipos de errores</h2>
<p>Existen distintos tipos de errores. No desde el punto de vista de si es error de disco, error de operación, etc. Sino desde el punto de vista de cómo estos pueden afectar a nuestra aplicación.</p>
<p>En este punto podemos identificar varios casos claros:</p>
<h3>Errores que podemos ignorar porque no tienen efecto sobre el funcionamiento de la aplicación.</h3>
<p>Este es el caso más sencillo de todos. Se produce un error, pero lo ignoramos.</p>
<p>Aunque rara vez deben ser ignorados los errores, es curioso cómo se abusa de esto en Java (especialmente durante la época de estudiante).</p>
<p>Podríamos poner aquí, como ejemplo, un sistema que envía datos a un notificador. Si la tasa de datos a enviar es muy alta, pero el valor del dato caduca en un tiempo muy breve, cabe la posibilidad de que si un dato da error al ser enviado no sea necesario tratarlo porque enseguida surgirá un nuevo dato que haga que este caduque.</p>
<h3>Errores que deberemos tratar para que no falle posteriormente la aplicación.</h3>
<p>Lo más habitual cuando se produce un error es que este pueda afectar al funcionamiento posterior de la aplicación. Por ejemplo, si tratamos de abrir un fichero para guardar información y se produce un error es lógico pensar que la siguiente operación, la de escritura, también fallará. Por tanto, es necesario controlar el error de la apertura y actuar en consecuencia.</p>
<p>Lo más habitual en este tipo de errores es que se muestre al usuario un mensaje indicando la causa del error, pero no se haga anda más. Esto puede suceder al tratar de guardar un fichero de solo lectura o si no tenemos permisos para guardarlo en el lugar que le indicamos.</p>
<h3>Errores que tras tratarlos deberemos realizar uno o más reintentos.</h3>
<p>Este es un subcaso del anterior. Esta vez, en lugar de devolver el error lo que hacemos es reintentar la operación hasta que funcione o hasta que se pase de un umbral de reintentos.</p>
<p>Por ejemplo, cuando se imprime en una impresora de <em>tickets</em> (como las de los cajeros automáticos) estas a veces pueden tardar un poco entre operaciones. Si ante los intentos la impresora no devuelve error, sino un ocupada, podemos reintentar la operación hasta que esta finalmente sí sea posible o se produzca un error real.</p>
<p>Otro ejemplo normal es el que se da cuando se hace uso de las funciones POSIX. Muchas de estas funciones devuelven error en caso de que se produzca una señal durante su ejecución. Este caso se puede comprobar si la variable global <em>errno</em> tiene el valor <em>EINTR</em>. Igualmente, si en <em>errno</em> se encuentra el valor <em>EAGAIN</em> se puede volver a intentar la operación.</p>
<h3>Errores que impedirán a al aplicación continuar.</h3>
<p>Aunque podemos tratar de controlar y recuperarnos de todos los errores, siempre habrá errores que tras los cuales no podremos hacer nada. Uno muy habitual es cuando se produce una señal <em>SIGSEGV</em>. Esto significa que hemos accedido a una zona inválida de memoria. Lo normal es que cuando sucede esto sea el propio sistema operativo el que cancele el proceso.</p>
<p>Otros casos, más prácticos, pueden ser cuando se cae la conexión con una base de datos en ciertas aplicaciones.</p>
<h2>Tratamiento de errores</h2>
<p>Hasta ahora hemos visto por encima qué herramientas tenemos directamente para tratar errores y los tipos de errores que hay, pero no es lo único que necesitamos. Es necesario saber cómo queremos reaccionar ante estos errores y cómo diseñar nuestras aplicaciones para lidiar con ellos.</p>
<p>Este tratamiento de errores es dependiente de las herramientas y bibliotecas que utilicemos.</p>
<p>Siempre es preferible ir a los casos más sencillos y no complicarse mucho la vida. Eso sí, lo que un día es lo más sencillo al siguiente puede ser lo más complicado del mundo por lo que no hay que olvidar hacer refactorizaciones de código de forma periódica.</p>
<p>He estado buscando información sobre patrones de tratamiento de errores. He encontrado bastantes cosas sobre excepciones (como <a title="Patrones sobre uso de excepciones" href="http://c2.com/cgi/wiki?ExceptionPatterns" target="_blank">este</a>), pero no es lo que andaba buscando (lo que no significa que no exista). Por ese motivo voy a ir nombrando los patrones según me venga en gana (sí, es así de feo).</p>
<p>Lo más sencillo es empezar por los patrones que ejemplifican los tipos de error (diríamos que es lo más directo) y luego ir a patrones más complejos. No voy a ser demasiado sistemático con el tratamiento (aunque el ideal sería seguir la base explicada en la wikipedia sobre <a title="Patrones de diseño" href="http://es.wikipedia.org/wiki/Patr%C3%B3n_de_dise%C3%B1o" target="_blank">patrones de diseño</a>).</p>
<h3>En caso de error, pánico</h3>
<p>Este es el caso típico de error no recuperable. Encontramos un error que nos impide continuar y hacemos <strong>una parada ordenada</strong> de la aplicación. Remarco lo de parada ordenada porque hacer <em>exit</em> es sencillo, pero eso puede ser aún peor solución que el error que se haya producido.</p>
<p>Personalmente, a mi no me gusta este patrón, pero está muy extendido.</p>
<p><img fetchpriority="high" decoding="async" class="aligncenter wp-image-710 " src="https://blog.laparca.es/wp-content/uploads/2015/02/pattern_panic.svg" alt="pattern panic" width="558" height="290" />Este patrón puede ser más o menos complejo dependiendo de la aplicación. Se puede implementar utilizando <em>atexit</em> o usando mecanismos más sofisticados que permitan emular <em>atexit</em>, pero incluyendo funcionalidades de reordenación y eliminación de las funciones de salida.</p>
<h3>En caso de error, reintentar</h3>
<p>Si tenemos un patrón para parar ante un error, también hay uno para reintentar hasta que se resuelva la situación de error:</p>
<h3><img decoding="async" class="aligncenter wp-image-716" src="https://blog.laparca.es/wp-content/uploads/2015/02/pattern_retry.svg" alt="pattern_retry" width="235" height="294" />En caso de error, propagar</h3>
<p>Por lo general las aplicaciones están desarrolladas por capas bien diferenciadas. Cada capa se encarga de una cosa y suelen estar organizadas de tal modo que las capas superiores son más abstractas que las inferiores.</p>
<p><img decoding="async" class="aligncenter wp-image-718" src="https://blog.laparca.es/wp-content/uploads/2015/02/capas_app.svg" alt="capas_app" width="172" height="194" /></p>
<p>En este tipo de aplicación es útil el este patrón que consiste en detectar el error, hacer el tratamiento específico de recuperación de la capa y propagamos el error a la capa superior para que haga lo propio. Esto es lo que hacen normalmente las funciones de sistema: si encuentran un error lo informan a quien las haya llamado.</p>
<p>Antes de informar de que se ha producido un error se pueden hacer dos cosas:</p>
<ul>
<li>Podemos hacer una recuperación del error para dejar la aplicación/biblioteca/objetos implicados en un estado consistente.</li>
<li>Podemos no hacer nada.</li>
</ul>
<p>La elección dependerá de nuestra aplicación, aunque personalmente prefiero que se haga algo, aunque sea poner un comentario de «no es necesario realizar tratamiento alguno del error».</p>
<h3>Tratamiento diferido</h3>
<p>Puede suceder que cuando se produce el error no podamos comprobar éste o simplemente prefiramos dejar el tratamiento para un momento más adecuado. Esto es muy útil cuando estamos trabajando con tareas asíncronas como <a title="Manual de Linux Asynchronous I/O" href="http://man7.org/linux/man-pages/man7/aio.7.html" target="_blank">el sistema</a> <a title="Guía de uso de AIO" href="https://code.google.com/p/kernel/wiki/AIOUserGuide" target="_blank">AIO</a> de Linux.</p>
<p><img loading="lazy" decoding="async" class="aligncenter wp-image-721 " src="https://blog.laparca.es/wp-content/uploads/2015/02/pattern_delay.svg" alt="pattern_delay" width="454" height="351" /></p>
<h3>En caso de error, informar y preguntar</h3>
<p>Si consideramos que nuestra aplicación se ajusta al lo mostrado antes (que se encuentra dividida en capas) puede darse el caso en que dudemos cómo puede afectar el tratamiento de errores a las capas superiores. Hay que tener en cuenta que cada capa debe comportarse como una caja negra para el resto.</p>
<p>Imaginemos por un momento que somos unos maniáticos de la encapsulación y tenemos un servicio a muy bajo nivel que falla. Sabemos que es un servicio complejo y que tiene que realizar una gran cantidad de pasos para llevarse a cabo por completo, por lo que en caso de que falle una parte es preferible reintentar a tener que empezar de nuevo. El problema es que para reintentar necesitamos consentimiento del usuario (o simplemente queremos informarle) y esa parte del programa no sabe nada sobre interfaces de usuario, ni salida por pantalla ni de un largo etcétera. En este caso lo que podemos hacer es utilizar una llamada de <em>callback</em>. Esta si se encontrará programada en un nivel que sabe cómo va la cosa para informar al usuario e indicar la acción a tomar:</p>
<p><script src="https://gist.github.com/12b5a6220134041bbef7.js?file=on_error_callback.c"></script></p>
<p>Esto nos permitirá desacoplar las funcionalidades de la aplicación, pero, en cambio, hará más complejo el código (sobre todo en C). En otros lenguajes sería más sencillo gracias al uso de funciones lambda:</p>
<p><script src="https://gist.github.com/12b5a6220134041bbef7.js?file=on_error_lambda.cpp"></script></p>
<p>Vemos que ahora el tratamiento del error queda más cerca del punto donde lógicamente debería estar. En cualquier caso se puede mejorar más (aún le queda mucha mejora semántica).</p>
<p>En cualquier caso, como se ve en el ejemplo, no eliminamos el mecanismo de propagación. Esto lo hacemos para garantizar la máxima compatibilidad.</p>
<p>Debo reconocer que con esta idea empezamos a pensar en una API específica de tratamiento de errores. El motivo principal es que en aplicaciones pequeñas este tipo de tratamiento es un dolor de cabeza, pero en el trabajo empezamos a tener problemas por la falta de encapsulación. En este punto este tipo de soluciones nos compensa bastante.</p>
<h2>¿Y a partir de aquí?</h2>
<p>Hasta ahora hemos visto lo que pasa cuando nuestra aplicación detecta errores. Además, se ha abarcado los errores desde el punto de vista de cómo pueden afectar a la aplicación, pero no desde el punto de vista de cómo detectarlos nosotros. Esto es, alguien nos ha dicho que hay un error, pero, por ejemplo, ¿cómo detectamos que los datos pueden estar corruptos?</p>
<p>Por otra parte, no se ha tenido en cuenta los efectos que puede tener la multitarea en la aplicación. ¿Qué hacemos si un thread falla? ¿Y si son dos procesos independientes?</p>
<p>Y hay cosas más divertidas como ¿puedo fiarme de lo que dice el microprocesador? Todos hemos oído hablar alguna vez del famoso <a title="Fallo de coma flotante en procesadores Intel Pentium" href="http://en.wikipedia.org/wiki/Pentium_FDIV_bug" target="_blank">fallo en coma flotante de los procesadores Intel Pentium</a>.</p>
<p>Y hay muchas más cosas. Casi todo esto entra en lo que se denomina <a title="Tolerancia a fallos" href="http://es.wikipedia.org/wiki/Tolerancia_a_fallos" target="_blank">tolerancia a fallos</a>. Es un campo muy amplio.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.laparca.es/2015/02/26/control-de-errores/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Tratamiento de cadenas en C</title>
		<link>https://blog.laparca.es/2015/02/13/tratamiento-de-cadenas-en-c/</link>
					<comments>https://blog.laparca.es/2015/02/13/tratamiento-de-cadenas-en-c/#respond</comments>
		
		<dc:creator><![CDATA[laparca]]></dc:creator>
		<pubDate>Fri, 13 Feb 2015 12:22:48 +0000</pubDate>
				<category><![CDATA[Desarrollo]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[cadenas]]></category>
		<category><![CDATA[programacion]]></category>
		<category><![CDATA[tratamiento]]></category>
		<guid isPermaLink="false">https://blog.laparca.es/?p=695</guid>

					<description><![CDATA[Cuando empezamos a programar en C una de las cosas que probablemente más nos cuesta controlar es el tratamiento de cadenas. El lenguaje C es de bastante bajo nivel, por lo que sus tipos de datos básicos son muy cercanos a lo que la máquina puede utilizar. Los ordenadores no entienden de cadenas, pero sí &#8230; <a href="https://blog.laparca.es/2015/02/13/tratamiento-de-cadenas-en-c/" class="more-link">Seguir leyendo <span class="screen-reader-text">Tratamiento de cadenas en C</span> <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<p>Cuando empezamos a programar en C una de las cosas que probablemente más nos cuesta controlar es el tratamiento de cadenas.</p>
<p>El lenguaje C es de bastante bajo nivel, por lo que sus tipos de datos básicos son muy cercanos a lo que la máquina puede utilizar. Los ordenadores no entienden de cadenas, pero sí de direcciones de memoria. De hecho, no existe un tipo de cadena, sino que se usan <a title="Array" href="http://es.wikipedia.org/wiki/Vector_%28inform%C3%A1tica%29" target="_blank">arrays</a> de bytes. Y lo mejor de todo, ¡en C es el programador el que debe conocer la longitud del array! (cuanto bien, y a la vez cuánto mal, han hecho los lenguajes modernos).</p>
<p>Todas las funciones del estándar de C presuponen que una cadena es un array de bytes donde el último carácter es un nulo.</p>
<p>No voy a entrar en más detalles sobre que son las cadenas. Si quieres aprender cómo se programa con ellas puedes leer <a title="Cadenas de caracteres" href="http://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C/Cadenas_de_caracteres" target="_blank">Cadenas de caracteres</a> del manual <a title="Programación en C" href="http://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C" target="_blank">Programación en C</a> de  wikibooks.</p>
<p>Quien más y quien menos habrá visto que muchos problemas de seguridad en bibliotecas en C viene precisamente del tratamiento de cadenas. Casi se podría decir que si tienes que hacer un programa que tenga que manejar cadenas es aconsejable que mires cualquier otra cosa que no sea C. Aún así, esto no siempre será posible.</p>
<p>En el lugar en el que trabajo hemos empezado a cambiar el modo en que utilizamos las cadenas. Para facilitar su uso y reducir la cantidad de errores que pueden producirse, hemos creado un nuevo tipo de cadena. Bueno, se parece más a un <a title="Java String Builder" href="http://docs.oracle.com/javase/7/docs/api/java/lang/StringBuilder.html" target="_blank">StringBuilder</a> de java. Las motivaciones son varias:</p>
<ul>
<li>Queremos un tratamiento de cadenas más rápido (tener que recorrer una cadena cada vez que quieres conocer su longitud no es óptimo).</li>
<li>Queremos poder trabajar con cadenas sin preocuparnos por reasignar constantemente memoria. ¿Habéis probado un <em>strcat</em> cuando estás usando arrays y el <em>buffer</em> de destino es más pequeño que la cadena a concatenar?</li>
<li>Para ciertas operatorias queremos poder tener cadenas con caracteres nulos. Las cadenas de C no se llevan bien con esto, pero nosotros creamos cadenas para mandar a dispositivos que no sólo aceptan el nulo, sino que ciertas operaciones lo requieren. Con las funciones estándar sería muy complicado esto.</li>
</ul>
<p>Personalmente no creo que seamos los primeros en hacer algo así; no tengo la más mínima duda de que hay muchas personas con los mismos problemas.</p>
<p>Las ventajas de usar esta biblioteca son inmediatas:</p>
<ul>
<li>Simplificamos el código por no tener que preocuparnos en si hay o no espacio para almacenar la cadena y en la gestión de este espacio.</li>
<li>Minimizamos errores pues no nos pasaremos nunca del <em>buffer</em> (siempre podemos quedarnos sin memoria).</li>
<li>Agilizamos el desarrollo al poder escribir directamente código que haga lo que queremos (es una consecuencia del primer punto).</li>
<li>Se pueden optimizar ciertas operaciones. Esto se debe a que no hay que estar constantemente recorriendo cadenas para medirlas o que al «liberar» una cadena, no hacemos <em>free</em> y <em>malloc</em>, sino que marcamos la cadena como de longitud 0 (que es más rápido y permite aprovechar la memoria).</li>
</ul>
<p><strong>¡Mucho ojo con esto! </strong>Que en el día a día de mi trabajo esta haya sido una buena solución no significa que lo sea para todos los casos. Siempre hay que evaluar convenientemente cada situación antes de decantarse por una u otra solución.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.laparca.es/2015/02/13/tratamiento-de-cadenas-en-c/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
