<?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>BeOSmAn&#039;s Blooog &#187; Informática</title>
	<atom:link href="http://beosman.org/archivo/category/informatica/feed" rel="self" type="application/rss+xml" />
	<link>http://beosman.org</link>
	<description>Breaking with the past to build the future</description>
	<lastBuildDate>Wed, 08 Feb 2012 20:42:10 +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>Sesión remota gráfica en Linux</title>
		<link>http://beosman.org/archivo/2012/informatica/sesion-remota-grafica-en-linux.html</link>
		<comments>http://beosman.org/archivo/2012/informatica/sesion-remota-grafica-en-linux.html#comments</comments>
		<pubDate>Tue, 07 Feb 2012 18:54:49 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Sistemas Operativos]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=5618</guid>
		<description><![CDATA[Cuando accedemos a un ordenador, generalmente lo hacemos en modo consola, es decir, estamos delante de la pantalla, el teclado y el ratón y todo lo que hagamos mediante la interfaz lo hacemos en la máquina que tenemos delante. Pero ¿qué pasa cuando queremos trabajar en otro ordenador pero sin movernos del nuestro? Bien porque [...]]]></description>
			<content:encoded><![CDATA[<p>Cuando accedemos a un ordenador, generalmente lo hacemos en modo consola, es decir, estamos delante de la pantalla, el teclado y el ratón y todo lo que hagamos mediante la interfaz lo hacemos en la máquina que tenemos delante.</p>
<p>Pero ¿qué pasa cuando queremos trabajar en otro ordenador pero sin movernos del nuestro? Bien porque está lejos, bien porque somos unos vagos… <img src='http://beosman.org/wp-includes/images/smilies/grin.gif' alt=':grin:' class='wp-smiley' /> </p>
<p><img src="/uploads/2012/02/conexion-escritorio-remoto-200x123.png" alt="" title="Conexión a Escritorio Remoto" width="200" height="123" class="floatright" /></p>
<p>En <a href="http://es.wikipedia.org/wiki/Windows">Windows</a> es de sobra conocido el <a href="http://es.wikipedia.org/wiki/Remote_Desktop_Protocol">Protocolo de Escritorio Remoto</a>, donde nos conectamos a cualquier ordenador con Windows cuyo equipo esté compartido (que acepte conexiones remotas) y tenemos, en una ventana o en pantalla completa, el escritorio completo del ordenador remoto con el que podemos trabajar como si estuviéramos delante.</p>
<p>Y, en Linux, ¿podemos hacer algo similar? La respuesta corta es: por supuesto. La respuesta larga incluye la siguiente explicación:</p>
<p>El sistema operativo <a href="http://es.wikipedia.org/wiki/GNU/Linux">GNU/Linux</a> cuenta con un servidor gráfico (la aplicación que gestiona la <a href="http://es.wikipedia.org/wiki/Interfaz_gr%C3%A1fica_de_usuario">interfaz gráfica de usuario</a>) llamado <a href="http://es.wikipedia.org/wiki/X.Org_Server">X.org</a>, que es una implementación del sistema <a lang="en" href="http://es.wikipedia.org/wiki/X_Window_System">X Window System</a>. Este servidor es el programa encargado de gestionar las pantallas, las ventanas y, también, las conexiones remotas a otros equipos para tener interfaz gráfica remota. El protocolo usado para estas conexiones remotas, que es lo que nos interesa, se llama <acronym lang="en" title="X Display Manager Control Protocol"><a href="http://es.wikipedia.org/wiki/XDMCP">XDMCP</a></acronym>.</p>
<p>Este servidor gráfico se apoya en otra aplicación, llamada <em>Display Manager</em>, encargada de iniciar dicho servidor gráfico a la vez que muestra la pantalla de acceso, es decir, donde se pone el usuario y la contraseña. Y seguro que los usuarios de Linux conocéis más de un gestor de pantalla: <a href="http://es.wikipedia.org/wiki/XDM"><acronym title="X Display Manager" lang="en">xdm</acronym></a>, <a href="http://es.wikipedia.org/wiki/GDM"><acronym title="Gnome Display Manager" lang="en">gdm</acronym></a>, <a href="http://es.wikipedia.org/wiki/KDM"><acronym title="KDE Display Manager" lang="en">kdm</acronym></a>, <a href="http://es.wikipedia.org/wiki/LightDM"><acronym title="Light Display Manager" lang="en">lightdm</acronym></a>…</p>
<p>A partir de este punto donde ya sabemos, más o menos, cómo funciona esto de la gestión de la interfaz gráfica, lo que nos queda para habilitar el acceso remoto en Linux es configurar el gestor de pantalla (<em>display manager</em>) del ordenador remoto al que queremos acceder para que tenga activado el protocolo <acronym lang="en" title="X Display Manager Control Protocol">XDMCP</acronym>.</p>
<p>Hay que tener en cuenta que cada gestor usado (como hemos dicho: gdm, kdm, lightdm&#8230;) tiene su propia configuración, pero para el más moderno y usado en la última versión de Ubuntu, <code>lightdm</code>, la configuración está en el archivo <code>/etc/lightdm/lightdm.conf</code> (para el resto se puede ver su configuración usando el manual o, en una consola, con el comando <code>man <em>&lt;dm&gt;</em></code>). En este archivo de configuración hay que activar el protocolo <acronym lang="en" title="X Display Manager Control Protocol">XDMCP</acronym> añadiendo las siguientes líneas en dicho archivo:</p>
<div class="source">
<p>[XDMCPServer]<br />
enable=true</p>
</div>
<p>Y luego reiniciar el servidor <code>lightdm</code> —teniendo en cuenta que se cerrarán todas las sesiones— con el comando:</p>
<p class="terminal">
$ sudo service lightdm restart
</p>
<p>Ya tenemos nuestro servidor funcionando y aceptando conexiones remotas. Y, ahora, para acceder a él, lo podemos hacer de dos formas:</p>
<p>La primera es usando el programa <code>Xnest</code> que se instala escribiendo el comando <code>sudo apt-get install xnest</code>. Luego, para lanzar la sesión remota hay que lanzar el comando:</p>
<p class="terminal">
$ Xnest :1 -query remote.server
</p>
<p>En el caso de que tengáis en vuestro equipo más de una sesión gráfica iniciada, hay que cambiar el <code>:1</code> por un número de pantalla que no está usado. Además, <code>remote.server</code> puede ser tanto el nombre de un servidor como su IP.</p>
<p>Con este comando se nos abrirá una ventana donde aparecerá la pantalla de acceso a nuestro servidor remoto como si estuviéramos delante de él.</p>
<p><a href="/uploads/2012/02/xnest.jpg"><img src="/uploads/2012/02/xnest-650x494.jpg" alt="Ventana de Xnest" title="Ventana de Xnest" width="650" height="494" class="alignnone size-large wp-image-5637 image" /></a></p>
<p>La segunda opción es lanzar directamente las X (otra instancia del servidor X.org) desde un terminal mediante el comando: </p>
<p class="terminal">
$ X :1 -query remote.server
</p>
<p>Hay que tener en cuenta lo mismo sobre el número de pantalla (<code>:1</code>) y el nombre del servidor que con <code>Xnest</code>.</p>
<p>Con este comando, en lugar de abrir una ventana, lo que hará será cambiar de <a href="http://en.wikipedia.org/wiki/Virtual_terminal">terminal virtual  (<abbr title="Virtual Terminal" lang="en">VT</abbr>)</a> —de forma similar a cuando cambiamos entre la interfaz gráfica y una consola con las teclas Ctrl+Alt+F1/F7— a, generalmente, el número 8 (Ctrl+Alt+F8) mostrándonos la pantalla de acceso al sistema remoto.</p>
<p>Con el segundo método realmente parece que estamos delante de la máquina remota ya que no hay ventanas de por medio que aparenten estar en un sistema virtualizado. Además, con las combinaciones de teclas Ctrl+Alt+F<em>x</em> bastará para cambiar entre equipos de forma muy cómoda y muy rápida, teniendo tanto la sesión local como la sesión remota totalmente activas y funcionales.</p>
<p>Y realmente es muy cómodo no tener que desplazarse para trabajar en otros equipos cuando necesitas la interfaz gráfica. Aunque, bueno, ya sabéis que para administrar sistemas no hay nada mejor ni más rápido que una consola en modo texto, por supuesto <img src='http://beosman.org/wp-includes/images/smilies/grin.gif' alt=':grin:' class='wp-smiley' /> .</p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2012/informatica/sesion-remota-grafica-en-linux.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Implementación de la clase de sincronización Semaphore con la librería boost (y alguna cosa más)</title>
		<link>http://beosman.org/archivo/2012/informatica/implementacion-de-la-clase-de-sincronizacion-semaphore-con-la-libreria-boost-y-alguna-cosa-mas.html</link>
		<comments>http://beosman.org/archivo/2012/informatica/implementacion-de-la-clase-de-sincronizacion-semaphore-con-la-libreria-boost-y-alguna-cosa-mas.html#comments</comments>
		<pubDate>Thu, 02 Feb 2012 19:21:19 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Informática]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=5583</guid>
		<description><![CDATA[Una de las primitivas clásicas de la sincronización de procesos e hilos —hablando de informática— es el semáforo. La diferencia entre este y el mutex es que el semáforo se puede bloquear y liberar desde diferentes hilos/procesos mientras que el mutex no; es para proteger una zona de código (el acceso a variables por un [...]]]></description>
			<content:encoded><![CDATA[<p>Una de las primitivas clásicas de la sincronización de <a href="http://es.wikipedia.org/wiki/Proceso_(inform%C3%A1tica)">procesos</a> e <a href="http://es.wikipedia.org/wiki/Hilo_de_ejecuci%C3%B3n">hilos</a> —hablando de informática— es el <a href="http://es.wikipedia.org/wiki/Sem%C3%A1foro_(programaci%C3%B3n)">semáforo</a>. La diferencia entre este y el <em><a href="http://es.wikipedia.org/wiki/Mutex">mutex</a></em> es que el semáforo se puede bloquear y liberar desde diferentes hilos/procesos mientras que el <em>mutex</em> no; es para proteger una zona de código (el acceso a variables por un sólo hilo).</p>
<p>La librería <a href="http://www.boost.org/"><code>boost</code></a> —una de las mejores librerías generalistas para C++ que hay, por no decir la mejor— no hay un semáforo de este tipo propiamente dicho, sino que se usan <a href="http://en.wikipedia.org/wiki/Condition_variable">variables de condición</a> para implementarlo; o semáforos con nombre, aunque estos son más específicos para sincronización entre procesos en lugar de entre hilos. Esta implementación se basa mucho en el estándar <acronym title="Portable Operating System Interface (UNIX)" lang="en"><a href="http://es.wikipedia.org/wiki/POSIX">POSIX</a></acronym> de hilos (<code><a href="http://en.wikipedia.org/wiki/Pthreads">pthreads</a></code>) pero orientándolo a objetos.</p>
<p>Es por esto que, para no tener que usar un variable de condición, un <code>mutex</code> y un contador cada vez que se quiere implementar un semáforo, se puede usar esta clase:</p>
<pre>
#include &lt;boost/thread.hpp&gt;
#include &lt;boost/thread/condition_variable.hpp&gt;
#include &lt;boost/thread/mutex.hpp&gt;

class Semaphore {
	private:
    	mutable boost::mutex fMutex;
	    boost::condition_variable fCondVar;
    	unsigned long fCounter;

	public:
    	Semaphore(unsigned long counter)
          : fMutex(),
            fCondVar(),
            fCounter(counter)
        {
    	}

	    void post() {
    	    boost::mutex::scoped_lock lock(fMutex);
    	    ++fCounter;
    	    fCondVar.notify_one();
	    }

    	void wait() {
    	    boost::mutex::scoped_lock lock(fMutex);
    	    while(fCounter &lt;= 0)
    	        fCondVar.wait(lock);
    	    --fCounter;
    	}

    	bool isLocked() const {
    		return fCounter == 0;
    	}
};
</pre>
<p>Un buen ejemplo de uso de un semáforo es implementar una cola de datos usada para el famoso <a href="http://en.wikipedia.org/wiki/Producer-consumer_problem">problema del productor/consumidor</a>, es decir, tenemos dos procesos, uno que produce datos y los mete en la cola, y otro que los consume sacándolos de dicha cola teniendo en cuenta que, cuando la cola está vacía, el consumidor está bloqueado esperando a que haya más valores.</p>
<p>Para ello, la implementación de la cola podría ser la siguiente:</p>
<pre>
#include &lt;deque.hpp&gt;

using std::deque;

template &lt;typename T&gt;
class Queue {
	private:
		deque&lt;T&gt; fQueue;
		mutable boost::mutex fAccessLock;
		mutable Semaphore fSem;

	public:
		Queue() : fQueue(), fAccessLock(), fSem(0) {}

		virtual ~Queue() {}

		virtual void push(T elem) {
			fSem.post();
			boost::mutex::scoped_lock lock(fAccessLock);
			fQueue.push_front(elem);
		}

		virtual T pop() {
			fSem.wait();
			boost::mutex::scoped_lock lock(fAccessLock);
			T elem = fQueue.back();
			fQueue.pop_back();
			return elem;
		}
};
</pre>
<p>Y el programa de prueba implementando dos funciones, una el productor y otra el consumidor, y usando <a href="http://www.boost.org/doc/libs/1_48_0/doc/html/thread.html">hilos de <code>boost</code></a> sería:</p>
<pre>
#include &lt;boost/ref.hpp&gt;
#include &lt;boost/date_time.hpp&gt;
#include &lt;iostream&gt;

template &lt;typename T&gt;
void
producer(Queue&lt;T&gt;&#038; q) {
	int counter = 0;
	int times = 5;
	while(!boost::this_thread::interruption_requested() &#038;&#038; times-- &gt; 0) {
		for(int i = 0; i &lt; 5; i++) {
			cout &lt;&lt; "producer: inserting " &lt;&lt; counter &lt;&lt; endl;
			q.push(counter++);
		}
		sleep(4);
	}
}

template &lt;typename T&gt;
void
consumer(Queue&lt;T&gt;&#038; q) {
	while(!boost::this_thread::interruption_requested()) {
		cout &lt;&lt; "consumer: extracting " &lt;&lt; q.pop() &lt;&lt; endl;
		boost::this_thread::sleep(boost::posix_time::milliseconds(100));
	}
}

int
main() {
	Queue&lt;int&gt; q(7);

	boost::thread p(producer,boost::ref(q));
	sleep(1);
	boost::thread c(consumer,boost::ref(q));

	p.join();
	c.join();

	return 0;
}
</pre>
<p>En este ejemplo, el hilo productor inserta cinco números cada 4 segundos (a ráfagas) mientras que el productor saca un número cada 100 milisegundos. Cuando la cola está vacía, gracias al semáforo el hilo consumidor espera hasta que el productor inserte más números, y así sucesivamente.</p>
<p>Pues sí, pues vale, muy bonito, pero ¿para qué se usa esta cola y el productor/consumidor? Pues, en informática, en multitud de software. Por ejemplo, en el reproductor multimedia que usáis todos los días. El hilo productor es el que hilo que lee del disco duro la música insertando los datos leídos en un <em>buffer</em> (en la cola), y el consumidor es el hilo que saca los datos de ese <em>buffer</em>, los decodifica y los envía a la tarjeta de sonido. Y con el vídeo funciona igual (aparte, claro, de los mecanismos de sincronización entre sonido y vídeo).</p>
<p>Pero en esta implementación hay una cosa que falta: el productor debería parar de insertar elementos cuando la cola esta llena hasta que el consumidor saque algún elemento. Pero esa implementación será para el próximo programa <img src='http://beosman.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  .</p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2012/informatica/implementacion-de-la-clase-de-sincronizacion-semaphore-con-la-libreria-boost-y-alguna-cosa-mas.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>11 características que Twitter debería tener</title>
		<link>http://beosman.org/archivo/2011/informatica/11-caracteristicas-que-twitter-deberia-tener.html</link>
		<comments>http://beosman.org/archivo/2011/informatica/11-caracteristicas-que-twitter-deberia-tener.html#comments</comments>
		<pubDate>Fri, 09 Dec 2011 14:59:32 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Opinión]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=5412</guid>
		<description><![CDATA[Mucha gente usa Twitter, esa red social tan &#8220;rara&#8221; que sólo permite 140 caracteres en cada mensaje. Y quizás sea por eso su gran éxito a pesar de que sus características técnicas no han cambiado desde&#8230; bueno, casi desde que se creó. Por eso creo que, desde el punto de vista de un usuario (no [...]]]></description>
			<content:encoded><![CDATA[<p>Mucha gente usa <a href="http://es.wikipedia.org/wiki/Twitter">Twitter</a>, esa <a href="http://es.wikipedia.org/wiki/Red_social">red social</a> tan <em>&#8220;rara&#8221;</em> que sólo permite 140 caracteres en cada mensaje. Y quizás sea por eso su gran éxito a pesar de que sus características técnicas no han cambiado desde&#8230; bueno, casi desde que se creó. Por eso creo que, desde el punto de vista de un usuario (no de un desarrollador), Twitter necesita, al menos, que se implementen estas 11 características:</p>
<ol>
<li><strong>Edición de tuits</strong>: Sería bueno poder editar los tuits, al menos durante un tiempo después de la publicación, para corregir, por ejemplo, faltas de ortografía. No sería bueno poder editarlos siempre ya que con la sucesivas ediciones podrías hacer totalmente incoherente la conversión con el resto de usuarios.</li>
<li><strong>Bloqueo de usuarios sin necesidad de dejar de seguirlos</strong>: ¿Sabéis eso de &#8220;te sigo por compromiso&#8221;? Pues eso. Además, he visto algunos tuits donde ya se demanda esta característica.</li>
<li><strong>Omisión de tuits en el <em>timeline</em> que contengan un determinado <em>hashtag</em></strong>: No estaría demás que se pudiera, en el <acronym title="Timeline" lang="en">TL</acronym> principal, omitir de forma automática los tuits que contengan algún <em><a href="http://es.wikipedia.org/wiki/Hashtag">hashtag</a></em> determinado, por eso de ser, en ocasiones, bastante cansinos.</li>
<li><strong>Poder recuperar todos tus tuits</strong>: En caso de tener un cliente de Twitter que no sea el de Web (y creo que con el de Web también), sólo podrás recuperar tus 3000 últimos tuits. Aunque el resto siguen en la base de datos, su API no soporta recuperar más de esta cantidad.</li>
<li><strong>Posibilidad de copia de seguridad de tus tuits</strong>: No hay ninguna forma de recuperar todos tus tuits si no es con aplicaciones externas. Y a esto hay que aplicarle el límite del punto anterior. Twitter debería implementar una forma de hacer copia de seguridad de tus tuits.</li>
<li><strong>Respuesta pública</strong>: Posibilidad de responder a un tuit de forma pública (que lo vean todos los usuarios que te siguen en lugar de los usuarios que te siguen y los que siguen al que respondes) para así no tener que poner un carácter antes del nombre de quien estás respondiendo y tener que desaprovecharlo.</li>
<li><strong>Implementación de un sistema para <em>&#8220;leer más tarde&#8221;</em></strong>: Yo, al menos, uso los favoritos como marcadores para leer luego. No tengo ningún tuit favorito, simplemente en mi cliente del móvil los marco (los que tienen imágenes, alguna <acronym title="Uniform Resource Locator" lang="en">URL</acronym>&#8230;) para leer cuando esté en un ordenador o <em>tablet</em>. Recordemos las limitaciones de las pantallas pequeñas y, sobre todo, las limitaciones de las conexiones <a href="http://es.wikipedia.org/wiki/3G">3G</a>.</li>
<li><strong>Formato del texto</strong>: Esta quizás sería la más rompedora con la filosofía de Twitter, pero ayudaría mucho a expresar justamente lo que queremos decir —<em>&#8220;emociones&#8221;</em> incluidas— con, al menos, negrita, cursiva y tachado.</li>
<li><strong>Enlaces contextualizados</strong>: Los enlaces deberían ir como en HTML, enlazando un texto en lugar de que vaya la <acronym title="Uniform Resource Locator" lang="en">URL</acronym> directamente. El contexto es muy importante en la Web y Twitter está haciendo un esfuerzo enorme —entiendo que inconscientemente— para eliminarlo. Lo mismo que los acortadores <acronym title="Uniform Resource Locator" lang="en">URL</acronym>, donde se pierde toda la semántica de las <a href="http://es.wikipedia.org/wiki/URL_sem%C3%A1ntica"><acronym title="Uniform Resource Locator" lang="en">URL</acronym>s amigables</a>. Pero ese es otro tema.</li>
<li><strong>Estadísticas</strong>: Sería buena idea que se proporcionaran estadísticas —principalmente informativas— de uso de Twitter, tanto de los usuarios (tuits por día, horarios de tuiteo, retuits…) como generales (tuis diarios, tuits diarios por países, usuarios activos en tiempo real…).</li>
<li><strong>Avance automático en el cliente Web</strong>: En el cliente Web, cuando sale el aviso de que hay nuevos tuits, al hacer clic, la página debería avanzar automáticamente hasta el último que has leído. Además, en la nueva interfaz, se debería marcar de alguna forma el último tuit que has leído (en la antigua se hacía).</li>
</ol>
<p>Y una característica extra, la duodécima: más caracteres. Aquí hay muchísima controversia. Quizás, como he dicho antes, el éxito de Twitter sea precisamente el de tener un número de caracteres limitados. Pero, al menos a mi, muchas más veces de las que me gustaría se me quedan muy cortos para escribir lo que quiero decir. Y a veces no soy capaz de hacerle caso al famoso mensaje <em>&#8220;Tu Tweet contiene mas de 140 caracteres. Tendrás que ser más ingenioso.&#8221;</em>.</p>
<p>No estoy diciendo que se ponga un número ilimitado (o muy grande) de caracteres como ocurre con <a href="http://es.wikipedia.org/wiki/Google%2B">Google+</a> o <a href="http://es.wikipedia.org/wiki/Facebook">Facebook</a>, pero sí alguno más, por ejemplo —por aventurarme con un número— 200; o, mejor, 256 (2<sup>8</sup>, por eso de ser friki <img src='http://beosman.org/wp-includes/images/smilies/tongue.gif' alt=':tongue:' class='wp-smiley' /> ). Por ejemplo, las <a href="http://www.meneame.net/notame/">notas de Menéame</a> tienen 1000 caracteres y creo que la mayoría de ellas no pasan ni de los 500, pero cuando hay algo más largo que decir, se puede hacer sin ningún problema.</p>
<p>Pero bueno, esta es sólo mi opinión. Y vosotros ¿qué opináis de estas 11 características que Twitter debería tener? ¿Alguna más? ¿Alguna menos?</p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2011/informatica/11-caracteristicas-que-twitter-deberia-tener.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>¿Pagarías por usar tu distribución de Linux favorita?</title>
		<link>http://beosman.org/archivo/2011/informatica/%c2%bfpagarias-por-usar-tu-distribucion-de-linux-favorita.html</link>
		<comments>http://beosman.org/archivo/2011/informatica/%c2%bfpagarias-por-usar-tu-distribucion-de-linux-favorita.html#comments</comments>
		<pubDate>Mon, 05 Dec 2011 22:09:05 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Opinión]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=5399</guid>
		<description><![CDATA[Me ha llamado mucho la atención esta encuesta del blog Usemos Linux: &#8220;¿Pagarías por usar tu distribución favorita de Linux?&#8221;. Mi respuesta corta: No. Mi respuesta larga: No porque todas las distribuciones usan el mismo software. Todas. Todas usan X Window System (de momento Wayland está en desarrollo). Todas usan Gnome o KDE con alguna [...]]]></description>
			<content:encoded><![CDATA[<p>Me ha llamado mucho la atención <a href="http://usemoslinux.blogspot.com/2011/12/pagarias-por-usar-tu-distro-linux.html">esta encuesta</a> del blog <a href="http://usemoslinux.blogspot.com/">Usemos Linux</a>: <em>&#8220;¿Pagarías por usar tu distribución favorita de Linux?&#8221;</em>.</p>
<p>Mi respuesta corta: <strong>No</strong>.</p>
<p>Mi respuesta larga: No porque <strong>todas</strong> las distribuciones <strong>usan el mismo software</strong>. Todas. Todas usan <a href="http://es.wikipedia.org/wiki/X_Window_System">X Window System</a> (de momento <a href="http://es.wikipedia.org/wiki/Wayland_(servidor_gr%C3%A1fico)">Wayland</a> está en desarrollo). Todas usan <a href="http://es.wikipedia.org/wiki/Gnome">Gnome</a> o <a href="http://es.wikipedia.org/wiki/KDE">KDE</a> con alguna disidente que usa <a href="http://es.wikipedia.org/wiki/Xfce">Xfce</a>, <a href="http://es.wikipedia.org/wiki/LXDE">LXDE</a> o similares. Todas tienen las mismas librerías. Todas tienen la misma arquitectura multimedia. Y, como no, todas usan, en esencia, el mismo <a href="http://es.wikipedia.org/wiki/N%C3%BAcleo_Linux">Kernel</a>.</p>
<p>¿Por qué pagar por algo que haga una empresa cuando cualquier otra empresa o particular lo puede hacer sin ningún coste? Incluso, si eres un poco aficionado al tema, te puedes hacer tu propia distribución sin más coste que tu tiempo. Y, ojo, que no estamos hablando del servicio técnico.</p>
<p>Yo, personalmente, pagaría por tener algo diferente (y mejor, se entiende). Algo que haya hecho una empresa para mejorar lo que hay en lugar de ser una mera agrupación de distintos elementos de software, todo con el mismo Kernel, y ponerle un nombre rimbombante.</p>
<p>Si Windows no es de mi agrado a nivel técnico (y lo uso como usuario), Linux tampoco lo es (y también lo uso como usuario). Ya sabéis que yo soy más de <a href="http://es.wikipedia.org/wiki/BeOS">BeOS</a>/<a href="http://es.wikipedia.org/wiki/Haiku_(sistema_operativo)">Haiku</a> <img src='http://beosman.org/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> .</p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2011/informatica/%c2%bfpagarias-por-usar-tu-distribucion-de-linux-favorita.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>C#</title>
		<link>http://beosman.org/archivo/2011/informatica/c-sharp.html</link>
		<comments>http://beosman.org/archivo/2011/informatica/c-sharp.html#comments</comments>
		<pubDate>Thu, 01 Dec 2011 18:54:20 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Lenguajes]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=5299</guid>
		<description><![CDATA[Por necesidades del servicio voy a empezar a programar en C#, así que me he leído un par de manuales y he practicado un poco con ello. Y, la verdad, no me ha convencido demasiado. Así que, por petición popular (si por una persona se le puede llamar &#8220;popular&#8221;), estas son algunas de las conclusiones [...]]]></description>
			<content:encoded><![CDATA[<p>Por <em>necesidades del servicio</em> voy a empezar a programar en <a href="http://es.wikipedia.org/wiki/C_Sharp">C#</a>, así que me he leído un par de manuales y he practicado un poco con ello. Y, la verdad, <a href="https://twitter.com/#!/beoxman/status/139403030180274177">no me ha convencido demasiado</a>. Así que, por <a href="https://twitter.com/#!/albfernandez/status/139419504382967808">petición popular</a> (si por una persona se le puede llamar <em>&#8220;popular&#8221;</em>), estas son algunas de las conclusiones que he sacado, aunque si eres muy fan de C# quizás no deberías seguir leyendo <img src='http://beosman.org/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> :</p>
<h3>Declaración de tipos</h3>
<p>Extrañamemente se usan formas diferentes para declarar lo mismo. Porque declarar una variable o un nuevo tipo de dato debería ser consistente. Por ejemplo, para declarar una variable se usa <code>&lt;tipo de dato&gt; <strong>&lt;identificador&gt;</strong>;</code>. En cambio, para declarar un alias de un tipo de dato (no hay nuevos tipos) se usa <code>using <strong>&lt;identificador&gt;</strong> = &lt;tipo de dato&gt;;</code>. Y, ya para rematar, para declarar un <code><a href="">delegate</a></code> se usa <code>delegate &lt;valor devuelto&gt; <strong>&lt;identificador&gt;</strong> (&lt;parámetros&gt;);</code>.</p>
<p>¿No sería más sencillo y consistente tener una sintaxis común? Por ejemplo: <code>&lt;tipo de dato&gt; &lt;descripción&gt; <strong>&lt;identificador&gt;</strong>;</code>, con lo que la declaración quedaría:</p>
<pre>
// Variable:
int i;

// Tipo de dato:
typedef int MyInt;

// Usando 'using' (sin introducir ninguna palabra reservada adicional):
using int as MyInt;

// Delegate:
delegate void(int) MyDelegate;
</pre>
<p>Con esto la sintaxis siempre es consistente. Tenemos a la izquierda los tipos y a la derecha, siempre, el nombre tanto de la variable como del tipo nuevo como del delegate (que no deja de ser un tipo nuevo).</p>
<h3>Nuevos tipos de datos</h3>
<p>En C#, al igual que en C++, no se pueden declarar nuevos tipos de datos. Sí, en serio. Lo que estáis pensando ahora mismo es que con typedef sí se puede&#8230; pues no. En realidad es un alias del tipo básico. En C++, este código:</p>
<pre>
typedef int myint_t;
void overloaded_function(int value);
void overloaded_function(myint_t value);  // Error de compilación.
</pre>
<p>Daría error de compilación porque las dos funciones son iguales. <code>myint_t</code> no es un tipo de datos nuevo, sino un alias de <code>int</code>. En C# ocurre lo mismo, sólo que en lugar de declarar los <em>nuevos</em> tipos con <code>typedef</code> (que no tiene esa palabra reservada) se usa <code>using</code>:</p>
<pre>
using myint_t = int;

class Main {
  void overloaded_funcion(int value) {...}
  void overloaded_funcion(myint_t value) {...}  // Error de compilación.
}
</pre>
<p>También se puede hacer alguna triquiñuela, como hacer una clase <code>MyInt</code> que herede de <code>System.Int32</code>. Pero ya habría que implementar ciertas cosas para que funcionase.</p>
<h3>Los métodos y su tipo de acceso</h3>
<p>Es bastante enrevesado el uso de <code>virtual</code>, <code>override</code> y <code>new</code> para controlar el polimorfismo de las clases. Por ejemplo, en el código:</p>
<pre>
class A {
	public virtual void Who() { Console.WriteLine("A"); }
}

class B : A {
	public override void Who() { Console.WriteLine("B"); }
}

class C : B {
	public new virtual void Who() { Console.WriteLine("C"); }
}

class D : C {
	public override void Who() { Console.WriteLine("D"); }
}

C c = new D();
c.Who();	// Escribe "D"; lógico ¿no?

A a = new D();
a.Who();	// ¡Escribe "B"! ¿Dónde está la lógica de funciones virtuales aquí?
</pre>
<p>Es obligatorio que en todos los métodos que se podrán sobreescribir en clases derivadas se ponga <code>virtual</code>; que en todos los métodos que sobreescriben se ponga <code>override</code>; y que si un método oculta a otro se ponga <code>new</code>.</p>
<p>¿No sería más sencillo que todos los métodos fuesen virtuales por defecto (porque cuando haces clases, lo más probable es que las vayas a heredar)? ¿No sería más lógico que cuando declaras un método con el mismo nombre en la clase base, automáticamente se sobreescriba el de la base y, en caso de querer llamar al método de la base, uses <code>super</code>, <code>base</code> o similar?</p>
<p>Por cierto, decidme un caso <strong>real</strong> donde se use esta funcionalidad.</p>
<h3>El problema de la clase base frágil</h3>
<p>En <a href="http://ssw.jku.at/Teaching/Lectures/CSharp/Tutorial/Part2.pdf">este manual se menciona el problema de la clase base frágil</a>, que habla de que en Java podría suceder esto, teniendo en principio estas clases:</p>
<pre>
class BaseClass {
	public void CleanUp() {
		System.out.println("BaseClass.CleanUp()");
	}
}

class DerivedClass extends BaseClass {
	public void Delete() {
		System.out.println("DerivedClass.Delete()");
	}
	public void CleanUp() {
		Delete();
	}
}

public class Test {
	public static void main(String[] args) {
		BaseClass k = new DerivedClass();
		k.CleanUp();
	}
}
</pre>
<p>La salida de este programa sería:</p>
<p class="terminal">
$ javac Test.java &#038;&#038; java Test<br />
DerivedClass.Delete();<br />
$
</p>
<p>Si luego implementamos el método <code>Delete()</code> en la clase base de esta forma:</p>
<pre>
class BaseClass {
	public void CleanUp() {
		System.out.println("BaseClass.CleanUp()");
	}
	public void Delete() {
		System.out.println("Delete all the world!");
	}
}
</pre>
<p>Según el manual, ¡podríamos borrar el mundo!</p>
<p>Esto sería un verdadero problema&#8230; si existiese. Pero es muy fácil comprobar que no se produce. La salida con la clase modificada es la misma que sin ella. Sólo usando <code>super.Delete()</code> se podría borrar el mundo.</p>
<h3>Ámbito global o local</h3>
<p>En C#, si una clase oculta un espacio de nombres, para acceder a dicho espacio introduce una nueva palabra que no está reservada, pero que hay que recordar: <code>global</code>. Por ejemplo:</p>
<pre>
class Main {

  public class System {}

  static void Main(string[] args) {
    System.Console.WriteLine("¡Hola mundo!");  // Error: la clase 'System' oculta
                                               // el espacio de nombres 'System'.
    global::System.Console.WriteLine("Esto sí funciona.");
  }
}
</pre>
<p>¿No sería más sencillo, en lugar de introducir otro identificador nuevo, usar sólo el operador <code>::</code>, como hace C++ o, incluso, usar el operador <code>.</code>?</p>
<h3>Comportamientos extraños de las variables</h3>
<p>Resulta que si declaras una variable de tipo <code>delegate</code>, esta se comporta como una <strong>lista</strong> de delegates que se llaman todos seguidos:</p>
<pre>

class Test {
	void Notify1(string text) {
		System.Console.WriteLine("Hello " + text);
	}
	void Notfiy2(string text) {
		System.Console.WriteLine("Goodbye " + text);
	}
}

Test test = new Test();

delegate void Notifier(string text);

Notifier notifier;
notifier = new Notifier(test.Notify1);
notifier += new Notifier(test.Notify2);

notifier("Manolito");

// La salida será:
// Hello Manolito
// Goodbye Manolito
</pre>
<p>¿Nos aclaramos? ¿<code>Notifier</code> es una variable o es una lista de variables? Y si todos los <code>delegate</code>s asignados devuelven algún valor, sólo se devuelve el último ejecutado. ¿Y el resto?</p>
<h3>Recorriendo listas</h3>
<p>C# añade el <code>foreach</code>, que no es más que lo que se conoce como <em><a href="http://en.wikipedia.org/wiki/Syntactic_sugar">syntactic sugar</a></em> para el bucle <code>for</code> de toda la vida evitando que el programador use variables índice:</p>
<pre>

string[] stringArray = new string[] { /* Inicialización */ };

foreach(var s in stringArray) {
  System.Console.WriteLn(s);
}
</pre>
<p>Pero no estoy criticando ese <em>syntactic sugar</em>, todo lo contrario, eso me parece muy bien. Cuanto menos código se escriba y haga más cosas, mejor.</p>
<p>Lo que ya no me parece tan bien es que en ese bucle <code>foreach</code> sólo se tenga acceso a los valores de la lista a recorrer y no se tenga acceso al índice de dicha lista. Sí, simplemente a la famosa <code>i</code> que se omite para que el programador escriba menos código.</p>
<p>Y por culpa de esto, en caso de necesitarla, pues tienes que declararla fuera e incrementarla manualmente. Vamos, con en un bucle <code>for</code>.</p>
<h3>Anidamiento</h3>
<p>No se permiten métodos anidados, es decir, declaración e implementación de métodos dentro de otros métodos. Sí, venga, vale, se puede “solucionar” mediante el uso de <code>delegates</code>, pero eso no es permitir métodos anidados, eso es una chapuza.</p>
<p>Y además, ya para rematar, tampoco se permite declarar estructuras ni clases dentro de métodos. Como está orientado a objetos, pues toda declaración adicional tiene que ir dentro de la clase.</p>
<p><strong>Actualización 2011-12-05</strong>: C y C++ tampoco permiten métodos anidados <a href="http://beosman.org/archivo/2011/informatica/c-sharp.html#comment-22891">como me indican en un comentario</a>. Esto lo puse porque yo los he usado para resolver algún problema, sólo que no recuerdo ni el lenguaje ni el proyecto en el que lo hice. ¿Pascal quizás?</p>
<h3>Atributos</h3>
<p>Los atributos del lenguaje también son otra cosa que está muy bien dentro de un lenguaje. Permiten extender la funcionalidad del compilador, por ejemplo, para hacer compilación condicional, controlar entre diferentes versiones o arquitecturas, marcar elementos como obsoletos… pero, me pregunto, ¿por qué la sintaxis no es coherente con el resto del lenguaje y hay que añadir triquiñuelas del estilo <code>[Conditional("Debug")]</code> al código?</p>
<h3>Conclusión</h3>
<p>Después de despotricar un poco toca una pequeña conclusión:</p>
<p>Si Microsoft tuvo la oportunidad de crear un nuevo lenguaje de programación desde cero, para ellos solos, sin que nadie se pueda meter, sin que nadie le diera lecciones, con la posibilidad de innovar, de mejorar lo que había hasta el momento ¿por qué lo ha hecho tan retorcido e incoherente? Porque sí, en serio, es retorcido. Hasta C++ —que mira que a <a href="http://es.wikipedia.org/wiki/Bjarne_Stroustrup">Bjarne Stroustrup</a> se le fue la olla cuando lo diseñó— es más consistente y coherente que C#. C# parece un batiburrilo de Java, C++ y alguna funcionalidad adicional como los <code>delegates</code> que más que ser un lenguaje nuevo es lo mismo de siempre con otro nombre. Y propietario, claro.</p>
<p>Y, bueno, de la compilación a código intermedio en lugar de a código máquina directamente ya no hablamos. Eso es una decisión que han tomado pero que tampoco es que importe demasiado. Recordemos que esta generación de código es una de las fases de compilación que se puede cambiar sin afectar a la sintaxis.</p>
<p>Concluyendo, a mi, personalmente, no me convence en absoluto. Pero claro, si quieres hacer un proyecto decente para sistemas Windows, no queda otra que hacerlo en C# o pelearte con los punteros en C++.</p>
<p>O usar <a href="http://es.wikipedia.org/wiki/Pascal_(lenguaje_de_programaci%C3%B3n)">Pascal</a> <img src='http://beosman.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  .</p>
<p class="postdata">
<abbr title="Postdata">P.D.</abbr>: Yo, en realidad, soy más del <a href="http://www.d-programming-language.org">lenguaje de programación D</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2011/informatica/c-sharp.html/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Representar un número en binario en C++</title>
		<link>http://beosman.org/archivo/2011/informatica/representar-un-numero-en-binario-en-cpp.html</link>
		<comments>http://beosman.org/archivo/2011/informatica/representar-un-numero-en-binario-en-cpp.html#comments</comments>
		<pubDate>Wed, 16 Nov 2011 19:01:20 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Lenguajes]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=5247</guid>
		<description><![CDATA[Puede que alguna vez en tu vida como desarrollador de software te veas en la necesidad de representar números en su forma binaria. Hay infinidad de algoritmos para ello, por eso no me voy a enrollar mucho. Aquí te muestro tres en C++: La forma sencilla e intuitiva template &#60;typename T&#62; char* ValueToBits(T value) { [...]]]></description>
			<content:encoded><![CDATA[<p>Puede que alguna vez en tu vida como desarrollador de software te veas en la necesidad de representar números en su forma binaria. Hay infinidad de algoritmos para ello, por eso no me voy a enrollar mucho. Aquí te muestro tres en <a href="http://es.wikipedia.org/wiki/C%2B%2B">C++</a>:</p>
<h3>La forma sencilla e intuitiva</h3>
<pre>
template &lt;typename T&gt;
char*
ValueToBits(T value) {
	int length = sizeof(T)*8;
	char* result = new char[length];
	result[length] = '\0';
	for(int i = 0; i &lt; length; i++) {
		result[length-1-i] = (value &#038; (1 &lt;&lt; i) ? '1' : '0');
	}
	return result;
}
</pre>
<p>Este algoritmo es fácilmente adaptable a <a href="http://es.wikipedia.org/wiki/C_(lenguaje_de_programaci%C3%B3n)">C estándar</a>. Basta con quitar la plantilla, sobrecargar esta función con más versiones, una por cada tipo de dato que se quiera convertir, y usar <code><a href="http://en.wikipedia.org/wiki/C_dynamic_memory_allocation">malloc()</a></code> en lugar de <code>new</code>. Y, por supuesto, no hay que olvidarse de liberar la memoria del valor devuelto, o bien con <code>delete[]</code> si usas <code>new</code>, o bien con <code>free()</code> si usas <code>malloc()</code>.</p>
<h3>Usando <code>std::string</code>s</h3>
<p>Este algoritmo es similar al anterior pero usando <code>std::string</code>s, con lo que evitamos el uso de <code>char*</code> y la reserva manual de memoria.</p>
<pre>
#include &lt;string&gt;

using std::string;

template &lt;typename T&gt;
const string
ValueToBits(T value) {
	string result;
	for(int i = 0; i &lt; sizeof(T)*8; i++) {
		result = (value &#038; (1 &lt;&lt; i) ? "1" : "0") + result;
	}
	return result;
}
</pre>
<h3>La forma elegante</h3>
<p>Y ya que estamos en C++, ¿por qué no usar toda la potencia que nos proporciona la <abbr title="Standard Template Library" lang="en"><a href="http://en.wikipedia.org/wiki/Standard_Template_Library">STL</a></abbr>?</p>
<pre>
#include &lt;bitset&gt;

using std::bitset;

template &lt;typename T&gt;
const string
ValueToBits(T value) {
	return bitset&lt;sizeof(T)*8&gt;(value).to_string();
}
</pre>
<p>No me digáis que esta forma no es <strong>muy</strong> elegante <img src='http://beosman.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2011/informatica/representar-un-numero-en-binario-en-cpp.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>¿Qué significan los iconos de inicio de HaikuOS?</title>
		<link>http://beosman.org/archivo/2011/informatica/que-significan-los-iconos-de-inicio-de-haikuos.html</link>
		<comments>http://beosman.org/archivo/2011/informatica/que-significan-los-iconos-de-inicio-de-haikuos.html#comments</comments>
		<pubDate>Fri, 11 Nov 2011 15:03:23 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Sistemas Operativos]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=5207</guid>
		<description><![CDATA[Cuando se inicia el sistema operativo Haiku se presentan una serie de iconos para indicar en qué estado del inicio nos encontramos. Estos iconos significan lo siguiente: Inicializa los módulos del kernel. Monta el sistema de archivos principal en / (rootfs) y monta el sistema de archivos de los dispositivos en /dev (devfs). Inicializa el [...]]]></description>
			<content:encoded><![CDATA[<p class="aligncenter">
<img class="image" src="/uploads/2011/11/haiku-boot-icons.png" alt="Iconos de inicio de HaikuOS" title="Iconos de inicio de HaikuOS" width="650" height="154" />
</p>
<p>Cuando se inicia el <a href="http://haiku-os.org">sistema operativo Haiku</a> se presentan una serie de iconos para indicar en qué estado del inicio nos encontramos. Estos iconos significan lo siguiente:</p>
<ul style="list-style-type: none;list-style-image: none;">
<li style="overflow:auto;"><img style="margin:0 5px 5px 0;" class="floatleft" src="/uploads/2011/11/haiku-boot-atom.png" alt="Haiku boot: Atom" title="Haiku boot: Atom" width="40" height="40" /> Inicializa los módulos del kernel.</li>
<li style="overflow:auto;"><img style="margin:0 5px 5px 0;" class="floatleft" src="/uploads/2011/11/haiku-boot-disk-glass.png" alt="Haiku boot: Disk with magnifier glass" title="Haiku boot: Disk with magnifier glass" width="40" height="40" /> Monta el sistema de archivos principal en <code>/</code> (<code>rootfs</code>) y monta el sistema de archivos de los dispositivos en <code>/dev</code> (<code>devfs</code>).</li>
<li style="overflow:auto;"><img style="margin:0 5px 5px 0;" class="floatleft" src="/uploads/2011/11/haiku-boot-plug-in-card.png" alt="Haiku boot: Plug-in card" title="Haiku boot: Plug-in card" width="40" height="40" /> Inicializa el gestor de dispositivos.</li>
<li style="overflow:auto;"><img style="margin:0 5px 5px 0;" class="floatleft" src="/uploads/2011/11/haiku-boot-disk-leaf.png" alt="Haiku boot: Disk with leaf" title="Haiku boot: Disk with leaf" width="40" height="40" /> Monta el disco del sistema (<code>/boot</code>).</li>
<li style="overflow:auto;"><img style="margin:0 5px 5px 0;" class="floatleft" src="/uploads/2011/11/haiku-boot-chip.png" alt="Haiku boot: Chip" title="Haiku boot: Chip" width="40" height="40" /> Activa los módulos para controlar las características específicas de la CPU.</li>
<li style="overflow:auto;"><img style="margin:0 5px 5px 0;" class="floatleft" src="/uploads/2011/11/haiku-boot-folder.png" alt="Haiku boot: Folder" title="Haiku boot: Folder" width="40" height="40" /> Finalización del inicio de los subsistemas (que cargan módulos del disco principal en <code>/boot</code>).</li>
<li style="overflow:auto;"><img style="margin:0 5px 5px 0;" class="floatleft" src="http://beosman.org/uploads/2011/11/haiku-boot-rocket.png" alt="Haiku boot: Rocket" title="Haiku boot: Rocket" width="40" height="40" /> Carga en memoria e inicia el <em>script</em> (<code>BootScript</code>) que carga los servidores de inicio como el <code>app_server</code> o el <code>input_server</code>.</li>
</ul>
<p>En una máquina virtual con <a href="http://es.wikipedia.org/wiki/VirtualBox">VirtualBox</a> (en un equipo moderno, todo hay que decirlo) tarda algo menos de 10 segundos en iniciar el sistema. Supongo que en hardware real tardará menos <img src='http://beosman.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2011/informatica/que-significan-los-iconos-de-inicio-de-haikuos.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Las tres leyes del software</title>
		<link>http://beosman.org/archivo/2011/citas/las-tres-leyes-del-software.html</link>
		<comments>http://beosman.org/archivo/2011/citas/las-tres-leyes-del-software.html#comments</comments>
		<pubDate>Mon, 07 Nov 2011 19:07:25 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Citas y frases]]></category>
		<category><![CDATA[Humor]]></category>
		<category><![CDATA[Informática]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=5180</guid>
		<description><![CDATA[Ningún programa se arrancará sin ser necesario y sin ser requerido por el usuario. Ningún programa recopilará, enviará o buscará datos por la jeta, sin ser parte de una tarea solicitada por el usuario. Todo programa (o componente de software) debe poder desinstalarse sin dejar rastro a la voz de ya. Propuestas por Supermon, como [...]]]></description>
			<content:encoded><![CDATA[<blockquote class="small">
<ol>
<li>Ningún programa se arrancará sin ser necesario y sin ser requerido por el usuario.</li>
<li>Ningún programa recopilará, enviará o buscará datos por la jeta, sin ser parte de una tarea solicitada por el usuario.</li>
<li>Todo programa (o componente de software) debe poder desinstalarse sin dejar rastro a la voz de ya.</li>
</ol>
</blockquote>
<p class="alignright">
<a href="http://halondisparado.com/?p=3874">Propuestas por Supermon</a>, como homólogas a <a href="/archivo/2010/citas/las-tres-leyes-de-la-robotica.html">las tres leyes de la robótica</a>, en <a href="http://halondisparado.com">Halón Disparado</a>.
</p>
<p class="alignright">
Y con las que estoy totalmente de acuerdo. Además, se podría añadir la de <em>«Todo programa será software libre y su código liberado»</em>, <a href="http://www.meneame.net/story/pardillo-de-asimov/00011">como comentan en Menéame</a>, aunque esa quizás ya sería para nota <img src='http://beosman.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2011/citas/las-tres-leyes-del-software.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hal o Win</title>
		<link>http://beosman.org/archivo/2011/informatica/hal-o-win.html</link>
		<comments>http://beosman.org/archivo/2011/informatica/hal-o-win.html#comments</comments>
		<pubDate>Mon, 31 Oct 2011 13:20:01 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Geek/Friki]]></category>
		<category><![CDATA[Humor]]></category>
		<category><![CDATA[Informática]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=5151</guid>
		<description><![CDATA[Hoy es Halloween; y qué mejor que esta imagen que nada tiene que ver con ello pero que tiene un juego de palabras de los mejores que he visto últimamente. Grande, muy grande. Desde Neoon. P.D.: Por cierto, la fiesta de Halloween es una fiesta que tiene su origen en la fiesta celta del Samhain [...]]]></description>
			<content:encoded><![CDATA[<p class="aligncenter">
<a href="http://www.neoon.es/halowin/"><img class="image" src="http://beosman.org/uploads/2011/10/hal_o_win-650x466.jpg" alt="Hal o Win" title="Hal o Win" width="650" height="466" /></a>
</p>
<p>Hoy es <a href="http://es.wikipedia.org/wiki/Halloween"><em>Halloween</em></a>; y qué mejor que esta imagen que nada tiene que ver con ello pero que tiene un juego de palabras de los mejores que he visto últimamente. Grande, muy grande. <a href="http://www.neoon.es/halowin/">Desde Neoon</a>.</p>
<p class="postdata">
<acronym title="Postdata">P.D.</acronym>: Por cierto, la fiesta de <em>Halloween</em> es una fiesta que tiene su origen en la fiesta celta del <a href="http://es.wikipedia.org/wiki/Samhain">Samhain</a> y en la fiesta cristiana de <a href="http://es.wikipedia.org/wiki/D%C3%ADa_de_todos_los_santos">Todos los Santos</a>. Por si a alguno se le ocurre decir a estas alturas esto de <em>&#8220;yo no celebraré ninguna fiesta traída de EE.UU.&#8221;</em>. Por favor, señores, que cada uno celebre lo que quiera <img src='http://beosman.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2011/informatica/hal-o-win.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Implementación básica de soporte de hilos (threads) usando programación orientada a objetos con C++</title>
		<link>http://beosman.org/archivo/2011/informatica/implementacion-basica-de-soporte-de-hilos-threads-usando-programacion-orientada-a-objetos-con-cpp.html</link>
		<comments>http://beosman.org/archivo/2011/informatica/implementacion-basica-de-soporte-de-hilos-threads-usando-programacion-orientada-a-objetos-con-cpp.html#comments</comments>
		<pubDate>Mon, 24 Oct 2011 18:01:56 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Informática]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=5067</guid>
		<description><![CDATA[Después de este título tan largo viene una pregunta: ¿conocéis alguna implementación de hilos (threads) orientada a objetos en C++ que sea medianamente decente? Si la respuesta es sí, genial, decídmelo en los comentarios para echarle un vistazo. Si la respuesta es no, no hagáis como yo y os dediquéis a reinventar la rueda y [...]]]></description>
			<content:encoded><![CDATA[<p>Después de este título tan largo viene una pregunta: ¿conocéis alguna implementación de <a href="http://es.wikipedia.org/wiki/Hilo_de_ejecuci%C3%B3n">hilos (threads)</a> <a href="http://es.wikipedia.org/wiki/Programaci%C3%B3n_orientada_a_objetos">orientada a objetos</a> en <a href="http://es.wikipedia.org/wiki/C%2B%2B">C++</a> que sea medianamente decente?</p>
<p>Si la respuesta es sí, genial, decídmelo en los comentarios para echarle un vistazo.</p>
<p>Si la respuesta es no, no hagáis como yo y os dediquéis a reinventar la rueda y usad la <a href="http://www.boost.org/doc/libs/1_47_0/doc/html/thread.html">implementación de hilos</a> de la <a href="http://www.boost.org/">librería <code>Boost</code></a>. En serio. Es más, usad <code>Boost</code> para todo lo que podáis porque tiene infinidad de cosas muy buenas y muy útiles ya probadas. De hecho, varias cosas de esta librería fueron incluidas en el último estándar de C++, <a href="http://es.wikipedia.org/wiki/C%2B%2B11">C++11</a> (antes conocido como C++0x).</p>
<p>Pero, en caso de que os guste investigar y queráis implementar vuestra propia librería de gestión de hilos mediante programación orientada a objetos en C++, aquí tenéis un ejemplo de lo que a mi se me ha ocurrido (y que, de momento, funciona, claro <img src='http://beosman.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> ). Y es un gran ladrillo, avisados estáis.</p>
<h3>Lo primero que hay que saber</h3>
<p>Lo primero que —de forma resumida— hay que saber es que la implementación de los hilos depende de cada sistema, aunque hay una especificación <a href="http://es.wikipedia.org/wiki/POSIX"><acronym title="Portable Operating System Interface for UNIX" lang="en">POSIX</acronym></a> llamada <code><a href="http://en.wikipedia.org/wiki/Pthreads">pthreads</a></code> que tienen implementada la mayoría de los sistemas operativos.</p>
<p>Esta implementación generalmente está hecha en <a href="http://es.wikipedia.org/wiki/C_(lenguaje_de_programaci%C3%B3n)">C</a> mediante <a href="http://es.wikipedia.org/wiki/Programaci%C3%B3n_estructurada">programación estructurada</a>, con lo que tenemos un conjunto de funciones a la que se le pasan parámetros para controlar todo el funcionamiento de los hilos.</p>
<p>Algunas de estas funciones son la de crear e iniciar el hilo —cuyo parámetro principal es un puntero a la función que dicho hilo tiene que ejecutar—, parar el hilo, esperar a que termine dicho hilo, etc.</p>
<p>De lo que trata esta entrada es de encapsular esta funcionalidad en clases para controlar los hilos mediante programación orientada a objetos y así tener un <a href="http://es.wikipedia.org/wiki/Interfaz_de_programaci%C3%B3n_de_aplicaciones"><acronym title="Application Programming Interface" lang="en">API</acronym></a> más consistente, más abstracta y, sobre todo, más moderna. Y aquí es donde los defensores a ultranza de la programación estructurada empiezan a gritar…</p>
<p>Bueno, yo creo que cada cosa está para lo que está y la programación estructurada está muy bien para programar <em><a href="http://es.wikipedia.org/wiki/N%C3%BAcleo_(inform%C3%A1tica)">kernels</a></em>, pero cuando se trata de programar aplicaciones de usuario por parte de un desarrollador de este tipo de aplicaciones (no de sistemas) siempre es mejor facilitarle la tarea a dicho desarrollador. Y con la <abbr title="Programación Orientada a Objetos">POO</abbr> se consigue.</p>
<h3>La idea principal</h3>
<p>Como comenté arriba, la idea principal es encapsular las funciones de C de gestión de hilos en clases y métodos de C++. Simple y sencillo ¿no? Para ello, diseñaremos las clases necesarias para incluirlas. En principio sólo una, la clase <code>Hilo</code>; o, mejor, la clase <code>Thread</code>, porque me gusta más programar en inglés, por eso de que si compartes tu código llegarás a más gente en este idioma, nos guste o no.</p>
<p>Pero, antes de nada, hay que solucionar un problema importante: a la función de creación del hilo hay que pasarle como parámetro un puntero a la función a ejecutar, pero las clases en C++ no tienen <a href="http://es.wikipedia.org/wiki/Funci%C3%B3n_(programaci%C3%B3n)">funciones</a> sino que tienen <a href="http://es.wikipedia.org/wiki/M%C3%A9todo_(inform%C3%A1tica)">métodos</a>. ¿Y cuál es la diferencia? La principal diferencia es que en el cuerpo de las funciones se tienen los parámetros que se declaran en su definición mientras que en los métodos, además de los parámetros definidos, se tiene un parámetro oculto llamado, generalmente, <code>this</code> (en C++, <code>self</code> en Delphi…) que es un puntero a la instancia del objeto que llama a dicho método.</p>
<p>Y, obviamente, no se puede pasar un puntero a un método a una función que requiere como parámetro un puntero a una función.</p>
<p>La solución está en pasar un método estático de nuestra clase <code>Thread</code> a esta función pasándole como parámetro (visible, no oculto) el puntero a la instancia de nuestra clase <code>Thread</code>. Luego veremos un ejemplo de implementación.</p>
<p>Después de abordar este problema, lo siguiente es encapsular las funciones de gestión de hilos. Aquí, la verdad, no es más que tener un método en nuestra clase por cada función de gestión de hilos que nos interese gestionar. Simple, la verdad.</p>
<h3>Lo que hay que ejecutar</h3>
<p>El problema de pasar un puntero a una función en lugar de un método como parámetro de la función de creación del hilo está solucionado. Ahora nos queda qué es lo que hay que ejecutar. Y también es sencillo. Se puede declarar un método en nuestra clase <code>Thread</code> llamado <code>execute()</code> que sea el método estándar que siempre ejecute nuestra clase, aunque una solución más elegante (que no más eficiente, sólo estamos hablando de elegancia) sería implementar el operador <code>()</code> (llamada de función) y ser ese el que ejecute nuestro hilo. Repito, cuestión de elegancia, nada más.</p>
<p>Pero, aquí llegamos al segundo problema: ¿qué pasa si quiero ejecutar código diferente sin tener que modificar mi clase <code>Thread</code> cada vez?</p>
<p>La primera solución que se nos ocurre, por obvia, es la herencia. Declaramos la función <code>execute()</code> (o el operador <code>()</code>) como <a href="http://es.wikipedia.org/wiki/Funci%C3%B3n_virtual">virtual</a> y hacemos clases derivadas donde lo implementamos. Sin duda, una muy buena solución.</p>
<p>Pero, ¿y si, por cualquier razón, queremos o necesitamos que nuestro hilo pueda ejecutar cualquier método de cualquier otra clase —siempre y cuando cumpla con una definición de parámetros común—?</p>
<p>Aquí es donde nuestra primera planificación de una sola clase <code>Thread</code> puede no ser suficiente.</p>
<h3>La implementación</h3>
<p>La solución que se me ocurrió pasa por tener dos clases. La primera, una clase <code>Thread</code> como la del texto anterior donde estén declarados e implementados todos los métodos que vamos a usar para gestionar el hilo, teniendo declarado el método <code>execute()</code> como virtual para que se puedan heredar más clases que implementen dicho método. A esta clase la llamaremos <code>AbstractThread</code> (por no permitir tener instancias de la misma y obligar a que sea derivada).</p>
<p>La otra clase sería una clase que hereda de <code>AbstractThread</code> a la que, ahora sí, llamaremos <code>Thread</code>, pero que tiene la peculiaridad de que va a usar <a href="http://en.wikipedia.org/wiki/Template_(programming)">plantillas de C++</a>, también conocidas como <em>templates</em>, para indicar qué método de qué clase se va a ejecutar en el hilo.</p>
<p>Al final, contaremos con dos clases: <code>AbstractThread</code>, que es derivable y que es el método <code>execute()</code> el que ejecutará el hilo, y <code>Thread</code>, que está basada en plantillas y será a través de ellas y de su constructor desde donde indicaremos el método a ejecutar y la clase a la que pertenece.</p>
<h3>El pseudocódigo de la interfaz de las clases</h3>
<p>En este pequeño <em><a href="http://www.wordreference.com/es/translation.asp?tranword=snippet">snippet</a></em> de código muestro la interfaz (que no la implementación) básica de las dos clases antes mencionadas. En un principio la clase <code>AbstractThread</code> de la que heredan las demás implementando el método <code>execute()</code> y luego la clase <code>Thread</code> usando plantillas.</p>
<h4>Clase <code>AbstractThread</code></h4>
<pre>

typedef int thread_id;

class AbstractThread {
  private:

    /**
     * Función estática que es la que se le pasa a la función
     * 'pthread_create(...)' para que ejecute. El parámetro
     * 'void* arg' será la instancia de la clase cuya función
     * 'execute()' hay que ejecutar. Un ejemplo de implementación
     * está en el siguiente código.
     */
    static void* thread_entry(void* arg) {
      // Código de ejemplo:
      AbstractThread* thread = reinterpret_cast&lt;AbstractThread*&gt;(arg);
      thread-&gt;execute();
      return NULL;
    }

  protected:
    /**
     * Función virtual pura que tienen que implementar las clases
     * derivadas y será la que ejecute el hilo.
     */
    virtual void execute() = 0;

  public:
    /**
     * Constructor de la clase.
     */
    AbstractThread();

    /**
     * Destructor de la clase.
     */
    virtual ~AbstractThread();

    /**
     * Devuelve el identificador del hilo (el 'handle').
     */
    thread_id getId();

    /**
     * Inicia el hilo.
     */
    virtual bool start();

    /**
     * Para el hilo.
     */
    virtual bool stop();

    /**
     * Indica si el hilo se está ejecutando o no.
     */
    bool isRunning();

    /**
     * Pide al hilo que pare de ejecutarse. Este es un método
     * de parada conde la implementación de 'execute()' para
     * de forma cooperativa (sin forzar la parada).
     */
    virtual bool requestStop();

    /**
     * Bloquea el hilo que llama a este método hasta que el
     * hilo en cuestión finaliza (espera la finalización del
     * hilo).
     */
    virtual bool wait();

    /**
     * Similar a 'wait()' pero con un tiempo de espera. Si el
     * hilo no finaliza el dicho tiempo de espera, devuelve
     * un error.
     */
    virtual bool timedWait(int microseconds);

    /**
     * Finaliza el hilo de forma abrupta.
     */
    virtual bool kill(int signum);

    /**
     * Devuelve la prioridad del hilo.
     */
    int  priority();

    /**
     * Fija la prioridad del hilo.
     */
    void  priority(int prio);

    /**
     * Función estática que devuelve el identificador
     * del hilo que llama a esta función.
     */
    static thread_id getCurrentThreadId();

    /**
     * Función estática que hace que el hilo que llama a
     * esta función deje de ejecutarse hasta que vuelva
     * a ser planificado por el kernel.
     */
    static void yield();
};
</pre>
<h4>Clase <code>Thread</code> usando plantillas</h4>
<pre>

template &lt;class Worker&gt;
class Thread : public AbstractThread {
  public:
    /**
     * Tipo de dato nuevo que representa la definición del método
     * a ejecutar en este hilo.
     */
    typedef void (Worker::*WorkerMethod)(const Thread&lt;Worker&gt;* thread);

  private:

    /**
     * Puntero a la instancia de la clase cuyo método hay que
     * ejecutar. En caso de que no se pase ninguna instancia en
     * el constructor, se creará (y destruirá) internamente.
     */
    Worker*      fWorker;

    /**
     * Puntero al método a ejecutar dentro de la clase Worker.
     */
    WorkerMethod fMethod;

  protected:

    /**
     * Método heredado de la clase AbstractThread que se implementa
     * para ejecutar el método del Worker en el hilo.
     */
    virtual void execute() {
      if(fWorker != NULL &amp;&amp; fMethod != NULL) {
        (fWorker-&gt;*fMethod)(this);
      }
    }
  public:

    /**
     * Constructor de la clase donde se le pasa como parámetro
     * un puntero al método a ejecutar. Como no se pasa instancia
     * de la clase a la que pertenece dicho método, se crea una
     * internamente (y se destruye al final).
     */
    Thread(WorkerMethod method = &#038;Worker::execute);

    /**
     * Constructor de la clase donde se le pasa una referencia a
     * una instancia de la clase de donde hay que ejecutar el método
     * y un puntero al método a ejecutar.
     */
    Thread(Worker&#038; worker, WorkerMethod method = &#038;Worker::execute);

    /**
     * Constructor de la clase donde se le pasa un puntero a
     * una instancia de la clase de donde hay que ejecutar el método
     * y un puntero al método a ejecutar.
     */
    Thread(Worker* worker, WorkerMethod method = &#038;Worker::execute);
};
</pre>
<p>El resto de métodos de la clase <code>Thread</code> serán los mismos que en la clase <code>AbstractThread</code> por lo que no hace falta volver a implementarlos.</p>
<h3>Un ejemplo de uso</h3>
<p>Un ejemplo del uso de la clase <code>AbstractThread</code> sería la propia clase <code>Thread</code>, donde basta con implementar el método virtual puro <code>execute()</code> para que sea ese código el que se ejecute en el hilo.</p>
<p>Un ejemplo de uso de la clase <code>Thread</code> podría ser:</p>
<pre>

#include &lt;iostream&gt;

using namespace std;

class Thread;

class MiClase {
  public:
    void ejecutar(const Thread&lt;MiClase&gt;* thread) {
      // Cualquier código a ejecutar en el hilo, por ejemplo:
      int counter = 5;
      while(counter-- &gt; 0) {
        cout &lt;&lt; "Hola mundo." &lt;&lt; endl;
        sleep(1);
      }
    }
};

MiClase mi_clase* = new MiClase();
Thread&lt;MiClase&gt;* thr = new Thread&lt;MiClase&gt;(mi_clase,&amp;MiClase::ejecutar);

thr-&gt;start();
thr-&gt;wait();

delete thr;
delete mi_clase;
</pre>
<h3>Algunas notas acerca del código</h3>
<p>En los métodos de las clases <code>AbastractThread</code> y <code>Thread</code> se usan valores de retorno para saber si se han ejecutado correctamente o no. Esta decisión está de mano del desarrollador pudiendo usar valores <a href="http://es.wikipedia.org/wiki/Booleano">booleanos</a>, números enteros representando códigos de error (usando, por ejemplo, un <code><a href="http://en.wikipedia.org/wiki/Enumerated_type">enum</a></code>) o <a href="http://es.wikipedia.org/wiki/Manejo_de_excepciones">excepciones</a>.</p>
<p>Personalmente, aunque la primera implementación que hice fue devolviendo un tipo de dato enumerado representando códigos de error, creo que la mejor forma de hacerlo es usar <a href="http://www.parashift.com/c++-faq-lite/exceptions.html">excepciones debido a que tienen sus ventajas respecto al uso de valores de retorno</a>.</p>
<h3>Clases adicionales necesarias</h3>
<p>El uso de hilos en las aplicaciones, además de tener que gestionar correctamente la creación de los mismos, implica, al menos, tres cosas más: </p>
<ol>
<li>Evitar el acceso a la misma zona de memoria de forma simultánea por dos o más hilos.</li>
<li>Sincronizar el orden de acceso de dos o más hilos a un recurso compartido.</li>
<li>Comunicación entre diferentes hilos.</li>
</ol>
<p>Es por esto que es necesario implementar otras clases (por seguir con el modelo de programación orientada a objetos) con el fin de tener dichos mecanismos.</p>
<p>Por ejemplo, para envitar el acceso a la misma memoria al mismo tiempo habría que implementar una clase <code><a href="http://es.wikipedia.org/wiki/Mutex">Mutex</a></code> (<em>mutex</em> viene de <em><strong>mut</strong>ual <strong>ex</strong>clusion</em>) que evita, precisamente, este supuesto, bloqueando el acceso a ciertas zonas de memoria a todos los hilos en caso de que uno de ellos ya esté en dicha zona.</p>
<p>Además, para la sincronización se debería implementar una clase <a href="http://es.wikipedia.org/wiki/Sem%C3%A1foro_(programaci%C3%B3n)">Semaphore</a> que sirve para indicar el orden en que los hilos acceden a los recursos. Además, también podría servir para pasar información (básica) entre hilos.</p>
<p>Y, finalmente, habría que implementar las clases de comunicación teniendo en cuenta los diferentes métodos que se pueden usar como, por ejemplo, la <a href="http://en.wikipedia.org/wiki/Shared_memory">memoria compartida</a>, <a href="http://en.wikipedia.org/wiki/Message_queue">colas de mensajes</a>, <a href="http://en.wikipedia.org/wiki/Signal_%28computing%29">señales</a>, <em><a href="http://es.wikipedia.org/wiki/Socket_de_Internet">sockets</a></em>, <a href="http://en.wikipedia.org/wiki/Named_pipe">colas <acronym title="First In First Out" lang="en">FIFO</acronym></a>…</p>
<h3>Conclusión</h3>
<p>Si estáis implementando aplicaciones en C++ que hagan uso de hilos, como dije más arriba, no os compliquéis la vida y usad la librería <code>Boost</code>. Bien implementada, con una buena interfaz y muy, muy probada.</p>
<p>Pero si, por cualquier motivo, tenéis que implementar vuestra propia librería, bien sea porque queréis aprender o porque no queréis que vuestro programa dependa de otras librerías o porque vuestro jefe os lo ha dicho, podéis probar, si queréis, esta idea que he expuesto aquí y, como no, podéis ponerlo en los comentarios… por compartir más que nada <img src='http://beosman.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</p>
<p>Y tened en cuenta que esto es <strong>muy</strong> mejorable, pero la implementación que he hecho funciona bastante bien y es la que estoy usando actualmente. Espero que os sirva <img src='http://beosman.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2011/informatica/implementacion-basica-de-soporte-de-hilos-threads-usando-programacion-orientada-a-objetos-con-cpp.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Tipografía &#8216;Ubuntu Monospace&#8217;</title>
		<link>http://beosman.org/archivo/2011/informatica/tipografia-ubuntu-monospace.html</link>
		<comments>http://beosman.org/archivo/2011/informatica/tipografia-ubuntu-monospace.html#comments</comments>
		<pubDate>Tue, 04 Oct 2011 12:59:47 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Informática]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=4971</guid>
		<description><![CDATA[¿Os acordáis de la tipografía Inconsolata que había puesto por aquí como buena fuente de ancho fijo para los editores de desarrollo? Pues he descubierto otra que, si no es tan buena, le está muy cerca. Aunque, bueno, quizás sea más por gustos que por &#8220;más buena&#8221; o &#8220;menos buena&#8221;. Esta es la tipografía &#8216;Ubuntu [...]]]></description>
			<content:encoded><![CDATA[<p>¿Os acordáis de la <a href="/archivo/2010/informatica/tipografia-inconsolata.html">tipografía Inconsolata</a> que había puesto por aquí como buena fuente de ancho fijo para los editores de desarrollo? Pues he descubierto otra que, si no es tan buena, le está muy cerca. Aunque, bueno, quizás sea más por gustos que por <em>&#8220;más buena&#8221;</em> o <em>&#8220;menos buena&#8221;</em>.</p>
<p>Esta es la tipografía &#8216;<a href="http://design.canonical.com/2010/11/the-monospace-is-coming/">Ubuntu Monospace</a>&#8216;, de la <a href="http://font.ubuntu.com/">familia de tipografías de Ubuntu</a> (que se pueden <a href="http://font.ubuntu.com/download/ubuntu-font-family-0.80.zip">descargar gratuitamente</a> y que valen para cualquier sistema operativo que soporte fuentes <a href="http://es.wikipedia.org/wiki/TrueType">TrueType</a>). Y aquí tenemos dos muestras:</p>
<p><a href="/uploads/2011/10/gnome-terminal-ubuntu-monospace-font.jpg"><img src="/uploads/2011/10/gnome-terminal-ubuntu-monospace-font-300x205.jpg" alt="Muestra de la tipografía Ubuntu Monospace en el terminal de Gnome" title="Muestra de la tipografía Ubuntu Monospace en el terminal de Gnome" width="300" height="205" class="image" /></a> <a href="/uploads/2011/10/eclipse-ubuntu-monospace-font.jpg"><img src="http://beosman.org/uploads/2011/10/eclipse-ubuntu-monospace-font-300x205.jpg" alt="Muestra de la tipografía Ubuntu Monospace en Eclipse" title="Muestra de la tipografía Ubuntu Monospace en Eclipse" width="300" height="205" class="image" /></a></p>
<p>Y estas muestras se pueden comparar con la del <a href="/uploads/2010/08/gnome-terminal-inconsolata-font.jpg">terminal con Inconsolata</a> y con la de <a href="/uploads/2010/08/eclipse-inconsolata-font.jpg">Eclipse con Inconsolata</a>.</p>
<p>Y a vosotros ¿cuál os gusta más? ¿Cuál usáis para desarrollar?</p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2011/informatica/tipografia-ubuntu-monospace.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Mejorando el Explorador de Windows (o no) y otros menesteres</title>
		<link>http://beosman.org/archivo/2011/informatica/mejorando-el-explorador-de-windows-o-no-y-otros-menesteres.html</link>
		<comments>http://beosman.org/archivo/2011/informatica/mejorando-el-explorador-de-windows-o-no-y-otros-menesteres.html#comments</comments>
		<pubDate>Tue, 30 Aug 2011 13:02:53 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Sistemas Operativos]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=4821</guid>
		<description><![CDATA[Los chicos de Microsoft se lo curran y han hecho un estudio donde se muestra el uso que los usuarios le damos al Explorador de Windows, esto es, cómo accedemos a las acciones para el tratamiento de archivos &#8212;mediante menús, iconos, teclas de acceso rápido, etc.&#8212; con el fin de &#8220;optimizar&#8221; estos componentes para mejorar [...]]]></description>
			<content:encoded><![CDATA[<p>Los chicos de <a href="http://es.wikipedia.org/wiki/Microsoft">Microsoft</a> se lo curran y <a href="http://blogs.msdn.com/b/b8/archive/2011/08/26/improvements-in-windows-explorer.aspx">han hecho un estudio</a> donde se muestra el uso que los usuarios le damos al <a href="http://es.wikipedia.org/wiki/Explorador_de_Windows">Explorador de Windows</a>, esto es, cómo accedemos a las acciones para el tratamiento de archivos &mdash;mediante menús, iconos, teclas de acceso rápido, <abbr title="etcétera">etc.</abbr>&mdash; con el fin de <em>&#8220;optimizar&#8221;</em> estos componentes para mejorar la experiencia de usuario.</p>
<p>Conforme a este estudio, el nuevo rediseño del Explorador&#8230; bueno, deja un poco que desear, teniendo en cuenta que han creado una barra de herramientas mucho más grande e intrusiva que las anteriores con acciones que los usuarios apenas usan (menos del <span class="nowrap">1 %</span> de las veces se usa la opción de la barra de herramientas en detrimento de otras opciones como el menú contextual o una tecla de acceso rápido).</p>
<p>Pero eso no es lo que quiero destacar aquí. Lo que quiero destacar es este gráfico:</p>
<p class="image aligncenter">
<img class="image" src="http://beosman.org/uploads/2011/08/command-entrypoint.png" alt="Punto de entrada de los comandos" title="Punto de entrada de los comandos" width="578" height="397" class="alignnone size-full wp-image-4825" /><br />
Punto de entrada de los comandos en el Explorador de Windows
</p>
<p>Es decir, según este gráfico, la mayoría de las acciones que un usuario hace en el Explorador de Windows &mdash;esto es, tratamiento de archivos&mdash; es mediante el menú contextual; luego mediante una combinación de teclas (teclas rápidas); lo siguiente es el uso de la barra de herramientas; y, finalmente, mediante el menú normal de toda la vida.</p>
<p>De este gráfico mi conclusión es que la barra de menús es un punto de entrada de comandos superfluo que, en cuanto estás acostumbrado a usar el software, obvias en favor de los menús contextuales y de las teclas de acceso rápido. Es decir, a mi parecer, la barra de menús sobraría en <strong>muchas</strong> interfaces de software.</p>
<p>Entonces, me pregunto ¿por qué los chicos de <a href="http://es.wikipedia.org/wiki/Apple">Apple</a> se empeñan en mantener un <strong>menú global</strong> que ocupa una parte <strong>muy</strong> importante del escritorio y que, según el estudio de Microsoft, apenas se usaría?</p>
<p>Por poner un sólo ejemplo, esa zona de la pantalla se usa en <a href="http://es.wikipedia.org/wiki/Google_Chrome">Google Chrome</a> y en <a href="http://es.wikipedia.org/wiki/Mozilla_Firefox">Mozilla Firefox</a> para acceder más rápidamente a las pestañas teniendo en cuenta que el ratón <em>&#8220;no se sale&#8221;</em> del borde de la pantalla.</p>
<p>Y esto ocurre con todas las interfaces que copian descaradamente la interfaz de <a href="http://es.wikipedia.org/wiki/Mac_OS_X">Mac OS X</a> (léase <a href="http://es.wikipedia.org/wiki/GNOME_Shell">Gnome Shell</a>, <a href="http://es.wikipedia.org/wiki/Unity_(entorno_de_escritorio)">Unity</a>&#8230;). Vamos, para mí es perder espacio y, sobre todo, funcionalidad y usabilidad. Pero no tengáis miedo de que en Mac OS X (y demás) lo quiten alguna vez (aunque sea por configuración). Ante todo hay que tener señas de identidad. Aunque no sean usables.</p>
<p class="postdata">
<abbr title="Postdata">P.D.</abbr>: Tengo en mente escribir algún día sobre las disposiciones de los elementos de los escritorio informáticos &mdash;esquinas, bordes&#8230;&mdash; y la tendencia de hoy en día. El problema es la falta de tiempo&#8230; y ganas <img src='http://beosman.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2011/informatica/mejorando-el-explorador-de-windows-o-no-y-otros-menesteres.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Llamadas encadenadas en C++</title>
		<link>http://beosman.org/archivo/2011/informatica/llamadas-encadenadas-en-c.html</link>
		<comments>http://beosman.org/archivo/2011/informatica/llamadas-encadenadas-en-c.html#comments</comments>
		<pubDate>Wed, 24 Aug 2011 17:36:38 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Lenguajes]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=4772</guid>
		<description><![CDATA[Esta entrada llevaba tiempo en el tintero, por eso de tener algo de tiempo libre en vacaciones para dedicarlo a leer y elucubrar soluciones. Por ejemplo, aquí tenemos una prueba de concepto para tener la misma funcionalidad que el operador &#60;&#60; de C++ pero usando llamadas encadenas. Y hace (casi) lo mismo: puede enviar a [...]]]></description>
			<content:encoded><![CDATA[<p>Esta entrada llevaba tiempo en el tintero, por eso de tener algo de tiempo libre en vacaciones para dedicarlo a leer y elucubrar soluciones.</p>
<p>Por ejemplo, aquí tenemos una prueba de concepto para tener la misma funcionalidad que el operador <code>&lt;&lt;</code> de <a href="http://es.wikipedia.org/wiki/C%2B%2B">C++</a> pero usando llamadas encadenas. Y hace (casi) lo mismo: puede enviar a la <a href="http://es.wikipedia.org/wiki/Salida_est%C3%A1ndar">salida estándar</a> cualquier tipo de variable, incluyendo cadenas, <a href="http://es.wikipedia.org/wiki/N%C3%BAmero_entero">números enteros</a>, <a href="http://es.wikipedia.org/wiki/N%C3%BAmero_real">números reales</a> y <a href="http://es.wikipedia.org/wiki/Booleano">booleanos</a>, sólo que con un formato de llamada diferente.</p>
<p>La implementación de la clase base, pudiendo extenderla lo que se quiera, es la siguiente:</p>
<div class="source">
<p><span class="directive">#include</span> &lt;iostream&gt;<br />
<span class="directive">#include</span> &lt;string&gt;<br />
<span class="directive">#include</span> &lt;sstream&gt;<br />
&nbsp;</p>
<p><span class="keyword">using</span> std::cout;<br />
<span class="keyword">using</span> std::endl;<br />
<span class="keyword">using</span> std::flush;<br />
<span class="keyword">using</span> std::string;<br />
<span class="keyword">using</span> std::stringstream;<br />
&nbsp;</p>
<p><span class="keyword">class</span> Stdout {<br />
  <span class="keyword">private</span>:<br />
    stringstream _buffer;<br />
  <span class="keyword">public</span>:<br />
    Stdout() : _buffer() {}<br />
    ~Stdout() {}<br />
    <span class="keyword">void</span> clear() {<br />
      _buffer.str(<span class="string">&quot;&quot;</span>);<br />
    }<br />
    Stdout&#038; <span class="keyword">operator</span> () (<span class="keyword">const char</span> c) {<br />
      string s;<br />
      s += c;<br />
      _buffer &lt;&lt; s;<br />
      <span class="keyword">return</span> *<span class="keyword">this</span>;<br />
    }<br />
    Stdout&#038; <span class="keyword">operator</span> () (<span class="keyword">const char</span>* text) {<br />
      _buffer &lt;&lt; text;<br />
      <span class="keyword">return</span> *<span class="keyword">this</span>;<br />
    }<br />
    Stdout&#038; <span class="keyword">operator</span> () (<span class="keyword">const</span> string text) {<br />
      _buffer &lt;&lt; text;<br />
      <span class="keyword">return</span> *<span class="keyword">this</span>;<br />
    }<br />
    Stdout&#038; <span class="keyword">operator</span> () (<span class="keyword">const int</span> i) {<br />
      _buffer &lt;&lt; i;<br />
      <span class="keyword">return</span> *<span class="keyword">this</span>;<br />
    }<br />
    Stdout&#038; <span class="keyword">operator</span> () (<span class="keyword">const float</span> f) {<br />
      _buffer &lt;&lt; f;<br />
      <span class="keyword">return</span> *<span class="keyword">this</span>;<br />
    }<br />
    Stdout&#038; <span class="keyword">operator</span> () (<span class="keyword">const double</span> d) {<br />
      _buffer &lt;&lt; d;<br />
      <span class="keyword">return</span> *<span class="keyword">this</span>;<br />
    }<br />
    Stdout&#038; <span class="keyword">operator</span> () (<span class="keyword">const bool</span> b) {<br />
      _buffer &lt;&lt; (b ? <span class="string">&quot;true&quot;</span> : <span class="string">&quot;false&quot;</span>);<br />
      <span class="keyword">return</span> *<span class="keyword">this</span>;<br />
    }<br />
    <span class="keyword">void</span> flush() {<br />
      cout &lt;&lt; _buffer.str() &lt;&lt; ::flush;<br />
      clear();<br />
    }<br />
    <span class="keyword">void</span> endl() {<br />
      cout &lt;&lt; _buffer.str() &lt;&lt; ::endl;<br />
      clear();<br />
    }<br />
};</p>
</div>
<p>Y un ejemplo de funcionamiento sería:</p>
<div class="source">
<p><span class="keyword">int</span><br />
main() {<br />
  Stdout stdout;<br />
  stdout(<span class="string">&quot;Llamadas encadenadas: enteros: &quot;</span>)(42)(<span class="string">&apos;;&apos;</span>)(<span class="string">&quot; reales: &quot;</span>)(25.4)(<span class="string">&apos;;&apos;</span>)(<span class="string">&quot; y booleanos: &quot;</span>)(<span class="keyword">false</span>)(<span class="string">&apos;.&apos;</span>).endl();<br />
  <span class="keyword">return</span> 0;<br />
}</p>
</div>
<p>Siendo la salida:</p>
<p class="terminal">
$ make &amp;&amp; ./test<br />
Llamadas encadenadas: enteros: 42; reales: 25.4; y booleanos: false.<br />
$
</p>
<p>No tiene la misma funcionalidad que el operador <code>&lt;&lt;</code> porque, entre otras cosas, si se quiere añadir otro elemento imprimible habría que derivar la clase, mientras que con el operador <code>&lt;&lt;</code> bastaría con sobrecargarlo. Pero no me digáis que no es elegante ¿eh? <img src='http://beosman.org/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> .</p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2011/informatica/llamadas-encadenadas-en-c.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Haiku OS Release 1 Alpha 3</title>
		<link>http://beosman.org/archivo/2011/informatica/haiku-os-release-1-alpha-3.html</link>
		<comments>http://beosman.org/archivo/2011/informatica/haiku-os-release-1-alpha-3.html#comments</comments>
		<pubDate>Wed, 22 Jun 2011 13:06:18 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Sistemas Operativos]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=4561</guid>
		<description><![CDATA[Todo este tinglado de letras y números en el título de la entrada no es más que para hacerse eco de la salida de la versión Release 1 Alpha 3 del sistema operativo Haiku, el clon libre de mi querido BeOS, un año y un mes después de la Alpha 2 (que no comenté aquí, [...]]]></description>
			<content:encoded><![CDATA[<p><img class="floatright" src="http://beosman.org/uploads/2011/06/haiku-os-r1a3-disc.png" alt="Portada del disco de HaikuOS Release 1 Alpha 3" title="Portada del disco de HaikuOS Release 1 Alpha 3" width="208" height="208" /></p>
<p>Todo este tinglado de letras y números en el título de la entrada no es más que para hacerse eco de la salida de la versión <a href="http://www.haiku-os.org/news/2011-06-18_haiku_release_1_alpha_3"><em>Release 1 Alpha 3</em></a> del <a href="http://es.wikipedia.org/wiki/Haiku_(sistema_operativo)">sistema operativo Haiku</a>, el clon libre de mi querido <a href="http://es.wikipedia.org/wiki/BeOS">BeOS</a>, un año y un mes después de la Alpha 2 (que no comenté aquí, por cierto).</p>
<p>Los <a href="http://www.haiku-os.org/get-haiku/release-notes" lang="en">cambios principales</a> son:</p>
<ul>
<li><strong>Hardware</strong>: mejor soporte de hardware con nuevos controladores.</li>
<li><strong>Sistemas de archivos</strong>: soporte para <a href="http://es.wikipedia.org/wiki/Btrfs">btrfs</a>, <a href="http://es.wikipedia.org/wiki/Ext4">ext4</a> y <a href="http://es.wikipedia.org/wiki/ExFAT">exFAT</a>.</li>
<li><strong>Localización</strong>: soporte para traducir y localizar el sistema operativo.</li>
<li><strong>Layout <a href="http://es.wikipedia.org/wiki/API"><acronym title="Application Programming Interface" lang="en">API</acronym></a></strong>: nuevo <acronym title="Application Programming Interface" lang="en">API</acronym> para la colocación de componentes en el desarrollo de aplicaciones.</li>
<li><strong>Aplicaciones</strong>: mejores en la funcionalidad y en las aplicaciones.</li>
<li><strong>Gestión de ventanas</strong>: apilado y ordenación de ventanas. Y con accesos directos de teclado.</li>
<li><strong>Multimedia</strong>: más formatos de audio y vídeo y mejoras en la reproducción de contenidos.</li>
<li><strong>Solución de errores</strong>: más de 950 incidencias resueltas desde la versión anterior.</li>
</ul>
<p>En definitiva, el avance es lento de constante, lo que me lleva a pensar que, quizás, dentro de ¿un año? ¿dos años? podamos disfrutar de la primera versión de <a href="http://www.haiku-os.org">HaikuOS</a>.</p>
<p>Por supuesto, hoy en día no es alternativa de uso; es, simplemente, para trastear, para aprender, para desarrollar&#8230; en definitiva, para quién le gusten las cosas bien hechas. Y sí, he dicho <strong>bien hechas</strong>. Hay mucha documentación sobre BeOS y Haiku para ver el porqué <img src='http://beosman.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2011/informatica/haiku-os-release-1-alpha-3.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Miniaplicación de indicadores en Ubuntu</title>
		<link>http://beosman.org/archivo/2011/informatica/miniaplicacion-de-indicadores-en-ubuntu.html</link>
		<comments>http://beosman.org/archivo/2011/informatica/miniaplicacion-de-indicadores-en-ubuntu.html#comments</comments>
		<pubDate>Wed, 25 May 2011 21:41:07 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Sistemas Operativos]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=4420</guid>
		<description><![CDATA[Los chicos de Ubuntu han desarrollado en las últimas versiones de este sistema operativo un nuevo concepto de bandeja del sistema (esa zona de la barra de menús donde se concentran iconos de aplicaciones en segundo plano) a lo que ellos llaman miniaplicación de indicadores (indicators applet en inglés); y es algo como esto (los [...]]]></description>
			<content:encoded><![CDATA[<p>Los chicos de Ubuntu han desarrollado en las últimas versiones de este sistema operativo un nuevo concepto de bandeja del sistema (esa zona de la barra de menús donde se concentran iconos de aplicaciones en segundo plano) a lo que ellos llaman miniaplicación de indicadores (<em lang="en"><a href="https://launchpad.net/indicator-applet">indicators applet</a></em> en inglés); y es algo como esto (los iconos grises de la izquierda):</p>
<p class="aligncenter">
<img class="image" src="/uploads/2011/05/indicators.png" alt="Indicadores" title="Indicadores" width="510" height="36" />
</p>
<p>Esta nuevo sistema pretende imitar la manida bandeja del sistema de Windows donde aplicaciones en segundo plano incrustan su icono para tener constancia de su ejecución y poder realizar acciones sobre las mismas.</p>
<p>Y, a lo que voy: los iconos son muy bonitos, pero la funcionalidad es una basura. Siento ser tan duro, pero me fastidia mucho que involucionemos en lugar de evolucionar. Porque en cada icono de la <em>antigua</em> bandeja del sistema yo podía hacer clic, doble clic y clic con el botón secundario para realizar diferentes acciones, mientras que con este sistema sólo puedo hacer un clic normal y siempre saldrá un menú de acciones.</p>
<p>¿Es esto evolución? ¿Mejora esto la usabilidad del sistema?</p>
<p>A mi entender no. Mismamente, con la aplicación <a href="http://es.wikipedia.org/wiki/Dropbox">Dropbox</a> (el primer icono empezando por la izquierda de la imagen), antes al hacer clic se abría la carpeta de Dropbox y, con el botón secundario, salía un menú. Ahora siempre sale un menú con el clic. ¿Dónde está el resto de funcionalidad?</p>
<p>¿Creen los desarrolladores de Ubuntu que eliminando funcionalidad se mejora la usabilidad? Yo creo que no.</p>
<p>Hasta aquí mi pataleta de hoy. Otro día seguiré con <a href="http://es.wikipedia.org/wiki/Unity_(entorno_de_escritorio)">Unity</a>, que para él tiene&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2011/informatica/miniaplicacion-de-indicadores-en-ubuntu.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Manifiesto por la artesanía del software</title>
		<link>http://beosman.org/archivo/2011/informatica/manifiesto-por-la-artesania-del-softwar.html</link>
		<comments>http://beosman.org/archivo/2011/informatica/manifiesto-por-la-artesania-del-softwar.html#comments</comments>
		<pubDate>Tue, 24 May 2011 20:36:41 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Informática]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=4385</guid>
		<description><![CDATA[Como aspirantes a Artesanos del Software estamos subiendo el listón del desarrollo profesional de software mediante su práctica, y el compromiso de ayudar a los demás a aprender el arte. A través de este proceso hemos aprendido a valorar: No sólo el software que funciona, sino también el software bien hecho No sólo responder al [...]]]></description>
			<content:encoded><![CDATA[<div style="margin-top:2em;font-style:italic;border-bottom:1px solid silver;">
<p><span style="font-size:300%">C</span>omo aspirantes a Artesanos del Software estamos subiendo el listón del desarrollo profesional de software mediante su práctica, y el compromiso de ayudar a los demás a aprender el arte. A través de este proceso hemos aprendido a valorar:</p>
<p>No sólo el software que funciona,<br />
 	<span style="text-indent:10em;display:block">sino también <strong style="font-size:140%">el software bien hecho</strong></span></p>
<p>No sólo responder al cambio,<br />
	<span style="text-indent:10em;display:block">sino también <strong style="font-size:140%">añadir valor de forma continuada</strong></span></p>
<p>No sólo los individuos y las interacciones,<br />
	<span style="text-indent:10em;display:block">sino también <strong style="font-size:140%">una comunidad de profesionales</strong></span></p>
<p>No sólo la colaboración con el cliente,<br />
	<span style="text-indent:10em;display:block">sino también <strong style="font-size:140%">las asociaciones productivas</strong></span></p>
<p>Esto es, en la búsqueda de los elementos de la izquierda hemos encontrado que los elementos de la derecha son indispensables.
</p>
</div>
<p>Me <a href="http://manifesto.softwarecraftsmanship.org/sign/new">uno</a> al <a href="http://manifesto.softwarecraftsmanship.org/">Manifiesto por la artesanía del software</a> porque yo si considero que hacer software es hacer arte.</p>
<p>Gracias a la <a href="http://mundogeek.net/archivos/2011/05/24/manifiesto-por-la-artesania-del-software/">traducción desde Mundo Geek</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2011/informatica/manifiesto-por-la-artesania-del-softwar.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

