<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Alpha's Manifesto</title>
	
	<link>http://blog.alphasmanifesto.com</link>
	<description>La madriguera de una insignificante figurita blanquinegra.</description>
	<lastBuildDate>Sun, 12 May 2013 18:02:06 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/zorri" /><feedburner:info uri="zorri" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Algunas reseñas de libros</title>
		<link>http://feedproxy.google.com/~r/zorri/~3/_BySLEX_rjI/</link>
		<comments>http://blog.alphasmanifesto.com/2013/05/12/algunas-resenas-de-libros/#comments</comments>
		<pubDate>Sun, 12 May 2013 18:02:06 +0000</pubDate>
		<dc:creator>Alpha</dc:creator>
				<category><![CDATA[Libros]]></category>
		<category><![CDATA[algoritmos]]></category>
		<category><![CDATA[best practices]]></category>
		<category><![CDATA[buenas prácticas]]></category>
		<category><![CDATA[ciencia]]></category>
		<category><![CDATA[código]]></category>
		<category><![CDATA[física]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[humor]]></category>
		<category><![CDATA[informática]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Juegos]]></category>
		<category><![CDATA[reseña]]></category>
		<category><![CDATA[review]]></category>
		<category><![CDATA[The Oatmeal]]></category>

		<guid isPermaLink="false">http://blog.alphasmanifesto.com/?p=4800</guid>
		<description><![CDATA[Hay algunos libros que he leído desde mi última reseña, y al igual que con las películas, dejaré de hacer reseñas individuales. ¡Celebren, porque habrá menos spam para ustedes! En este caso, los libros de los que voy a hablar son: How to tell if your cat is plotting to kill you, por Matthew Inman [...]]]></description>
				<content:encoded><![CDATA[<p style="text-align: justify;">Hay algunos libros que he leído desde mi última reseña, y al igual que con las películas, dejaré de hacer reseñas individuales. ¡Celebren, porque habrá menos spam para ustedes!</p>
<p style="text-align: justify;">En este caso, los libros de los que voy a hablar son:</p>
<ul>
<li style="text-align: justify;"><span style="line-height: 13px;"><em>How to tell if your cat is plotting to kill you</em>, por Matthew Inman</span></li>
<li style="text-align: justify;"><em>Algorithms in a Nutshell</em>, por George Heineman, Gary Pollice y Stanley Selkow</li>
<li style="text-align: justify;"><em>The Grand Design</em>, por Stephen Hawking</li>
<li style="text-align: justify;"><em>HTML5 Games</em>, por Jacob Seidelin</li>
</ul>
<p><span id="more-4800"></span></p>
<hr style="width: 75%;" width="75%" />
<h2>How to tell if your cat is plotting to kill you</h2>
<p><em>por Matthew Inman</em></p>
<p style="text-align: justify;"><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/catplot1.jpg"><img class="size-full wp-image-4802 alignleft" style="margin-right: 10px; margin-top: 10px;" alt="How to tell if your cat is plotting to kill you" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/catplot1.jpg" width="284" height="363" /></a>Este es el libro de Matthew Inman, mejor conocido como <a href="http://theoatmeal.com/">The Oatmeal</a>, un escritor de web comics que tiene un humor algo explícito y muy sarcástico. Amante de los animales y la ciencia, fue mucho mejor conocido por las respuestas ultra-sarcásticas que da a quienes lo amenazan legalmente (ver <a href="http://theoatmeal.com/blog/funnyjunk">caso FunnyJunk</a>, la <a href="http://theoatmeal.com/blog/funnyjunk2">respuesta de FunnyJunk</a> y la <a href="http://theoatmeal.com/blog/funnyjunk_letter">demanda de FunnyJunk por defamación</a>). Si algo quiero compartir de los comics de Oatmeal es su increíble tributo a la vida de Tesla: <a href="http://theoatmeal.com/comics/tesla">Why Nikola Tesla was the greatest geek that ever lived</a>, y la seguidilla de posts en donde él usó su fama para salvar la torre Wardenclyffe y convertirla en un museo.</p>
<p style="text-align: justify;">Volviendo al libro, es una recopilación de muchos de los comics que están online y una compilación de varios otros que no lo están. El estilo de humor es el mismo, por lo que si te gusta lo que ves online, probablemente te guste el libro. No es extremadamente extenso, y la naturaleza de los comics hace que sea de lectura rápida. Literalmente, lo leí en 10 minutos.</p>
<p style="text-align: justify;">Quiero alardear un poquito sobre el hecho de que Matthew Inman (&#8220;el chico de los gatos&#8221;, según se refirieron a él en la librería) visitó nuestra ciudad el año pasado y aprovechamos a saludar y pedirle un autógrafo. A diferencia de lo que sus comics nos hacen pensar, él es una persona de buena presentación, en buena forma física, joven y muy amable.</p>
<p style="text-align: justify;"><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/catplot2.jpg"><img class="aligncenter size-full wp-image-4803" alt="How to tell if your cat is plotting to kill you - signed" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/catplot2.jpg" width="746" height="400" /></a>Resumiendo: buen humor, aunque no destacable, simple. Libro corto.</p>
<p><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-FullSkunk.png"><img class="alignnone size-full wp-image-4808" alt="Review-FullSkunk" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-FullSkunk.png" width="50" height="50" /></a><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-FullSkunk.png"><img alt="Review-FullSkunk" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-FullSkunk.png" width="50" height="50" /></a><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-FullSkunk.png"><img alt="Review-FullSkunk" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-FullSkunk.png" width="50" height="50" /></a><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-NoSkunk.png"><img alt="Review-NoSkunk" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-NoSkunk.png" width="50" height="50" /></a><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-NoSkunk.png"><img alt="Review-NoSkunk" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-NoSkunk.png" width="50" height="50" /></a></p>
<hr style="width: 75%;" width="75%" />
<h2></h2>
<h2>Algorithms in a Nutshell</h2>
<p><em>por George Heineman, Gary Pollice y Stanley Selkow</em></p>
<p style="text-align: justify;"><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/algorithms_nutshell.jpeg"><img class="alignright size-full wp-image-4812" style="margin-left: 10px; margin-top: 10px;" alt="Algorithms in a nutshell" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/algorithms_nutshell.jpeg" width="250" height="378" /></a>Este libro tiene una muy buena premisa y propósito: hacer entender el concepto detrás de los algoritmos más comunes que se utilizan en el mundo de la informática. Básicamente: ordenamiento, asociación, recorrida de grafos, recorrida de árboles, búsqueda. Desafortunadamente, el libro sufre de varios problemas que lo hace muy difícil de seguir, como por ejemplo:</p>
<ul style="text-align: justify;">
<li><span style="line-height: 13px;">Hay elementos de los cuales se dan sus definiciones matemáticas, asumiendo que el lector ya tiene conocimiento sobre esas bases (recordemos que el libro es para entender los algoritmos &#8212; ¿quizá la premisa no tiene en cuenta la audiencia que querría hacer esto?)</span></li>
<li>Los gráficos utilizados como ejemplos son demasiado pequeños para ser parte de un libro. Literalmente cuesta mucho trabajo verlos.</li>
<li>Hay muchas explicaciones que se basan en ejemplos puntuales y no en generalidades. Entiendo el uso de un ejemplo para, precisamente, ejemplificar, pero no para deducir relaciones matemáticas entre objetos y llamarlo una ley.</li>
<li>Extensas tablas de datos, a veces con pocas conclusiones al respecto. Es útil para comparar resultados si uno mismo se propone repetir toda la investigación que los autores hicieron, pero no para, nuevamente, entender los algoritmos.</li>
<li>Se efectúan análisis de espacio (memoria) que son específicos a entornos o lenguajes, pero no en cuanto a aspectos generales de la información utilizada.</li>
<li>Existen casos en donde las explicaciones no logran identificar los elementos que son bases para lograr la intuición del algoritmo. Como un buen ejemplo, la explicación de la búsqueda en grafos habla de colores para identificar el estado de análisis y basa sus conclusiones en base al tamaño o extensión de la frontera de búsqueda &#8212; cuando nunca se definió qué era esa frontera.</li>
<li>El código de ejemplo no está escrito para ser legible, en muchos casos incluso está optimizado. La elección de los lenguajes tampoco es la más feliz (C, con un bajo nivel innecesario, Java con una sobre-ingeniería sobre la jerarquía de objetos). En los ejemplos hay poco de algoritmo y mucho de detalles de implementación.</li>
</ul>
<p style="text-align: justify;">En definitiva, tuve una mala experiencia pero no fue totalmente negativa. Logré entender varios de los puntos que querían hacerse y logré sacar algunas cosas del libro. Además, podría ser útil como material de referencia (si es que uno trabaja en C o en Java, porque hay muy poco pseudocódigo).</p>
<p><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-FullSkunk.png"><img alt="Review-FullSkunk" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-FullSkunk.png" width="50" height="50" /></a><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-NoSkunk.png"><img alt="Review-NoSkunk" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-NoSkunk.png" width="50" height="50" /></a><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-NoSkunk.png"><img alt="Review-NoSkunk" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-NoSkunk.png" width="50" height="50" /></a><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-NoSkunk.png"><img alt="Review-NoSkunk" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-NoSkunk.png" width="50" height="50" /></a><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-NoSkunk.png"><img alt="Review-NoSkunk" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-NoSkunk.png" width="50" height="50" /></a></p>
<hr style="width: 75%;" width="75%" />
<h2>The Grand Design</h2>
<p><em>por Stephen Hawking</em></p>
<p style="text-align: justify;"><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/grandDesign.jpg"><img class="alignleft size-full wp-image-4818" style="margin-right: 10px; margin-top: 10px;" alt="The Grand Design" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/grandDesign.jpg" width="260" height="390" /></a>Personalmente, pensé que este libro se centraría en la controversia de Hawking afirmando que no se requiere un Dios para tener al universo de la forma en la que hoy existe, y más aún con toda la polémica de las teorías del Diseño Inteligente. (Esa es una discusión que no abordaré aquí.)</p>
<p style="text-align: justify;">Sin embargo, aunque menciona estos puntos, el libro está centrado en explicar el progreso de la ciencia desde los más antiguos mitos (¡recomiendo muchísimo el segundo capítulo, es la corta historia de toda la ciencia!), explicar el método científico y dar a entender también cuáles son las últimas teorías más válidas y por qué. Cubre, sin ir demasiado en detalle, la teoría de cuerdas, las previas teorías del Big Bang y la relatividad. Cuenta algunos hechos fascinantes sobre la mecánica cuántica y por qué realmente es más complicada de lo que podemos imaginar.</p>
<p style="text-align: justify;">Un punto muy importante que también explica es el principio antrópico y cómo ha hecho la ciencia para responder esas respuestas. Estén satisfechos o no con esa respuesta, está claro que expone una respuesta a esos problemas y lo explica de una forma muy amena, no hace falta ser un físico teórico para comprender de qué se habla. Como siempre, me quito el sombrero ante Hawking por su capacidad de explicar temas tan complejos de una forma tan simple.</p>
<p style="text-align: justify;"><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-FullSkunk.png"><img alt="Review-FullSkunk" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-FullSkunk.png" width="50" height="50" /></a><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-FullSkunk.png"><img alt="Review-FullSkunk" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-FullSkunk.png" width="50" height="50" /></a><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-FullSkunk.png"><img alt="Review-FullSkunk" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-FullSkunk.png" width="50" height="50" /></a><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-FullSkunk.png"><img alt="Review-FullSkunk" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-FullSkunk.png" width="50" height="50" /></a><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-NoSkunk.png"><img alt="Review-NoSkunk" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-NoSkunk.png" width="50" height="50" /></a></p>
<hr style="width: 75%;" width="75%" />
<h2>HTML5 Games</h2>
<p><em>por Jacob Seidelin</em></p>
<p style="text-align: justify;"><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/html5games.jpg"><img class="alignright size-full wp-image-4825" style="margin-left: 10px; margin-top: 10px;" alt="HTML5 Games" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/html5games.jpg" width="230" height="292" /></a>Este es uno de esos libros que, como <em>Algorithms in a Nutshell</em>, tiene muy buena intención pero la forma de llevar a cabo sus explicaciones no son tan buenas. Sin embargo, a diferencia de ese ejemplo, este sí tiene un contenido con bases mucho más fáciles de comprender, incluso para aquél que no esté totalmente familiarizado con la programación JavaScript.</p>
<p style="text-align: justify;">El libro nos lleva sobre las posibles opciones al momento de desarrollar juegos HTML5 siguiendo la línea de un ejemplo práctico, de principio a fin. En este caso, nos cuenta cómo implementar un juego del tipo match-three, haciendo un clon simple de Bejeweled.</p>
<p style="text-align: justify;">A lo largo del libro, introduce varias herramientas y técnicas pero nunca se detalla en totalidad ninguna de ellas, en pos de seguir adelante con el ejemplo planteado. Personalmente creo que esto distrae del objetivo de educar sobre las posibles opciones y cuándo elegir una u otra, pero no deja de ser un libro instructivo por eso. De la misma forma, se van introduciendo distintas tecnologías hasta el punto necesario para el ejemplo.</p>
<p style="text-align: justify;">Así, el libro es una buena introducción como para tener una idea básica de qué cosas se pueden hacer y de qué forma se harían, pero no es un compendio de posibilidades, ni es extremadamente detallado en las capacidades que las tecnologías mencionadas nos ofrecen. Cabe aclarar, que eso es difícil de lograr de todos modos ya que estas se encuentran aún en un proceso de cambio. Son los riesgos de escribir un libro sobre un tema tan actual.</p>
<p style="text-align: justify;">Por último, quería mencionar que el libro hace caso a las buenas prácticas aunque no las hace una parte central del mismo. Pero es bueno saber que no se sacrifica la calidad de código por llevar adelante un ejemplo. Eso es un punto a favor.</p>
<p style="text-align: justify;"><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-FullSkunk.png"><img alt="Review-FullSkunk" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-FullSkunk.png" width="50" height="50" /></a><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-FullSkunk.png"><img alt="Review-FullSkunk" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-FullSkunk.png" width="50" height="50" /></a><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-HalfSkunk.png"><img class="alignnone size-full wp-image-4809" alt="Review-HalfSkunk" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-HalfSkunk.png" width="50" height="50" /></a><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-NoSkunk.png"><img alt="Review-NoSkunk" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-NoSkunk.png" width="50" height="50" /></a><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-NoSkunk.png"><img alt="Review-NoSkunk" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Review-NoSkunk.png" width="50" height="50" /></a></p>

<div class="wp_rp_wrap  wp_rp_plain" id="wp_rp_first"><div class="wp_rp_content"><h3 class="related_post_title">Posts relacionados:</h3><ul class="related_post wp_rp" style="visibility: visible"><li data-position="0" data-poid="in-4065" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2012/07/01/jquery-novice-to-ninja/" class="wp_rp_title">jQuery Novice to Ninja</a></li><li data-position="1" data-poid="in-2752" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2010/12/31/la-teoria-del-todo/" class="wp_rp_title">La Teoría del Todo</a></li><li data-position="2" data-poid="in-3569" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2012/02/04/pro-asp-net-mvc3-framework/" class="wp_rp_title">Pro ASP.NET MVC3 Framework</a></li><li data-position="3" data-poid="in-4204" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2012/07/22/flatland/" class="wp_rp_title">Flatland</a></li><li data-position="4" data-poid="in-1994" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2010/03/31/link-del-dia-imaginando-la-decima-dimension/" class="wp_rp_title">Link del día: Imaginando la décima dimensión</a></li></ul></div></div>
<img src="http://feeds.feedburner.com/~r/zorri/~4/_BySLEX_rjI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.alphasmanifesto.com/2013/05/12/algunas-resenas-de-libros/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.alphasmanifesto.com/2013/05/12/algunas-resenas-de-libros/</feedburner:origLink></item>
		<item>
		<title>Los favoritos</title>
		<link>http://feedproxy.google.com/~r/zorri/~3/haUuXSZPEh8/</link>
		<comments>http://blog.alphasmanifesto.com/2013/05/12/los-favoritos/#comments</comments>
		<pubDate>Sun, 12 May 2013 15:16:43 +0000</pubDate>
		<dc:creator>Alpha</dc:creator>
				<category><![CDATA[Misceláneos]]></category>
		<category><![CDATA[Tecnología]]></category>
		<category><![CDATA[apoyo]]></category>
		<category><![CDATA[cultura 2.0]]></category>
		<category><![CDATA[DeviantArt]]></category>
		<category><![CDATA[favoritos]]></category>
		<category><![CDATA[sitios]]></category>
		<category><![CDATA[Tumblr]]></category>
		<category><![CDATA[Twitter]]></category>
		<category><![CDATA[web 2.0]]></category>
		<category><![CDATA[Youtube]]></category>

		<guid isPermaLink="false">http://blog.alphasmanifesto.com/?p=4783</guid>
		<description><![CDATA[Una amiga mía preguntó en DeviantArt: ¿por qué favean? ¿Qué hacen con sus favoritos? La pregunta me parece un poco más profunda de lo que aparenta ser en una primera leída. Los favoritos y la forma en la que se usan pueden ser un fenómeno de internet en sí mismo y la cultura 2.0. Quisiera [...]]]></description>
				<content:encoded><![CDATA[<p style="text-align: justify;"><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Favorites.jpg"><img class="aligncenter size-full wp-image-4794" alt="Favorites" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/05/Favorites.jpg" width="746" height="374" /></a></p>
<p style="text-align: justify;"><a href="http://trollkhatt.deviantart.com/journal/Question-Why-do-you-fav-370017816">Una amiga mía preguntó en DeviantArt</a>: ¿por qué favean? ¿Qué hacen con sus favoritos?</p>
<p style="text-align: justify;">La pregunta me parece un poco más profunda de lo que aparenta ser en una primera leída. Los favoritos y la forma en la que se usan pueden ser un fenómeno de internet en sí mismo y la cultura 2.0. Quisiera hablar un poco de eso.</p>
<p style="text-align: justify;"><span id="more-4783"></span></p>
<p style="text-align: justify;">En caso de que estén viviendo debajo de una roca (en cuyo caso, felicitaciones por haber llegado a este blog), los favoritos son generalmente un mecanismo por el cual podemos expresar nuestro gusto particular por contenido disponible en alguna aplicación. Se puede expresar de distintas formas, pero lo que lo distingue de un <em>like</em> de Facebook es que tenemos la posibilidad de volver a ellos y mostrarlos, o no, públicamente. Podemos generar una colección propia de favoritos que luego podremos usar para varias cosas.</p>
<p style="text-align: justify;">Esta capacidad plantea una serie de preguntas, porque si disponemos la capacidad de clasificarlos, ¿de qué forma los clasificamos? En casos contados, esa clasificación ya viene dada por nosotros, como GitHub que nos permite indicar nuestro soporte por un proyecto o indicar nuestro soporte Y estar actualizados sobre un proyecto. En casos como esos la decisión es obvia. Pero en otros casos en donde nosotros podemos definir esa clasificación, ¿qué criterio se usa?</p>
<p style="text-align: justify;">Otra pregunta que se nos plantea es qué utilidad le damos a estos favoritos, puesto que tenemos la posibilidad de volver a ellos y de compartirlos. Pueden ser para mostrar apoyo a un artista o al creador de la obra en general, o puede ser para usar de referencia futura, puede ser para generar una colección virtual temática, o puede ser para sólo juntar cosas que nos gustan (y en ese caso, ¿cuál es el mínimo de &#8220;me gusta&#8221; que debe tener algo para elegirlo como favorito?).</p>
<p style="text-align: justify;">Como extra, en general los favoritos se muestran junto con nuestro perfil al conviertirlo en favoritos. De alguna forma, nuestro perfil entonces tendrá contenido que elijamos de alguien más &#8212; nuevamente la pregunta es: ¿qué criterio utilizar?</p>
<h2 style="text-align: justify;">Favoritos públicos</h2>
<p style="text-align: justify;">Existen sitios como DeviantArt o Twitter, en donde los favoritos son públicos. De alguna forma, <strong>cualquiera que visite el perfil puede ver los favoritos de uno y darse cuenta de qué es lo que nos agrada</strong>. En mi caso personal, no sólo hago de mis favoritos cosas que me gustan, sino cosas que me agradan tanto que estoy dispuesto a asociarlas conmigo. Tanto como si estuviera al lado de un extraño y decirle &#8220;Este es el tipo de cosas que me gustan&#8221;. Son favoritos que estoy dispuesto a compartir, aunque no lo hago activamente. Las redes sociales disponen de una forma de compartirlo (por ejemplo, Twitter y su Retweet), mientras otras no (DeviantArt, para usar los mismos ejemplos).</p>
<p style="text-align: justify;">Yo rara vez vuelvo a revisar esos favoritos, pero probablemente debería. Con el tiempo, el criterio de uno cambia, y muchas cosas de antes ya no son tan valiosas o tan asociables con nosotros.</p>
<h2 style="text-align: justify;">Favoritos privados</h2>
<p style="text-align: justify;">Existen sitios como Tumblr (o Google Reader, ¡por un mes más!), en donde los favoritos son privados. En este caso los uso como referencia personal, de cosas a las que me interesa volver en el futuro. Cosas que quiero revisar, o leer o investigar con posteridad. La integración de servicios fue una herramienta muy importante para que yo pudiera centralizar todo eso (por ejemplo, un starred de Google Reader se va a Instapaper, un favorito de Twitter se va a Instapaper, etc.)</p>
<p style="text-align: justify;">No tengo posibilidad de mostrar estos y de alguna forma tengo una libertad más <em>privada</em> de elegir lo que me gusta y lo que no. Es como no preocuparse en decorar, si nadie va a verlo.</p>
<p style="text-align: justify;">Suelo pensar que la mayoría de nosotros hace algo parecido, pero hay un pequeño detalle: <strong>no son exactamente 100% privados</strong>. Por ejemplo, Tumblr le informa al publicador original a quién le gustan sus obras, o Feedly indica a cuánta gente le gustó un artículo en particular. ¿Supongo que también puede utilizarse el favorito como una forma particular de mostrar apoyo? Yo no lo hago de esa forma.</p>
<h2 style="text-align: justify;">Casos híbridos</h2>
<p style="text-align: justify;">Hay casos híbridos, como Youtube, en donde <strong>los favoritos pueden ser públicos o privados, o mejor aún, los privados pueden compartirse con un grupo selecto</strong>. Google+ y Facebook son también ejemplos.</p>
<p style="text-align: justify;">Aquí yo hago ambas cosas que mencioné antes, desde guardar referencias a mostrar cosas que me gustaría que se asociaran conmigo, a utilizarlos para compartir cosas que un grupo particular de gente que conozco disfrutaría.</p>
<p style="text-align: justify;">Por ejemplo, uno de los favoritos implícitos de Youtube es <em>Watch Later</em>, una lista privada en donde guardamos las cosas que nos gustarían ver después. Otra puede ser una lista privada de música que tengo para cuando quiero escuchar, pero que no me interesa que todos vean públicamente, o videos graciosos que me sacan una sonrisa y no necesariamente quiero asociados conmigo.</p>
<h2 style="text-align: justify;">¿Y ustedes?</h2>
<p style="text-align: justify;">Me interesa escuchar alternativas, ¿cómo trabajan ustedes con los favoritos?</p>
<p style="text-align: justify;">Las preguntas son:</p>
<ul style="text-align: justify;">
<li><span style="line-height: 13px;">¿Qué criterio usan para &#8220;favoritear&#8221; algo?</span></li>
<li>¿Comparten esos favoritos con otra gente? ¿Y de qué  forma?</li>
<li>Pasado el tiempo, ¿vuelven a sus favoritos? ¿Con qué propósito?</li>
</ul>

<div class="wp_rp_wrap  wp_rp_plain" ><div class="wp_rp_content"><h3 class="related_post_title">Posts relacionados:</h3><ul class="related_post wp_rp" style="visibility: visible"><li data-position="0" data-poid="in-3284" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2011/09/26/link-del-dia-if-this-then-that/" class="wp_rp_title">Link del día: If This Then That</a></li><li data-position="1" data-poid="in-2596" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2010/10/14/link-del-dia-microcuentos/" class="wp_rp_title">Link del día: Microcuentos</a></li><li data-position="2" data-poid="in-2189" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2010/06/28/link-del-dia-que-harias-si-ganaras-el-mundial/" class="wp_rp_title">Link del día: Qué harías si ganaras el mundial?</a></li><li data-position="3" data-poid="in-2591" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2010/10/12/link-del-dia-almanaque-solidario/" class="wp_rp_title">Link del día: Almanaque Solidario</a></li><li data-position="4" data-poid="in-2195" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2010/07/01/link-del-dia-datos-todos-en-uno/" class="wp_rp_title">Link del día: Datos, todos en uno</a></li></ul></div></div>
<img src="http://feeds.feedburner.com/~r/zorri/~4/haUuXSZPEh8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.alphasmanifesto.com/2013/05/12/los-favoritos/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.alphasmanifesto.com/2013/05/12/los-favoritos/</feedburner:origLink></item>
		<item>
		<title>PHP: Un fractal de mal diseño</title>
		<link>http://feedproxy.google.com/~r/zorri/~3/hiG34ZjTpA4/</link>
		<comments>http://blog.alphasmanifesto.com/2013/04/15/php-un-fractal-de-un-mal-diseno/#comments</comments>
		<pubDate>Tue, 16 Apr 2013 02:53:23 +0000</pubDate>
		<dc:creator>Alpha</dc:creator>
				<category><![CDATA[Tecnología]]></category>
		<category><![CDATA[artículo]]></category>
		<category><![CDATA[best practices]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[CGI]]></category>
		<category><![CDATA[desarrollo]]></category>
		<category><![CDATA[desarrollo web]]></category>
		<category><![CDATA[excepciones]]></category>
		<category><![CDATA[herramientas]]></category>
		<category><![CDATA[lenguaje]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[problemas]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[seguridad]]></category>
		<category><![CDATA[traducción]]></category>
		<category><![CDATA[Zend]]></category>

		<guid isPermaLink="false">http://blog.alphasmanifesto.com/?p=4537</guid>
		<description><![CDATA[Durante mucho tiempo utilicé PHP, y de hecho, lo sigo utilizando. Sin embargo, siempre sentí como que algunas cosas no encajaban, y aunque varias veces me propuse aprender un paradigma de PHP de forma seria, nunca lo logré. Mucho tiempo después me enteré del gran odio generalizado a PHP y los problemas que ha tenido [...]]]></description>
				<content:encoded><![CDATA[<p style="text-align: justify;">Durante mucho tiempo utilicé PHP, y de hecho, lo sigo utilizando. Sin embargo, siempre sentí como que algunas cosas no encajaban, y aunque varias veces me propuse aprender un paradigma de PHP de forma seria, nunca lo logré. Mucho tiempo después me enteré del gran odio generalizado a PHP y los problemas que ha tenido y leyendo esos artículos me encontré el que voy a traducir a continuación. <a href="http://me.veekun.com/blog/2012/04/09/php-a-fractal-of-bad-design/">PHP: A fractal of Bad Design</a> es una recopilación de <a href="http://me.veekun.com/">Eevee</a>, quien muy amablemente accedió a que yo lo traduzca. La elegí porque es exageradamente detallada y certera.</p>
<p style="text-align: justify;">Debería aclarar que no estoy de acuerdo con todos los puntos mencionados como negativos o siquiera problemas, pero respeto el artículo original del autor sin interrupciones.</p>
<p style="text-align: justify;">Sin más, los dejo con el artículo. Si pueden leer el original, lo recomiendo.</p>
<p><span id="more-4537"></span></p>
<h2>Prefacio</h2>
<p style="text-align: justify;">Soy quejoso. Me quejo sobre un montón de cosas. Hay mucho en el mundo de la tecnología que no me gusta, y eso realmente es de esperar &#8212; programar es una disciplina irrisoriamente joven, y ninguno de nosotros tiene la más mínima idea de lo que estamos haciendo. Combinen eso con la <a href="http://en.wikipedia.org/wiki/Sturgeon%27s_Law">Ley de Sturgeon</a>, y tengo una vida llena de cosas sobre las que protestar.</p>
<p style="text-align: justify;">Esto no es lo mismo. PHP no es meramente raro de usar, o inapropiado para lo que yo quiero, o subóptimo, o contra mi religión. Puedo decir cualquier tipo de cosas buenas sobre lenguajes que evado, y todo tipo de cosas malas sobre lenguajes que disfruto. Adelante, ¡pregunten! Crea conversaciones interesantes.</p>
<p style="text-align: justify;">PHP es la única excepción. Virtualmente cualquier característica de PHP está rota de alguna forma. El lenguaje, el framework, el ecosistema, son todos simplemente <strong>malos</strong>. Y no puedo siquiera remarcar ninguna cosa particular porque el daño es demasiado sistémico. Cada vez que intento compilar una lista de quejas sobre PHP, me quedo estancado en esta búsqueda en profundidad descubriendo más y más trivia fatal. (Por tanto, un fractal.)</p>
<p style="text-align: justify;">PHP es una vergüenza, una mancha en mi oficio. Está tan roto, pero tan elogiado por cada amateur emocionado a quien todavía le queda aprender algo más, hasta ser exasperante. Tiene míseras pocas cualidades redentoras que prefiero olvidarme que existe completamente.</p>
<p style="text-align: justify;">Pero tengo que quitarme esto de encima. Así que aquí va, un último intento.</p>
<hr style="width: 75%;" width="75%" />
<h2>Una analogía</h2>
<blockquote>
<p style="text-align: justify;">Se me acaba de escapar esto explicando mi frustración a Mel y ella insistió en que lo reprodujera aquí:</p>
<p style="text-align: justify;">No puedo siquiera decir qué está mal con PHP porque &#8212; okay. Imagina que tienes, eh, una caja de herramientas. Un conjunto de herramientas. Se ve bien, con las cosas comunes ahí.</p>
<p style="text-align: justify;">Sacas un desarmador, y ves que es uno de esos raros de cabecitas triples. Okay, bueno, eso no es demasiado útil para tí, pero imaginas que puede servir a veces.</p>
<p style="text-align: justify;">Sacas un martillo, pero disgustado ves que tiene las cuñas de ambos lados. De todos modos, aún sirve, me refiero a que puedes golpear los clavos con la parte del centro de la cabeza sosteniéndolo de lado.</p>
<p style="text-align: justify;">Sacas una de las pinzas, pero no tienen esas superficies ásperas; es plana y suave. Eso es menos útil, pero aún ayuda a girar las tuercas, así que de todos modos está bien.</p>
<p style="text-align: justify;">Y así sigues. Cada cosa en la caja es de alguna forma rara y estrafalaria, pero quizá no tanto como para hacerla inútil. Y no hay ningún problema claro con el conjunto como un todo; todavía tiene todas las herramientas.</p>
<p style="text-align: justify;">Ahora imagina que conoces a millones de carpinteros usando esta herramienta que te dicen &#8220;hey bueno, ¿cuál es el problema con estas herramientas? ¡Es todo lo que he usado y han funcionado bien!&#8221; Y los carpinteros te muestran las csasas que han hecho, en donde cada habitación es un pentágono y el techo está de cabeza. Y golpeas en la puerta principal y todo colapsa hacia adentro y todos te gritan por romper su puerta.</p>
<p style="text-align: justify;">Eso es lo que está mal con PHP.</p>
</blockquote>
<hr style="width: 75%;" width="75%" />
<h2>Postura</h2>
<p style="text-align: justify;">Yo aseguro que las siguientes cualidades son <em>importantes</em> para hacer a un lenguaje productivo y útil, y PHP las viola desenfrenadamente. Si no estás de acuerdo en que estas son cruciales, bueno, no puedo imaginar que estaremos de acuerdo en nada.</p>
<ul style="text-align: justify;">
<li>Un lenguaje debe ser <strong>predecible</strong>. Es un medio para expresar ideas humanas y tener a una computadora ejecutándolas, por lo que es crítico que la comprensión humana de un programa sea de hecho correcta.</li>
<li>Un lenguaje debe ser <strong>consistente</strong>. Cosas similares se ven similares, cosas diferentes se ven diferentes. Conocer parte del lenguaje debería ayudar en aprender y comprender el resto.</li>
<li>Un lenguaje debe ser <strong>conciso</strong>. Los nuevos lenguajes existen para reducir el modelo estándar de otros lenguajes viejos. (Todos <em>podríamos</em> escribir en código máquina.) Un lenguaje debe entonces buscar introducir nuevos modelos estándares propios.</li>
<li>Un lenguaje debe ser <strong>confiable</strong>. Los lenguajes son herramientas para resolver problemas; deberían minimizar cualquier nuevo problema que introducen. Cualquier &#8220;gotchas&#8221; son distracciones masivas.</li>
<li>Un lenguaje debe ser <strong>debuggeable</strong>. Cuando algo sale mal, el programador <em>debe</em> arreglarlo, y necesitamos toda la ayuda que podamos obtener.</li>
</ul>
<p style="text-align: justify;">Mi posición es por tanto:</p>
<ul style="text-align: justify;">
<li>PHP está lleno de sorpresas: <span style="font-family: 'courier new', courier;">mysql_real_escape_string</span>, <span style="font-family: 'courier new', courier;">E_ALL</span></li>
<li>PHP es inconsistente: <span style="font-family: 'courier new', courier;">strpos</span>, <span style="font-family: 'courier new', courier;">str_rot13</span></li>
<li>PHP requiere de un modelo estándar: checkeo alrededor de llamadas a APIs de C, <span style="font-family: 'courier new', courier;">===</span></li>
<li>PHP es descascarado: <span style="font-family: 'courier new', courier;">===</span>, <span style="font-family: 'courier new', courier;">foreach ($foo as &amp;$bar)</span></li>
<li>PHP es opaco: no hay stack traces por default o for fatales, el reporte de errores es complejo</li>
</ul>
<p style="text-align: justify;">No puedo proveer un párrafo de comentario para cada problema explicando por qué falla en estas categorías, o esto sería interminable. Espero que el lector, digamos, piense.</p>
<hr style="width: 75%;" width="75%" />
<h2>No comentes con estas cosas</h2>
<p style="text-align: justify;">He estado <em>mucho</em> en discusiones sobre PHP. Escucho muchos argumentos muy genéricos que están solo diseñados para detener la conversación inmediatamente. No me vengas con estos por favor. :(</p>
<ul>
<li style="text-align: justify;">No me digan que &#8220;los buenos programadores pueden escribir buen código en cualquier lenguaje&#8221;, o que los malos programadores bla, bla, bla. Eso no significa nada. Un buen carpintero <em>puede </em>martillar un clavo con una roca o un martillo, pero ¿cuántos carpinteros ves martillando con rocas? Parte de lo que hace a un buen desarrollador es la habilidad para <em>elegir</em> las herramientas con las que trabaja mejor.</li>
<li style="text-align: justify;">No me digas que es responsabilidad de los programadores memorizar mil excepciones y comportamientos extraños. Sí, esto es necesario en cualquier sistema, porque las computadoras apestan. Eso no significa que no hay un límite superior por cuánto payaseo es permitido en un sistema. PHP no es nada <em>sino</em> excepciones, y no está bien cuando pelear con el lenguaje de hecho toma más esfuerzo que escribir tu programa. Mis herramientas no deberían crear más trabajo neto para que yo haga.</li>
<li style="text-align: justify;">No me digas que &#8220;así es cómo funciona la API de C&#8221;. ¿Cuál es el punto de usar un lenguaje de alto nivel si todo lo que provee son utilidades de cadenas y un montón de wrappers de C textuales? ¡Sólo escriban C en ese caso! Aquí, incluso hay una <a href="http://www.boutell.com/cgic/">librería CGI</a> para él.</li>
<li style="text-align: justify;">No me digas que &#8220;eso es lo que te pasa por hacer cosas raras&#8221;. Si dos características existen, algún día, alguien va a encontrar una razón para usarlas juntas. Y nuevamente, esto no es C; no hay especificaciones, no hay necesidad para &#8220;comportamiento indeterminado&#8221;.</li>
<li style="text-align: justify;">No me digas que Facebook y Wikipedia están construidos en PHP. ¡Ya lo sé! Podrían estar también escritos en Brainfuck, pero mientras haya gente inteligente todavía peleando con las cosas, ellos <em>pueden</em> sobreponerse a los problemas con la plataforma. Por todo lo que sabemos, el tiempo de desarrollo podría haber sido duplicado o reducido a la mitad si huberan sido escritos en otro lenguaje; estos datos de por sí no significan nada.</li>
<li style="text-align: justify;">Idealmente, ¡no me digas nada! Este es mi gran intento; si esta lista no hiere tu opinión de PHP, <em>nada</em> nunca lo hará, así que deja de discutir con un tipo en internet y ve a hacer un sitio cool en tiempo récord para demostrar que estoy equivocado. :)</li>
</ul>
<p style="text-align: justify;">Observación al margen: me encaaaaaaaaanta Python. También podría felizmente hablarte lo que quieras quejándome sobre él, si realmente quisieras que lo haga. No aseguro que sea <em>perfecto</em>; simplemente he balanceado sus beneficios contra sus problemas y he concluído que es lo mejor que se ajusta a las cosas que quiero hacer.</p>
<p style="text-align: justify;">Y nunca he conocido a un programador de PHP que puede hacer lo mismo con PHP. Pero me he encontrado con muchos que son rápidos para disculparse por cualquier cosa y todo lo que PHP hace. Esa mentalidad es terrible.</p>
<hr style="width: 75%;" width="75%" />
<h2>PHP</h2>
<h3>Lenguaje central</h3>
<p style="text-align: justify;">CPAN ha sido llamada la &#8220;librería estándar de Perl&#8221;. Eso no dice mucho sobre la librería estándar de Perl, pero deja ver el punto de que un núcleo sólido puede construir cosas grandes.</p>
<h4>Filosofía</h4>
<ul>
<li style="text-align: justify;">PHP fue originalmente diseñado explícitamente para no-programadores (y, leyendo entre líneas, no-programas); y no ha escapado sus raíces bien. Una cita escogida desde la <a href="http://www.php.net/manual/phpfi2.php#overload">documentación de PHP 2.0</a>, respecto de <span style="font-family: 'courier new', courier;">+</span> y amigos haciendo conversión de tipos:</li>
</ul>
<blockquote>
<p style="text-align: justify;">Una vez que comienzas a tener operadores separados para cada tipo, comienzas a hacer el lenguaje mucho más complejo. i.e., no puedes usar &#8216;==&#8217; para stings [sic], ahora usarías &#8216;eq&#8217;. No veo el punto, especialmente para algo como PHP en donde la mayoría de los scripts serán generalmente simples y en muchos casos escrito por no-programadores que quieren un lenguaje con una sintaxis lógica básica y no tiene una curva de aprendizaje muy elevada.</p>
</blockquote>
<ul style="text-align: justify;">
<li>PHP está construido para mantenerse resoplando a todo costo. Cuando se encuentra con la opción de hacer algo sin sentido o abortar con un error, hará algo sin sentido. Cualquier cosa es mejor que nada.</li>
<li>No hay una filosofía de diseño clara. El antiguo PHP fue inspirado en Perl; la gran librería estándar stdlib con parámetros &#8220;out&#8221; es de C; las partes orientadas a objetos fueron diseñadas como C++ y Java.</li>
<li>PHP toma grandes cantidades de inspiración de otros lenguajes, pero aún así logra ser incomprensible para aquellos que <em>conocen</em> esos lenguajes. <span style="font-family: 'courier new', courier;">(int)</span> se ve como C, pero <span style="font-family: 'courier new', courier;">int</span> no existe. Los namespaces usan <span style="font-family: 'courier new', courier;">\</span>. La nueva sintaxis de los arrays resulta en <span style="font-family: 'courier new', courier;">[key =&gt; value]</span>, único entre cualquier lenguaje con hashes literales.</li>
<li>El tipado débil (i.e., conversión silenciosa automática entre strings/números/et al) es tan complejo que cualquier esfuerzo menor de programación ahorrado no lo vale.</li>
<li>Funcionalidad nueva pequeña es implementada como sintaxis nueva; mucho de lo que está hecho con funciones o cosas que parecen como funciones. Excepto por el soporte de clases, que mereció un montón de nuevos operadores y keywords.</li>
<li>Algunos de los problemas listados en esta página tienen soluciones de primera mano &#8212; si estás dispuesto a pagarle a Zend por arreglos para su lenguaje de programación open-source.</li>
<li>Hay mucha acción a distancia. Considera este código, tomado de los documentos de PHP en algún lado.<br />
<span style="font-family: 'courier new', courier;">@fopen(&#8216;http://example.com/archivo-no-existente&#8217;, &#8216;r&#8217;);<br />
</span><br />
¿Qué hará?</p>
<ul>
<li>Si PHP fue compilador con <span style="font-family: 'courier new', courier;">&#8211;disable-url-fopen-wrapper</span>, no funcionará. (La documentación no dice que significa &#8220;no funcionará&#8221;; ¿devuelve null, tira una excepción?)</li>
<li>Si <span style="font-family: 'courier new', courier;">allow_url_fopen</span> está deshabilitado en php.ini, aún no funcionará. (¿Cómo? Ni idea.)</li>
<li>Dado el <span style="font-family: 'courier new', courier;">@</span>, el warning sobre el archivo no existente no será mostrado.</li>
<li>Pero será mostrado si <span style="font-family: 'courier new', courier;">scream.enabled</span> está seteado en php.ini.</li>
<li>Pero no si el <span style="font-family: 'courier new', courier;">error_reporting</span> correcto no está seteado.</li>
<li>Si <em>es</em> mostrado, a donde va exactamente depende de <span style="font-family: 'courier new', courier;">display_errors</span>, nuevamente en php.ini. O <span style="font-family: 'courier new', courier;">ini_set</span>.</li>
</ul>
</li>
<li>(continuación del punto anterior)<br />
No puedo saber cómo esta inocua llamada  a función se comportará sin consultar seteos de compilación, configuraciones a nivel servidor y configuraciones hechas en mi programa. Y todo esto es comportamiento <em>intrínseco</em>.</li>
<li>El lenguaje está lleno de estado global implícito. <span style="font-family: 'courier new', courier;">mbstring</span> usa un set de caracteres global. <span style="font-family: 'courier new', courier;">func_get_arg</span> y compañía se ven como funciones regulares, pero operan en la función que se ejecuta actualmente. Manejo de errores y excepciones tienen defaults globales. <span style="font-family: 'courier new', courier;">register_tick_function</span> setea a una función global para ser ejecutada en cada tick &#8212; ¡¿qué?!</li>
<li>No hay soporte de threading en absoluto. (No es sorprendente, dado lo anterior.) Combinado con la falta de un <span style="font-family: 'courier new', courier;">fork</span> incorporado (mencionado abajo), esto hace que la programación paralela sea extremedamente difícil.</li>
<li>Partes de PHP están prácticamente <em>diseñadas </em>para producir código con bugs.
<ul>
<li><span style="font-family: 'courier new', courier;">json_decode</span> devuelve null para entradas inválidas, aunque null es también un objeto perfectamente válido para ser decodificado como JSON &#8212; esta función es <em>completamente poco fiable</em> a menos que también llames a <span style="font-family: 'courier new', courier;">json_last_error</span> cada vez que la uses.</li>
<li><span style="font-family: 'courier new', courier;">array_search</span>, <span style="font-family: 'courier new', courier;">strpos</span> y funciones similares devuelven <span style="font-family: 'courier new', courier;">0</span> si encuentra la aguja en la posición cero, pero falso si no la encuentran en absoluto.</li>
</ul>
</li>
<li>(continuación del punto anterior)<br />
Permíteme expandirme en esa última parte un poco.<br />
En C, las funciones como <span style="font-family: 'courier new', courier;">strpos</span> devuelven <span style="font-family: 'courier new', courier;">-1</span> si el item no es encontrado. Si no checkeas por ese caso e intentas usarlo como índice, llegarás a memoria basura y tu programa explotará. (Probablemente. Es C. ¿Quién demonios sabe? Estoy seguro de que hay herramientas para esto, como menos.)<br />
En, digamos, Python, el método equivalente, <span style="font-family: 'courier new', courier;">.index</span> arrojarán una excepción  si el ítem no es encontrado. Si no checkeas por ese caso, tu programa explotará.<br />
En PHP, estas funciones devuelven falso. Si usas <span style="font-family: 'courier new', courier;">FALSE</span> como índice, o haces casi cualquier cosa con él excepto comparar con <span style="font-family: 'courier new', courier;">===</span>, PHP silenciosamente lo convertirá a <span style="font-family: 'courier new', courier;">0</span> para tí. Tu programa no explotará; en cambio, <em>hará lo equivocado sin aviso</em>, a menos que recuerdes incluir el código estándar alrededor de cada lugar en donde uses <span style="font-family: 'courier new', courier;">strpos</span> y ciertas otras funciones.<br />
¡Esto está mal! Los lenguajes de programación son herramientas; se supone que deben trabajar <em>conmigo</em>. Aquí, PHP ha activamente creado una sutil trampa para que yo caiga en ella, y yo debo estar atento incluso con cosas mundanas como operaciones de cadena y comparaciones de igualdad. PHP es <em>un campo minado</em>.</li>
</ul>
<p style="text-align: justify;">He escuchado una buena cantidad de historias sobre PHP y <a href="http://en.wikiquote.org/wiki/Rasmus_Lerdorf">sus desarrolladores</a> de muchos lugares. Estas son de la gente que ha trabajado en <a href="http://www.reddit.com/r/lolphp/comments/qeq7k/php_540_ships_with_82_failing_tests_in_the_suite/">el núcleo de PHP</a>, <a href="http://perlbuzz.com/2008/09/optimizing-for-the-developer-not-the-user-php-misses-again.html">ha debuggeado</a> el núcleo de PHP, interactuado con los desarrolladores del núcleo. Ni una sola historia ha sido un elogio.</p>
<p style="text-align: justify;">Entonces debo poner esto aquí, porque vale la pena repetirlo: PHP es una comunidad de amateurs. Muy poca gente diseñándolo, trabajando en él o escribiendo código en él parece saber lo que están haciendo. (Oh, querido lector, ¡<em>tú</em> eres por supuesto una rara excepción!) Ellos que <em>sí</em> logran tener una pista tienden a alejarse a otras plataformas, reduciendo la competencia promedio del todo. Este, aquí mismo, es el mayor problema con PHP: es absolutamente el ciego guiando a los ciegos.</p>
<p style="text-align: justify;">Okay, de vuelta a los hechos.</p>
<h4>Operadores</h4>
<ul>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">== </span>es inútil
<ul>
<li>No es transitivo.  <span style="font-family: 'courier new', courier;">&#8220;foo&#8221; == TRUE</span>, y <span style="font-family: 'courier new', courier;">&#8220;foo&#8221; == 0</span>&#8230; pero, por supuesto, <span style="font-family: 'courier new', courier;">TRUE != 0</span>.</li>
<li><span style="font-family: 'courier new', courier;">==</span> convierte a números cuando es posible (<span style="font-family: 'courier new', courier;">123 == &#8220;123foo&#8221;</span>&#8230; aunque <span style="font-family: 'courier new', courier;">&#8220;123&#8243; != &#8220;123foo&#8221;</span>), lo que significa que convierte a punto flotante cuando es posible. Entonces, cadenas largas hexadecimales (como por ejemplo, digamos, hashes de passwords) pueden ocasionalmente <a href="http://phpsadness.com/sad/47">compararse a true cuando no lo son</a>. Ni JavaScript hace esto.</li>
<li>Por la misma razón, <span style="font-family: 'courier new', courier;">&#8220;6&#8243; == &#8221; 6 &#8220;</span>, <span style="font-family: 'courier new', courier;">&#8220;4.2&#8243; == &#8220;4.20&#8243;</span>, y <span style="font-family: 'courier new', courier;">&#8220;133&#8243; == &#8220;0133&#8243;</span>. Pero nota que <span style="font-family: 'courier new', courier;">133 != 0133</span> porque <span style="font-family: 'courier new', courier;">0133</span> es octal. ¡<em>Pero</em> <span style="font-family: 'courier new', courier;">&#8220;0&#215;10&#8243; == &#8220;16&#8243;</span> y <span style="font-family: 'courier new', courier;">&#8220;1e3&#8243; == &#8220;1000&#8243;</span>!</li>
<li><span style="font-family: 'courier new', courier;">===</span> compara valores y tipo&#8230; excepto con objectos, ¡en donde <span style="font-family: 'courier new', courier;">===</span> es solamente verdadero si ambos operandos son el mismo objeto! Para objetos <span style="font-family: 'courier new', courier;">==</span> compara ambos valores (de cada atributo) y tipo, que es lo que <span style="font-family: 'courier new', courier;">===</span> hace para cualquier otro tipo. <a href="http://developers.slashdot.org/comments.pl?sid=204433&amp;cid=16703529">¿Qué?</a></li>
</ul>
</li>
<li style="text-align: justify;">La comparación no es mucho mejor.
<ul>
<li>Ni siquiera es consistente: <span style="font-family: 'courier new', courier;">NULL &lt; -1</span>, y <span style="font-family: 'courier new', courier;">NULL == 0</span>. El ordenamiento es por tanto no determinístico; depende del orden en el que los algoritmos de ordenación comparan los elementos.</li>
<li>Los operadores de comparación tratan de ordenar arrays de dos maneras distintas: primero por tamaño, luego por <em>elementos</em>. Sin embargo, si tienen el mismo número de elementos, pero <em>diferente</em> conjunto de claves, son incomparables.</li>
<li>Los objetos se comparan como mayores a cualquier otra cosa&#8230; excepto otros objetos, en donde nunca son menores o mayores.</li>
<li>Para un <span style="font-family: 'courier new', courier;">==</span> con tipado más seguro, tenemos <span style="font-family: 'courier new', courier;">===</span>. Para un <span style="font-family: 'courier new', courier;">&lt;</span> con tipado más seguro tenemos&#8230; nada. <span style="font-family: 'courier new', courier;">&#8220;123&#8243; &lt; &#8220;0124&#8243;</span>, no importa lo que hagas. El casting tampoco ayuda.</li>
</ul>
</li>
<li style="text-align: justify;">A pesar de la locura de más arriba, y el rechazo explícito de los pares de operadores numéricos y de cadena de Perl, PHP no sobrecarga <span style="font-family: 'courier new', courier;">+</span>. <span style="font-family: 'courier new', courier;">+</span> es siempre adición y <span style="font-family: 'courier new', courier;">.</span> es siempre concatenación.</li>
<li style="text-align: justify;">El operador de indexado <span style="font-family: 'courier new', courier;">[]</span> también puede ser escrito <span style="font-family: 'courier new', courier;">{}</span>.</li>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">[]</span> puede ser usado en cualquier variable, no sólo cadenas y arrays. Devuelve null y no arroja ningún warning.</li>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">[]</span> no puede partir/rebanar, sólo devuelve elementos individuales.</li>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">foo()[0]</span> es un error de sintaxis. (Arreglado en PHP 5.4.)</li>
<li style="text-align: justify;">A diferencia de (¡literalmente!) cualquier otro lenguaje con un operador similar, ?: es asociativo <em>a izquierda</em>. Entonces esto:<br />
<span style="font-family: 'courier new', courier;">$arg = &#8216;T&#8217;;</span><br />
<span style="font-family: 'courier new', courier;">$vehicle = ( ( $arg == &#8216;B&#8217; ) ? &#8216;bus&#8217; :<br />
( $arg == &#8216;A&#8217; ) ? &#8216;airplane&#8217; :<br />
( $arg == &#8216;T&#8217; ) ? &#8216;train&#8217; :<br />
( $arg == &#8216;C&#8217; ) ? &#8216;car&#8217; :<br />
( $arg == &#8216;H&#8217; ) ? &#8216;horse&#8217; :<br />
&#8216;feet&#8217;);<br />
echo $vehicle<br />
</span>imprime <span style="font-family: 'courier new', courier;">horse</span>.</li>
</ul>
<h4>Variables</h4>
<ul>
<li style="text-align: justify;">No hay forma de declarar una variable. Las variables que no existen son creadas con un valor nulo cuando son usadas por primera vez.</li>
<li style="text-align: justify;">Las variables globales necesitan una declaración <span style="font-family: 'courier new', courier;">global</span> antes de ser usadas. Esta es una consecuencia natural de lo anterior, por lo que sería perfectamente razonable, pero las variables globales no se pueden siqueira <em>leer</em> sin una declaración explícita &#8212; PHP en su lugar silenciosamente creará una variable local con el mismo nombre. No estoy consciente de otro lenguaje con problemas de ámbitos similares.</li>
<li style="text-align: justify;">No hay referencias. Lo que PHP llama referencias son en realidad alias; no hay nada que sea un paso atrás, como las referencias de Perl, y no hay identidad de pasaje-por-objeto como en Python.</li>
<li style="text-align: justify;">El referenciamiento infecta una variable como ninguna otra cosa en el lenguaje. PHP es de tipado dinámico, por lo que las variables generalmente no tienen tipo&#8230; excepto las referencias, que adornan definiciones de funciones, sintaxis de las variables, y asignaciones. Una vez que una variable ha sido convertida en referencia (que puede pasar en cualquier lugar), está atorada como referencia. No hay una forma obvia de detectar esto y de-referenciarla requiere destruir la variable completamente.</li>
<li style="text-align: justify;">Okay, mentí. Hay &#8220;<a href="http://www.php.net/manual/en/book.spl-types.php">Tipos SPL</a>&#8221; que también infectan a las variables: <span style="font-family: 'courier new', courier;">$x = new SplBool(true); $x = &#8220;foo&#8221;;</span> fallará. Es como un tipado estático.</li>
<li style="text-align: justify;">Una referencia puede ser hecha a una key que no existe en una variable no definida (que se convierte en un array). Usar un array no existente por lo general genera un aviso, pero este no.</li>
<li style="text-align: justify;">Las constantes son definidas por una llamada a una función que toman una cadena; antes de eso, no existían. (Esto podría de hecho ser una copia del comportamiento de <span style="font-family: 'courier new', courier;">use constant</span> de Perl.)</li>
<li style="text-align: justify;">Los nombres de las variables son sensibles a mayúsculas y minúsculas. Las funciones y nombres de clases no lo son. Esto incluye nombres de métodos, que hace que camelCase sea una elección extraña para la nomenclatura.</li>
</ul>
<h4>Conceptos</h4>
<ul>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">array()</span> y otra docena de conceptos no son funciones. <span style="font-family: 'courier new', courier;">array</span> por cuenta propia no significa nada. <span style="font-family: 'courier new', courier;">$func = &#8220;array&#8221;; $func();</span> no funciona.</li>
<li style="text-align: justify;">El desempaquetado de arrays puede hacerse con la operación <span style="font-family: 'courier new', courier;">list($a, $b) = &#8230;</span>. <span style="font-family: 'courier new', courier;">list()</span> es sintaxis función-simil como array. No sé por qué a esto no se le dio una sintaxis propiamente dedicada, o por qué el nombre es tan obviamente confuso.</li>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">(int)</span> está obviamente diseñado para verse como C, pero es un token único; no hay nada llamado int en el lenguaje. Inténtalo: no sólo <span style="font-family: 'courier new', courier;">var_dump(int)</span> no funciona, arroja un error de parseo porque el argumento se parece como el operador de casting.</li>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">(integer)</span> es un sinónimo para <span style="font-family: 'courier new', courier;">(int)</span>. También están <span style="font-family: 'courier new', courier;">(bool)</span> / <span style="font-family: 'courier new', courier;">(boolean)</span> y <span style="font-family: 'courier new', courier;">(float)</span> / <span style="font-family: 'courier new', courier;">(double)</span> / <span style="font-family: 'courier new', courier;">(real)</span>.</li>
<li style="text-align: justify;">Hay un operador <span style="font-family: 'courier new', courier;">(array)</span> para castear a arrays y <span style="font-family: 'courier new', courier;">(object)</span> para castear a objetos. Suela loco, pero hay al menos un uso: puedes usar <span style="font-family: 'courier new', courier;">(array)</span> para tener un argumento de una función que sea o un item simple o una lista y tratarlo de forma idéntica. Excepto que no puedes hacerlo con seguridad, porque si alguien pasa un único <em>objeto</em>, castearlo a un array producirá un array conteniendo los atributos del objeto. (Castear a object produce la operación inversa.)</li>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">include()</span> y compañía son básicamente el <span style="font-family: 'courier new', courier;">#include</span> de C: tiran el contenido de otro archivo de código fuente en el tuyo. No hay sistema de módulos, ni siquiera para código PHP.</li>
<li style="text-align: justify;">No hay algo como funciones o clases anidadas o locales. Son sólo globales. Incluir un archivo pone sus variables en el ámbito de la función actual (y le da al archivo acceso a tus variables), pero pone las funciones y clases en el ámbito global.</li>
<li style="text-align: justify;">Agregar a un array se hace con <span style="font-family: 'courier new', courier;">$foo[] = $bar</span>.</li>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">echo</span> es algo estilo instrucción, no una función.</li>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">empty($var)</span> es tan extremadamente no-función que cualquier cosa excepto una variable, por ejemplo, <span style="font-family: 'courier new', courier;">empty($var || $var2)</span>, es un error de parseo. ¿Por qué en la Tierra tiene el parser que saber sobre <a href="http://phpsadness.com/sad/28"><span style="font-family: 'courier new', courier;">empty</span></a>?</li>
<li style="text-align: justify;">Hay sintaxis redundante para los bloques: <span style="font-family: 'courier new', courier;">if (&#8230;): &#8230; endif;</span>, etc.</li>
</ul>
<h4>Manejo de errores</h4>
<ul>
<li style="text-align: justify;">El único operador de PHP es <span style="font-family: 'courier new', courier;">@</span> (de hecho, tomado prestado de DOS), que <em>silencia</em> errores.</li>
<li style="text-align: justify;">Los errores de PHP no proveen stack traces. Debes instalar un handler para que los genere. (Pero no puedes hacerlo para errores fatales &#8212; ver abajo.)</li>
<li style="text-align: justify;">Los errores de parseo de PHP generalmente sólo escupen el estado de parseo y nada más, haciendo una comilla olvidada <a href="http://phpsadness.com/sad/44">terrible para debuggear</a>.</li>
<li style="text-align: justify;">El parser de PHP se refiere, por ejemplo, a <span style="font-family: 'courier new', courier;">::</span> internamente como <span style="font-family: 'courier new', courier;">T_PAAMAYIM_NEKUDOTAYIM</span>, y al operador <span style="font-family: 'courier new', courier;">&lt;&lt;</span> como <span style="font-family: 'courier new', courier;">T_SL</span>. Digo &#8220;internamente&#8221; pero igual que arriba, esto es lo que se le muestra al programador cuando <span style="font-family: 'courier new', courier;">::</span> o <span style="font-family: 'courier new', courier;">&lt;&lt;</span> aparecen en el lugar equivocado.</li>
<li style="text-align: justify;">Mucho del manejo de errores es en la forma de imprimir una línea a un log en el servidor que nadie lee y seguir adelante.</li>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">E_STRICT</span> está ahí, pero no parece prevenir mucho y no hay documentación sobre lo que en realidad hace.</li>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">E_ALL</span> incluye todas las categorias de errores &#8212; excepto <span style="font-family: 'courier new', courier;">E_STRICT</span>. (Arreglado en 5.4.)</li>
<li style="text-align: justify;">Es raramente inconsistente entre lo que está permitido y lo que no. No sé cómo <span style="font-family: 'courier new', courier;">E_STRICT</span>aplica acá, pero estas cosas están permitidas:
<ul>
<li>Intentar acceder a una propiedad no existente en un objeto, i.e., <span style="font-family: 'courier new', courier;">$foo-&gt;x</span>. (Warning.)</li>
<li>Usar una variable como un nombre de función, o nombre de variable, o nombre de clase. (Silencioso.)</li>
<li>Tratar de usar una constante no definida. (Notice.)</li>
<li>Tratar de acceder una propiedad de algo que no es un objeto. (Notice.)</li>
<li>Tratar de usar un nombre de variable que no existe. (Notice.)</li>
<li><span style="font-family: 'courier new', courier;">2 &lt; &#8220;foo&#8221;</span> (silencioso)</li>
<li><span style="font-family: 'courier new', courier;">foreach (2 as $foo);</span> (warning)</li>
</ul>
</li>
<li style="text-align: justify;">(continuación del punto anterior)<br />
Y estas cosas no lo están:</p>
<ul>
<li>Tratar de acceder una constante de una clase no existente, i.e., <span style="font-family: 'courier new', courier;">$foo::x</span>. (Error fatal.)</li>
<li>Usar una cadena constante como un nombre de funci&#8217;on, o nombre de variable, o nombre de clase. (Error de parseo.)</li>
<li>Tratar de llamar a una función indefinida. (Error fatal.)</li>
<li>No poner un punto y coma en la última instrucción en un bloque o archivo. (Error de parseo.)</li>
<li>Usar <span style="font-family: 'courier new', courier;">list</span> y cualquier otro quasi-elemento incorporado como nombre de método. (Error de parseo.)</li>
<li>Subindicar el valor devuelto por una función, i.e., <span style="font-family: 'courier new', courier;">foo()[0]</span>. (Error de parseo; permitido en 5.4, ver arriba.)</li>
</ul>
</li>
<li style="text-align: justify;">(continuación del punto anterior)<br />
Hay otros buenos ejemplos de otros errores de parseo extraños en algún otro lado en esta lista.</li>
<li style="text-align: justify;">El método <span style="font-family: 'courier new', courier;">__toString</span> no puede arrojar excepciones. Si intentar, PHP &#8230; er&#8230; arrojará una excepción. (De hecho, un error fatal, que podría ser aceptable, excepto&#8230;)</li>
<li style="text-align: justify;">Los errores de PHP y las excepciones de PHP son dos bestias completamente distintas. No parecen interactuar <em>para nada</em>.
<ul>
<li>Los errores de PHP (los internos, y las llamadas a <span style="font-family: 'courier new', courier;">trigger_error</span>) no se pueden atrapar con <span style="font-family: 'courier new', courier;">try</span> / <span style="font-family: 'courier new', courier;">catch</span>.</li>
<li>De forma similar, las excepciones no desatan manejadores de errores instalados por <span style="font-family: 'courier new', courier;">set_error_handler</span>.</li>
<li>En su lugar, hay un <span style="font-family: 'courier new', courier;">set_exception_handler</span> separado que maneja excepciones no atrapadas, porque envolver al punto de entrada de tu programa en un bloque <span style="font-family: 'courier new', courier;">try</span> es imposible en el modelo <span style="font-family: 'courier new', courier;">mod_php</span>.</li>
<li>Los errores fatales (por ejemplo, <span style="font-family: 'courier new', courier;">new ClassDoesntExist()</span>) no pueden ser atrapados por nada. <em>Muchas</em> de las cosas inofensivas arrojan errores fatales, terminando tu programa forzosamente por razones cuestionables. Las funciones de cierre aún se ejecutarán, pero no pueden obtener un stack trace (corren al nivel más alto) y no pueden fácilmente determinar si el programa terminó por error o por haberse completado.</li>
</ul>
</li>
<li style="text-align: justify;">No hay una construcción <span style="font-family: 'courier new', courier;">finally</span>, haciendo al código que envuelve otro código (poner manejador, correr el código, quitar el manejador; monkeypatch, correr un test, quitar el monkeypatch) tedioso y difícil de escribir. A pensar que la orientación a objectos y las excepciones fueron en su mayor parte copiadas de Java, esto <a href="https://bugs.php.net/bug.php?id=32100">es deliberado</a>, porque finally &#8220;no tiene mucho sentido en el contexto de PHP&#8221;. ¿Eh?</li>
</ul>
<h4>Funciones</h4>
<ul>
<li style="text-align: justify;">Las llamadas a funciones aparentemente son algo <a href="http://www.phpwtf.org/php-function-calls-have-quite-some-overhead">caras</a>.</li>
<li style="text-align: justify;">Algunas funciones incorporadas interactúan con las funciones que devuelven referencias en, ehm, <a href="http://www.phpwtf.org/php-function-calls-returning-references">una manera extraña</a>.</li>
<li style="text-align: justify;">Como está mencionado en algún otro lado, muchas cosas que parecen funciones o se ven como que <em>deberían ser</em> funciones, son de hecho construcciones del lenguaje, de forma que nada que trabaje con funciones trabajará con ellas.</li>
<li style="text-align: justify;">Los argumentos de las funciones pueden tener &#8220;implicación de tipos&#8221;, que es básicamente tipado estático. Pero no puedes requerir que un argumento sea un <span style="font-family: 'courier new', courier;">int</span>, o <span style="font-family: 'courier new', courier;">string</span>, u <span style="font-family: 'courier new', courier;">object</span>, u otro tipo &#8220;del núcleo&#8221;, incluso cuando cualquier función incorporada usa este tipo de tipado, probablemente porque <span style="font-family: 'courier new', courier;">int</span> no es nada en PHP. (Ver arriba sobre <span style="font-family: 'courier new', courier;">(int)</span>.) Tampoco puedes usar las <a href="http://www.php.net/manual/en/language.pseudo-types.php#language.types.mixed">decoraciones de pseudo-tipos</a> usada tanto en las funciones incorporadas: <span style="font-family: 'courier new', courier;">mixed</span>, <span style="font-family: 'courier new', courier;">number</span>, o <span style="font-family: 'courier new', courier;">callback</span>. (<span style="font-family: 'courier new', courier;">callable</span>está permitido desde PHP 5.4.)
<ul>
<li>Como resultado, esto:<span style="font-family: 'courier new', courier;">function foo(string $s) {}</span><br />
<span style="font-family: 'courier new', courier;">foo(&#8220;hello world&#8221;);</span>produce el error:<span style="font-family: 'courier new', courier;">PHP Catchable fatal error: argument 1 passed to foo() must be an instance of string, string given, called in&#8230;</span></li>
<li>Puedes notar que el &#8220;implicado de tipo&#8221; dado no tiene que existir; no hay ninguna clase <span style="font-family: 'courier new', courier;">string</span> en este programa. Si intentas usar <span style="font-family: 'courier new', courier;">ReflectionParameter::getClass()</span> para examinar el implicado de tipos de forma dinámica, entonces negará que la clase no existe, haciendo imposible obtener el nombre de la clase.</li>
<li>El valor devuelto por una función no puede ser tipado.</li>
</ul>
</li>
<li style="text-align: justify;">Pasar los argumentos de una función a otra función (dispatching, no raro) es hecho llamando a <span style="font-family: 'courier new', courier;">call_user_func_array(&#8216;other_function&#8217;, func_get_args())</span>. Pero <span style="font-family: 'courier new', courier;">func_get_args</span> arroja un error fatal en tiempo de ejecución, quejándose que no puede ser un parámetro de función. ¿Cómo y por que es esto siquiera un <em>tipo</em> de error? (Arreglado en PHP 5.3.)</li>
<li style="text-align: justify;">Las clausuras requieren explícitamente nombrar cada variable sobre la que se cerrará. ¿Por qué no puede el intérprete detectarlo solo? Como que destroza el propósito de la característica. (Okay, es porque usar una variable en algún punto, en cualquier punto, la crea a menos que se le diga explícitamente lo contrario.)</li>
<li style="text-align: justify;">Las variables sobre las que se cierra la clausura son &#8220;pasadas&#8221; por la misma semántica que otros argumentos de función. Eso es, arrays, strings, etc., serán &#8220;pasados&#8221; a la clausura por valor. A menos que uses <span style="font-family: 'courier new', courier;">&amp;</span>.</li>
<li style="text-align: justify;">Ya que las variables sobre las que se cierra la clausura son efectivamente argumentos automáticamente pasados y no hay ámbitos anidados, una clausura no se puede referir a métodos privados, incluso si está definido dentro de una clase. (¿Posiblemente arreglado en 5.4? No está claro.)</li>
<li style="text-align: justify;">No hay argumentos nombrados a las funciones. De hecho, <a href="http://www.php.net/~derick/meeting-notes.html#named-parameters">se rechazaron explícitamente</a> por los desarrolladores porque &#8220;ayuda a código más desprolijo&#8221;.</li>
<li style="text-align: justify;">Los argumentos de función con valores por defecto pueden aparecer antes que los argumentos de función sin ellos, incluso aunque la documentación aclara que esto es raro e inútil. (Entonces, ¿por qué permitirlo?)</li>
<li style="text-align: justify;">Los argumentos extras a una función son ignorados (excepto con funciones incorporadas, que arrojan un error). Los argumentos faltantes se asumen nulos.</li>
<li style="text-align: justify;">Las funciones &#8220;variadicas&#8221; requieren pelear con <span style="font-family: 'courier new', courier;">func_num_args</span>, <span style="font-family: 'courier new', courier;">func_get_arg</span> y <span style="font-family: 'courier new', courier;">func_get_args</span>. No hay sintaxis para algo así.</li>
</ul>
<h4>Orientación a Objetos (OO)</h4>
<ul>
<li style="text-align: justify;">Las partes procedurales de PHP están diseñadas como C, pero la parte objeccional (jo jo) están diseñadas como Java. No puedo sobreenfatizar lo discordante que esto es. El sistema de clases está diseñado alrededor del lenguaje Java de <em>bajo-nivel</em> que es naturalmente y deliberadamente más limitado que los contemporarios de PHP, y estoy perplejo.
<ul>
<li>Todavía debo encontrar alguna función global que siquiera tenga una letra mayúscula en su nombre, pero aún así varias <a href="http://www.php.net/manual/en/class.reflectionfunction.php">clases importantes incorporadas</a> usan nombres de métodos camelCase y tienen métodos de acceso <span style="font-family: 'courier new', courier;">getFoo</span> al estilo Java.</li>
<li>Perl, Python y Ruby, todos tienen algún concepto de acceso a &#8220;propiedad&#8221; vía código; PHP sólo tiene el torpe <span style="font-family: 'courier new', courier;">__get</span> y sus amigos. (La documentación inexplicablemente se refiere a esos métodos especiales como &#8220;sobrecarga&#8221;.)</li>
<li>Las clases tienen algo como la declaración de variables (<span style="font-family: 'courier new', courier;">var</span> y <span style="font-family: 'courier new', courier;">const</span>) para atributos de clase, mientras que la parte procedural del lenguaje no.</li>
<li>A pesar de la pesada influencia de C++/Java, donde los objetos son medianamente opacos, PHP generalmente trata a los objetos como hashes bonitos &#8212; por ejemplo, el comportamiento por defecto de <span style="font-family: 'courier new', courier;">foreach ($obj as $key =&gt; $value)</span> es para iterar sobre cada atributo accesible del objeto.</li>
</ul>
</li>
<li style="text-align: justify;">Las clases no son objetos. Cualquier tipo de metaprogramación se debe referir a ellas con nombres en cadenas, igual que las funciones.</li>
<li style="text-align: justify;">Los tipos incorporados no son objetos y (a diferencia de Perl) no se pueden hacer parecer objetos de ninguna forma.</li>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">instanceof</span> es un operador, a pesar que las clases fueron una adición tardía y que mucho del lenguaje está construido en funciones y sintaxis orientada a funciones. ¿Influencia de Java? ¿Las clases no son de primera clase? (No sé si lo son.)</li>
<li style="text-align: justify;">
<ul>
<li>Pero <em>sí</em> hay una función <span style="font-family: 'courier new', courier;">is_a</span>. Con un argumento opcional indicando si se permite al objeto ser en realidad una cadena nombrando una clase.</li>
<li><span style="font-family: 'courier new', courier;">get_class</span> es una función; no hay operador <span style="font-family: 'courier new', courier;">typeof</span>. Parecido a <span style="font-family: 'courier new', courier;">is_subclass_of</span>.</li>
<li>Esto no trabaja en tipos incorporadas, sin embargo (de nuevo, <span style="font-family: 'courier new', courier;">int</span> no es nada). Para eso necesitas <span style="font-family: 'courier new', courier;">is_int</span>, etc.</li>
<li>También, el lado derecho debe ser una variable o una cadena literal; no puede ser una expresión. Eso causa&#8230; un error de parseo.</li>
</ul>
</li>
<li style="text-align: justify;">¿!<span style="font-family: 'courier new', courier;">clone</span> es un operador!?</li>
<li style="text-align: justify;">Los atributos de objetos son <span style="font-family: 'courier new', courier;">$obj-&gt;foo</span>, pero los atributos de clases son <span style="font-family: 'courier new', courier;">Class::$foo</span>. (<span style="font-family: 'courier new', courier;">$obj::foo</span> intentará convertir <span style="font-family: 'courier new', courier;">$obj</span> a string y usarlo como nombre de clase.) Los atributos de clase no pueden accederse desde los objetos, los espacios de nombres están completamente separados, haciendo que los atributos de clase sean completamente inútiles para polimorfismo. Los <em>métodos</em> de clase, por supuesto, están excemptos de esta regla y pueden ser llamdos como cualquier otro método. (Me han dicho que C++ también hace esto. C++ no es un buen ejemplo de OO correcta.)</li>
<li style="text-align: justify;">También, un método de instancia puede ser llamado de forma estática. (<span style="font-family: 'courier new', courier;">Class::method()</span>). Si se hace desde otro método, esto es tratado como una llamada regular a un método en el <span style="font-family: 'courier new', courier;">$this</span> actual. Creo.</li>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">new</span>, <span style="font-family: 'courier new', courier;">private</span>, <span style="font-family: 'courier new', courier;">public</span>, <span style="font-family: 'courier new', courier;">protected</span>, <span style="font-family: 'courier new', courier;">static</span>, etc. ¿Intentando ganar desarrolladores de Java? Soy consciente que esto es más una cuestión de gusto, pero no sé por qué esto es necesario en un lenguaje dinámico &#8212; en C++, mucho de esto se trata de compilación y resolución de nombres en tiempo de compilación.</li>
<li style="text-align: justify;">PHP tiene soporte de primera clase para &#8220;clases abstractas&#8221;, que son clases que no pueden ser instanciadas. El código en lenguajes similares logra esto arrojando una excepción en el constructor.</li>
<li style="text-align: justify;">Las clases derivadas no pueden sobreescribir métodos privados. Las sobreescrituras (overrides) de métodos públicos no pueden siquiera <em>ver</em>, menos llamar, a los métodos privados de la clase padre. Problemático para, digamos, mocks de testing.</li>
<li style="text-align: justify;">Los métodos no se pueden nombrar, por ejemplo, &#8220;list&#8221;, porque <span style="font-family: 'courier new', courier;">list()</span> es sintaxis especial (no una función), y el parser se confunde. No hay razón por la que esto debería ser ambiguo, y hacer monkeypatching de la clase funciona bien. (<span style="font-family: 'courier new', courier;">$foo-&gt;list()</span> no es un error de sintaxis).</li>
<li style="text-align: justify;">Si una excepción es lanzada mientras se evalúan los argumentos de un constructor (por ejemplo, <span style="font-family: 'courier new', courier;">new Foo(bar())</span> y <span style="font-family: 'courier new', courier;">bar()</span> la arroja), el constructor no será llamado pero el <em>destructor </em>lo será. (Esto está arreglado en PHP 5.3).</li>
<li style="text-align: justify;">Las excepciones en <span style="font-family: 'courier new', courier;">__autoload</span> y los destructores causan errores fatales. (Arreglado en PHP 5.3.6. Entonces ahora un destructor podría arrojar una excepción literalmente en cualquier lugar, dado que es llamado en el momento en donde el contador de referencias deja el zero. Hmm.)</li>
<li style="text-align: justify;">No hay constructores o destructores. <span style="font-family: 'courier new', courier;">__construct</span> es un inicializador, igual que el <span style="font-family: 'courier new', courier;">__init__</span> de Python. No hay método que puedas llamar en una clase para reservar memoria y crear un objeto.</li>
<li style="text-align: justify;">No hay inicializador por defecto. Llamar a <span style="font-family: 'courier new', courier;">parent::_construct()</span> si la clase padre no define su propio <span style="font-family: 'courier new', courier;">__construct</span> es un error fatal.</li>
<li style="text-align: justify;">OO trae consigo una interfaz de interador que partes del lenguaje respetan (por ejemplo, <span style="font-family: 'courier new', courier;">for&#8230;as</span>), pero nada incorporado (como los arrays) implementa la interfaz. Si quieres un iterador de array, debes envolverlo en un <span style="font-family: 'courier new', courier;">ArrayIterator</span>. No hay maneras incorporadas de encadenar llamadas o partir collecciones o trabajar de alguna otra forma con los iteradores como objetos de primera clase.</li>
<li style="text-align: justify;">Las interfaces como <span style="font-family: 'courier new', courier;">Iterator</span> se reservan unos beuenos métodos sin prefijos. Si quieres que tu clase sera iterable (sin el comportamiento por defecto de iterar en todos sus atributos), pero quieres usar un método común como <span style="font-family: 'courier new', courier;">key</span>, o <span style="font-family: 'courier new', courier;">next</span>, o <span style="font-family: 'courier new', courier;">current</span>, bueno, lástima.</li>
<li style="text-align: justify;">Las clases pueden sobrecargar cómo se convierten a strings y cómo actúan cuando son llamadas, pero no cómo se convierten a números ni a ningún otro tipo incorporado.</li>
<li style="text-align: justify;">Las cadenas, números y arrays todos tienen conversiones a cadena; el lenguaje recae fuertemente en esto. Las funciones y las clases <em>son</em> cadenas. Aún así, intentar convertir un objeto incorporado o definido por el usuario (incluso una clausura) a un string causa un error si no se define <span style="font-family: 'courier new', courier;">__toString</span>. Incluso <span style="font-family: 'courier new', courier;">echo</span> se convierte en propenso a errores.</li>
<li style="text-align: justify;">No hay sobrecarga para igualdad u ordenamiento.</li>
<li style="text-align: justify;">Las variables estáticas dentro de los métodos de instancias son globales; tienen el mismo valor en todas las instancias de la clase.</li>
</ul>
<h3>Librería estándar</h3>
<p style="text-align: justify;">Perl es &#8220;algo de construcción necesaria&#8221;. Python es &#8220;baterías incluidas&#8221;. PHP es &#8220;de todo y más, pero es de Canadá y <a href="http://mcguirehimself.com/?p=4146">ambas llaves dicen C</a>&#8220;.</p>
<h4>General</h4>
<ul>
<li style="text-align: justify;">No hay sistema de módulos. Puedes compilar extensiones PHP, pero las que se carguen son especificadas en php.ini, y tus opciones son que una extensión exista (e inyecte sus contenidos en el espacio de nombres global) o no.</li>
<li style="text-align: justify;">Como los espacios de nombres son una característica reciente, la librería estándar no está dividida para nada. Hay miles de funciones en el espacio de nombres global.</li>
<li style="text-align: justify;">Pedazos de la librería son terriblemente inconsistentes de otros.
<ul>
<li>Guión bajo versus sin guión bajo: <span style="font-family: 'courier new', courier;">strpos</span> / <span style="font-family: 'courier new', courier;">str_rot13</span>, <span style="font-family: 'courier new', courier;">php_uname</span> / <span style="font-family: 'courier new', courier;">phpversion</span>, <span style="font-family: 'courier new', courier;">base64_encode</span> / <span style="font-family: 'courier new', courier;">urlencode</span>, <span style="font-family: 'courier new', courier;">gettype</span> / <span style="font-family: 'courier new', courier;">get_class</span>.</li>
<li>&#8220;to&#8221; versus &#8220;2&#8243;: <span style="font-family: 'courier new', courier;">ascii2ebcdic</span>, <span style="font-family: 'courier new', courier;">bin2hex</span>, <span style="font-family: 'courier new', courier;">deg2grad</span>, <span style="font-family: 'courier new', courier;">strtolower</span>, <span style="font-family: 'courier new', courier;">strtotime</span>.</li>
<li>Objeto+verbo versus verbo+objeto: <span style="font-family: 'courier new', courier;">base64_decode</span>, <span style="font-family: 'courier new', courier;">str_shuffle</span>, <span style="font-family: 'courier new', courier;">var_dump</span> versus <span style="font-family: 'courier new', courier;">create_function</span>, <span style="font-family: 'courier new', courier;">recode_string</span>.</li>
<li>Orden de argumentos: <span style="font-family: 'courier new', courier;">array_filter($input, $callback)</span> versus <span style="font-family: 'courier new', courier;">array_map($callback, $input)</span>, <span style="font-family: 'courier new', courier;">strpos($haystack, $needle)</span> versus <span style="font-family: 'courier new', courier;">array_search($needle, $haystack)</span>.</li>
<li>Confusión de prefijos: <span style="font-family: 'courier new', courier;">usleep</span> versus <span style="font-family: 'courier new', courier;">microtime</span>.</li>
<li>Funciones insensitivas a mayúsculas y minúsculas que varían en donde la <span style="font-family: 'courier new', courier;">i</span> va en el nombre.</li>
<li>Alrededor de la mitad de las funciones de arrays comienzan con <span style="font-family: 'courier new', courier;">array_</span>. Las otras no.</li>
<li><span style="font-family: 'courier new', courier;">htmlentities</span> y <span style="font-family: 'courier new', courier;">html_entity_decode</span> son <em>inversas</em> una de la otra, con convenciones de nombre completamente distintas.</li>
</ul>
</li>
<li>De todo y algo más. La librería incluye:
<ul>
<li style="text-align: justify;">Bindeos a ImageMagick, bindeos a GraphicsMagick (que es un fork de ImageMagick), y un puñado de funciones para inspeccionar datos EXIF (que ImageMagick ya puede hacer).</li>
<li style="text-align: justify;">Funciones para parsear bbcode, un tipo de markup muy específico utilizado por un puñado de paquetes de foros.</li>
<li style="text-align: justify;">Demasiados paquetes XML. <span style="font-family: 'courier new', courier;">DOM</span> (orientado a objetos), <span style="font-family: 'courier new', courier;">DOM XML</span> (no), <span style="font-family: 'courier new', courier;">libxml</span>, <span style="font-family: 'courier new', courier;">SimpleXML</span>, &#8220;XML Parser&#8221;, <span style="font-family: 'courier new', courier;">XMLReader</span>/<span style="font-family: 'courier new', courier;">XMLWriter</span>, y otra media docena de acrónimos que no puedo identificar. Hay seguramente algún tipo de diferencia entre estas cosas y eres libre de averiguar cuál es.</li>
<li style="text-align: justify;">Bindings para dos procesadores específicos de tarjetas de crédito, SPPLUS y MCVE. ¿Qué?</li>
<li style="text-align: justify;">Tres maneras de acceder a una base de datos MySQL: <span style="font-family: 'courier new', courier;">mysql</span>, <span style="font-family: 'courier new', courier;">mysqli</span>, y la cosa esa de abtracción <span style="font-family: 'courier new', courier;">PDO</span>.</li>
</ul>
</li>
</ul>
<h4>Influencia de C</h4>
<p style="text-align: justify;">Esto merece su propio título, porque es tan absurdo y aún así permea al lenguaje. PHP es un lenguaje de programación de alto nivel dinámicamente tipado. Aún así una porción masiva de la librería estándar son aún wrappers muy finos sobre APIs de C, con los siguientes resultados:</p>
<ul>
<li style="text-align: justify;">Parámetros &#8220;out&#8221;, incluso a pesar de que PHP puede devolver hashes ad-hoc o múltiples argumentos con poco esfuerzo.</li>
<li style="text-align: justify;">Al menos una docena de funciones para obtener el último error de un subsistema en particular (ver más abajo), a pesar de que PHP ha tenido excepciones por ocho años.</li>
<li style="text-align: justify;">Verrugas como <span style="font-family: 'courier new', courier;">mysql_real_escape_string</span>, a pesar de que tiene los mismos argumentos que <span style="font-family: 'courier new', courier;">mysql_escape_string</span>, sólo porque es parte de la API C de MySQL.</li>
<li style="text-align: justify;">Comportamiento global para funcionalidad no-global (como MySQL). Usar múltiples conexiones a MySQL aparentemente requiere pasar un identificador de conexión en cada llamada a función.</li>
<li style="text-align: justify;">Los wrappers son realmente, realmente finos. Por ejemplo, llamar a <span style="font-family: 'courier new', courier;">dba_nextkey</span> sin llamar a <span style="font-family: 'courier new', courier;">dba_firstkey</span> generará un error de segmentación.</li>
<li style="text-align: justify;">Hay un conjunto de funciones <span style="font-family: 'courier new', courier;">ctype_*</span> (por ejemplo, <span style="font-family: 'courier new', courier;">ctype_alnum</span>), que mapean a las funciones de detección de clases de caracteres de C de nombres similares, a pesar de, digamos, <span style="font-family: 'courier new', courier;">isupper</span>.</li>
</ul>
<h4>Genericismo</h4>
<p style="text-align: justify;">No hay ninguno. Si una función tiene que hacer dos cosas ligeramente distintas, PHP simplemente tiene dos funciones.</p>
<p style="text-align: justify;">¿Cómo ordenas en orden inverso? En Perl podrías hacer <span style="font-family: 'courier new', courier;">sort { $b &lt;=&gt; $a }</span>. En Python, podrías hacer <span style="font-family: 'courier new', courier;">sort(reverse=True)</span>. En PHP hay una función separada llamada <span style="font-family: 'courier new', courier;">rsort()</span>.</p>
<ul>
<li style="text-align: justify;">Funciones que buscan un error de C: <span style="font-family: 'courier new', courier;">curl_error</span>, <span style="font-family: 'courier new', courier;">json_last_error</span>, <span style="font-family: 'courier new', courier;">openssl_error_string</span>, <span style="font-family: 'courier new', courier;">imap_errors</span>, <span style="font-family: 'courier new', courier;">mysql_error</span>, <span style="font-family: 'courier new', courier;">xml_get_error_code</span>, <span style="font-family: 'courier new', courier;">bzerror</span>, <span style="font-family: 'courier new', courier;">date_get_last_errors</span>, ¿otras?</li>
<li style="text-align: justify;">Funciones que ordenan: <span style="font-family: 'courier new', courier;">array_multisort</span>, <span style="font-family: 'courier new', courier;">arsort</span>, <span style="font-family: 'courier new', courier;">asort</span>, <span style="font-family: 'courier new', courier;">ksort</span>, <span style="font-family: 'courier new', courier;">krsort</span>, <span style="font-family: 'courier new', courier;">natsort</span>, <span style="font-family: 'courier new', courier;">natcasesort</span>, <span style="font-family: 'courier new', courier;">sort</span>, <span style="font-family: 'courier new', courier;">rsort</span>, <span style="font-family: 'courier new', courier;">uasort</span>, <span style="font-family: 'courier new', courier;">uksort</span>, <span style="font-family: 'courier new', courier;">usort</span>.</li>
<li style="text-align: justify;">Funciones que encuentran texto: <span style="font-family: 'courier new', courier;">ereg</span>, <span style="font-family: 'courier new', courier;">eregi</span>, <span style="font-family: 'courier new', courier;">mb_ereg</span>, <span style="font-family: 'courier new', courier;">mb_eregi</span>, <span style="font-family: 'courier new', courier;">preg_match</span>, <span style="font-family: 'courier new', courier;">strstr</span>, <span style="font-family: 'courier new', courier;">strchr</span>, <span style="font-family: 'courier new', courier;">stristr</span>, <span style="font-family: 'courier new', courier;">strrchr</span>, <span style="font-family: 'courier new', courier;">strpos</span>, <span style="font-family: 'courier new', courier;">stripos</span>, <span style="font-family: 'courier new', courier;">strrpos</span>, <span style="font-family: 'courier new', courier;">strripos</span>, <span style="font-family: 'courier new', courier;">mb_strpos</span>, <span style="font-family: 'courier new', courier;">mb_strrpos</span>, más las variaciones que hacen reemplazos.</li>
<li style="text-align: justify;">Hay muchos alias también, lo que ciertamente no ayuda al tema: <span style="font-family: 'courier new', courier;">strstr</span> / <span style="font-family: 'courier new', courier;">strchr</span>, <span style="font-family: 'courier new', courier;">is_int</span> / <span style="font-family: 'courier new', courier;">is_integer</span> / <span style="font-family: 'courier new', courier;">is_long</span>, <span style="font-family: 'courier new', courier;">is_float</span> / <span style="font-family: 'courier new', courier;">is_double</span>, <span style="font-family: 'courier new', courier;">pos</span> / <span style="font-family: 'courier new', courier;">current</span>, <span style="font-family: 'courier new', courier;">sizeof</span> / <span style="font-family: 'courier new', courier;">count</span>, <span style="font-family: 'courier new', courier;">chop</span> / <span style="font-family: 'courier new', courier;">rtrim</span>, <span style="font-family: 'courier new', courier;">implode</span> / <span style="font-family: 'courier new', courier;">join</span>, <span style="font-family: 'courier new', courier;">die</span> / <span style="font-family: 'courier new', courier;">exit</span>, <span style="font-family: 'courier new', courier;">trigger_error</span> / <span style="font-family: 'courier new', courier;">user_error</span>, <span style="font-family: 'courier new', courier;">diskfreespace</span> / <span style="font-family: 'courier new', courier;">disk_free_space</span>, &#8230;</li>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">scandir</span> devuelve un listado de archivos en un directorio dado. En lugar de (potencialmente útil) devolverlos en el orden del directorio, la función devuelve los archivos ya ordenados. Y hay un argumento opcional para obtenerlos en orden alfabético <em>inverso</em>. No había, aparentemente, suficientes funciones de ordenamiento. (PHP 5.4 agrega un tercer valor para la dirección del ordenamiento que deshabilitará el ordenamiento.)</li>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">str_split</span> partirá una cadena en pedazos de igual tamaño. <span style="font-family: 'courier new', courier;">chunk_split</span> parte una cadena en pedazos de igual tamaño y luego los une con un delimitador.</li>
<li style="text-align: justify;">Leer archivos requiere un conjunto separado de funciones dependiendo del formato. Hay seis grupos separados de esas funciones, todas con APIs diferentes, para bzip2, LZF, phar, rar, zip y gzip/zlib.</li>
<li style="text-align: justify;">Ya que llamar a una función con un array como sus argumentos es tan raro (<span style="font-family: 'courier new', courier;">call_user_func_array</span>), hay algunos pares como <span style="font-family: 'courier new', courier;">printf</span> / <span style="font-family: 'courier new', courier;">vprintf</span> y <span style="font-family: 'courier new', courier;">sprintf</span> / <span style="font-family: 'courier new', courier;">vsprintf</span>. Estos hacen lo mismo, pero una función toma argumentos y la otra toma un array de argumentos.</li>
</ul>
<h4>Texto</h4>
<ul>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">preg_replace</span> con la opción <span style="font-family: 'courier new', courier;">/e</span> (eval) hará un reemplazo de los resultados encontrados con una cadena de texto, y <em>luego la evalúa</em>.</li>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">strtok</span> está aparentemente diseñado desde la función C equivalente, la que ya es una mala idea por varias razones. Dejando de lado que PHP puede fácilmente deolver un array (mientras esto es raro en C), o que el mismo hack que <span style="font-family: 'courier new', courier;">strtok(3)</span> usa (modificando la cadena en-el-lugar) no es usada aquí.</li>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">parse_str</span> parsea un query string, con ninguna indicación en su nombre. También actúa igual que <span style="font-family: 'courier new', courier;">register_globals</span> y arroja el query en tu ámbito local como variables, a menos que le pases un array para que popule. (No devuelve nada, por supuesto.)</li>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">explode</span> se rehusa a separar cadenas con un limitador vacío o faltante. Todas las otras implementaciones de separación de cadenas hace algo útil en este caso; PHP en cambio tiene una función completamente separada, confusamente llamada <span style="font-family: 'courier new', courier;">str_split</span> y descripta como &#8220;convierte una cadena a un array&#8221;.</li>
<li style="text-align: justify;">Para formatear fechas, está <span style="font-family: 'courier new', courier;">strftime</span>, que actúa como la API de C y respeta el lugar. También está date, que tiene una sintaxis completamente distinta y sólo funciona en inglés.</li>
<li style="text-align: justify;">&#8220;<span style="font-family: 'courier new', courier;"><a href="http://php.net/manual/en/function.gzgetss.php">gzgetss</a> </span>&#8211; Obtiene una línea desde un puntero a un archivo gz y remueve las etiquetas HTML.&#8221; Me estoy muriendo por conocer la serie de circunstancias que llevaron a la concepción de esta función.</li>
<li><span style="font-family: 'courier new', courier;">mbstring</span>
<ul>
<li style="text-align: justify;">Es todo sobre &#8220;multi-byte&#8221;, cuando el problema son los conjuntos de caracteres.</li>
<li style="text-align: justify;">Aún así opera en cadenas comunes. Tiene un conjunto de caracteres &#8220;por defecto&#8221; global. Algunas funciones permiten un conjunto específico, pero luego aplica a todos los argumentos y el valor de retorno.</li>
<li style="text-align: justify;">Provee funciones <span style="font-family: 'courier new', courier;">ereg_*</span>, pero esas están obsoletas. <span style="font-family: 'courier new', courier;">preg_*</span> no tienen suerte, aunque pueden entender UTF-8 pasándoles un indicador PCRE específico.</li>
</ul>
</li>
</ul>
<h4>Sistema y reflexión</h4>
<ul>
<li style="text-align: justify;">Hay, en general, muchas funciones que bordean la línea entre texto y variables. <span style="font-family: 'courier new', courier;">compact</span> y <span style="font-family: 'courier new', courier;">extract</span> son sólo la punta del iceberg.</li>
<li style="text-align: justify;">Hay muchas formas de ser dinámico en PHP, y en una primera mirada no hay una diferencia obvia o beneficios orelativos. <span style="font-family: 'courier new', courier;">classkit</span> puede modificar clases definidas por el usuario; <span style="font-family: 'courier new', courier;">runkit</span> lo suplanta y puede modificar cualquier cosa definida por el usuario; las clases <span style="font-family: 'courier new', courier;">Reflection*</span> pueden reflexionar en la mayor parte del lenguaje; hay una buena cantidad de funciones individuales para reportar propiedades de funciones y clases. ¿Son estos subsistemas independientes, relacionados, redundantes?</li>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">get_class($obj)</span> devuelve el nombre de la clase del objeto, <span style="font-family: 'courier new', courier;">get_class()</span> devuelve el nombre de la clase de la función que lo llama. Dejando de lado que esta única función hace dos cosas radicalmente distintas: <span style="font-family: 'courier new', courier;">get_class(null)</span> funciona como el segundo. Por tanto no se lo puede confiar en un valor arbitrario. ¡Sorpresa!</li>
<li style="text-align: justify;">Las clases <span style="font-family: 'courier new', courier;">stream_*</span> permiten implementar objetos de flujos de datos personalizados para usar con <span style="font-family: 'courier new', courier;">fopen</span> y otros elementos inherentes archivezcos. &#8220;tell&#8221; no puede ser implementado por <a href="https://bugs.php.net/bug.php?id=30157">razones internas</a>. (También hay <a href="http://www.php.net/manual/en/book.stream.php">MUCHAS</a> funciones involucradas con este sistema.)</li>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">register_tick_function</span> aceptará un objeto clausura. <span style="font-family: 'courier new', courier;">unregister_tick_function</span> no; en lugar de eso arroja un error quejándose de que la clausura no puede ser convertida a cadena.</li>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">php_uname</span> te cuenta sobre el sistema operativo actual. A menos que PHP no pueda decir en qué está corriendo, en cuyo caso te cuenta sobre el sistema operativo en el que fue <em>compilado</em>. No te avisará si esto ocurrió.</li>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">fork</span> y <span style="font-family: 'courier new', courier;">exec</span> no son propios del lenguaje. Vienen con la extensión pcntl, pero no está incluida por defecto. <span style="font-family: 'courier new', courier;">popen</span> no provee un pid.</li>
<li style="text-align: justify;">El valor de retorno de <span style="font-family: 'courier new', courier;">stat</span> es cacheado.</li>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">session_decode</span> es para leer una cadena de sesión PHP arbitraria, pero sólo funciona si ya hay una sesión activa. Y deja el resultado en <span style="font-family: 'courier new', courier;">$_SESSION</span>, en lugar de devolverlo.</li>
</ul>
<h4>Misceláneos</h4>
<ul>
<li style="text-align: justify;"><span style="line-height: 13px;"><span style="font-family: 'courier new', courier;">curl_multi_exec</span> no cambia <span style="font-family: 'courier new', courier;">curl_errno</span> cuando ocurre un error, pero sí cambia <span style="font-family: 'courier new', courier;">curl_error</span>.</span></li>
<li style="text-align: justify;">Los argumentos de <span style="font-family: 'courier new', courier;">mktime</span> son, en orden: hora, minuto, segundo, mes, día, año.</li>
</ul>
<h3>Manipulación de datos</h3>
<p style="text-align: justify;">Los programas no son más que grandes máquinas que mastican datos y escupen más datos. Varios lenguajes grandiosos están diseñados <em>alrededor</em> de los tipos de datos que manipulan, desde awk hasta Prolog, hasta C. Si un lenguaje no puede manejar datos, no puede hacer nada.</p>
<h4>Números</h4>
<ul>
<li style="text-align: justify;"><span style="line-height: 13px;">Los enteros tienen signo y tienen 32 bits en plataformas de 32 bits. A diferencia de todos los contemporarios de PHP, no hay promoción automática a bigint. Por lo que puedes terminar con sorpresas como tamaños de archivos negativos, y tu matemática puede funcionar diferentemente basada en la <em>arquitectura del CPU</em>. Tu única opción para enteros más grandes es usar las funciones wrapper GMP o BC. (Los desarrolladores han propuesto <a href="http://www.php.net/~derick/meeting-notes.html#add-a-64bit-integer">añadir un nuevo tipo, separado, de 64 bits</a>. Esto es locura.)</span></li>
<li style="text-align: justify;">PHP soporta sintaxis octal con un <span style="font-family: 'courier new', courier;">0</span> inicial, por lo que, por ejemplo, <span style="font-family: 'courier new', courier;">012</span> será el número diez. Sin embargo, <span style="font-family: 'courier new', courier;">08</span> se convierte en el número cero. El <span style="font-family: 'courier new', courier;">8</span> (o <span style="font-family: 'courier new', courier;">9</span>) y cualquier dígito posterior desaparecen. <span style="font-family: 'courier new', courier;">01c</span> es un error de sintaxis.</li>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">0&#215;0+2</span> produce 4. El parser considera el <span style="font-family: 'courier new', courier;">2</span> como parte simultánea del literal hexadecimal <em>y</em> como un literal decimal separado, tratando esto como <span style="font-family: 'courier new', courier;">0&#215;002 + 2</span>. <span style="font-family: 'courier new', courier;">0&#215;0+0&#215;2</span> muestra el mimo problema. Extrañamente, <span style="font-family: 'courier new', courier;">0&#215;0 +2</span> es todavía 4, pero <span style="font-family: 'courier new', courier;">0&#215;0+ 2</span> es correctamente 2. (Esto se arregló en PHP 5.4. Pero también se volvió a romper en PHP 5.4 con el nuevo prefijo literal <span style="font-family: 'courier new', courier;">0b</span>: <span style="font-family: 'courier new', courier;">0b0+1</span> produce 2.)</li>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">pi</span> es una función. O hay una constante, <span style="font-family: 'courier new', courier;">M_PI</span>.</li>
<li style="text-align: justify;">No hay <a href="https://bugs.php.net/bug.php?id=13756">operador de exponenciación</a>, sólo la función <span style="font-family: 'courier new', courier;">pow</span>.</li>
</ul>
<h4>Texto</h4>
<ul>
<li style="text-align: justify;"><span style="line-height: 13px;">No hay soporte Unicode. Sólo ASCII trabajará confiablemente. Existe la extensión <span style="font-family: 'courier new', courier;">mbstring</span>, mencionada arriba, pero apesta un poco.</span></li>
<li style="text-align: justify;">Lo que significa que usar las funciones incorporadas en texto UTF-8 lo corrompe.</li>
<li style="text-align: justify;">Similarmente, no hay concepto de, por ejemplo, comparaciones de mayúsculas o minúsculas fuera de ASCII. A pesar de la proliferación de versiones insensitivas a la capitalización de las funciones, ninguna de ellas considerará <span style="font-family: 'courier new', courier;">é</span> igual a <span style="font-family: 'courier new', courier;">É</span>.</li>
<li style="text-align: justify;">No puedes encomillar claves en interpolación de variables, es decir, <span style="font-family: 'courier new', courier;">&#8220;$foo['key']&#8220;</span> es un error de sintaxis. Puedes des-encomillarlo (lo que <em>sí</em> generaría una advertencia en cualquier otro lugar!), o usar <span style="font-family: 'courier new', courier;">${&#8230;}</span>/<span style="font-family: 'courier new', courier;">{$&#8230;}</span>.</li>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">&#8220;${foo[0]}&#8221;</span> está bien. <span style="font-family: 'courier new', courier;">&#8220;${foo[0][0]}&#8221;</span> es un error de sintaxis. Poner el <span style="font-family: 'courier new', courier;">$</span> dentro está bien en ambos casos. ¿Mala copia de la sintaxis similar de Perl (con semánticas radicalmente distintas)?</li>
</ul>
<h4>Arreglos</h4>
<p>Oh&#8230;</p>
<ul>
<li style="text-align: justify;"><span style="line-height: 13px;">Este tipo de datos actúa como lista, hash ordenado, conjunto ordenado, lista dispersa, y ocasionalmente alguna combinación extraña de esos. ¿Cómo se desempeña? ¿Qué tipo de uso de memoria habrá ahí? ¿Quién sabe? De cualquier modo, no es como si tuviera otras opciones.</span></li>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">=&gt;</span> no es un operador. Es una construcción especial que sólo existe dentro de <span style="font-family: 'courier new', courier;">array(&#8230;)</span> y la construcción <span style="font-family: 'courier new', courier;">foreach</span>.</li>
<li style="text-align: justify;">El indexado negativo no funciona, ya que <span style="font-family: 'courier new', courier;">-1</span> es una clave válida como <span style="font-family: 'courier new', courier;">0</span>.</li>
<li style="text-align: justify;">A pesar de que esta es la única estructura de datos del lenguaje, no hay sintaxis corta para él; <span style="font-family: 'courier new', courier;">array(&#8230;)</span> es la sintaxis corta. (PHP 5.4 trae &#8220;literales&#8221;, <span style="font-family: 'courier new', courier;">[...]</span>.)</li>
<li style="text-align: justify;">La construcción <span style="font-family: 'courier new', courier;">=&gt;</span> está basada en Perl, que permite <span style="font-family: 'courier new', courier;">foo =&gt; 1</span>, sin comillas. (Eso es, de hecho, porque existen en Perl; de otra forma es sólo una coma.) En PHP no puedes hacer esto sin obtener una advertencia; es el único lenguaje en su nicho que no tiene forma aprobada de crear un hash sin encomillar las claves de cadena.</li>
<li style="text-align: justify;">Las funciones de arreglos por lo general tienen comportamietno confuso o inconsistente porque tienen que operar en listas, hashes o quizá una combinación de los dos. Consideren <span style="font-family: 'courier new', courier;">array_diff</span>, que &#8220;computa la diferencia de los arreglos&#8221;.<br />
<span style="font-family: 'courier new', courier;">$primero = array(&#8220;foo&#8221; =&gt; 123, &#8220;bar&#8221; =&gt; 456);</span><br />
<span style="font-family: 'courier new', courier;">$segundo = array(&#8220;foo&#8221; =&gt; 456, &#8220;bar&#8221; =&gt; 123);</span><br />
<span style="font-family: 'courier new', courier;">echo var_dump(array_diff($primero, $segundo));</span><br />
¿Qué hará este código? Si <span style="font-family: 'courier new', courier;">array_diff</span> trata sus argumentos como hashes, obviamente estos son diferentes; las mismas claves tienen distintos valores. Si los trata como listas, aún son distintas; los valores están en orden distinto.<br />
En realidad <span style="font-family: 'courier new', courier;">array_diff</span> considera a estos iguales, porque los trata como <em>conjuntos</em>, compara solamente valores e ignora el orden.</li>
<li style="text-align: justify;">En una vena similar, <span style="font-family: 'courier new', courier;">array_rand</span> tiene el extraño comportamiento de seleccionar <em>claves</em> al azar, que no es tan útil para el caso más común de necesitar elegir de un listado de opciones.</li>
<li style="text-align: justify;">A pesar de lo mucho que el código PHP recae en preservar el orden de las claves:<br />
<span style="font-family: 'courier new', courier;">array(&#8220;foo&#8221;, &#8220;bar&#8221;) != array(&#8220;bar&#8221;, &#8220;foo&#8221;)</span><br />
<span style="font-family: 'courier new', courier;">array(&#8220;foo&#8221; =&gt; 1, &#8220;bar&#8221; =&gt; 2) == array(&#8220;bar&#8221; =&gt; 2, &#8220;foo&#8221; =&gt; 1)</span><br />
Dejo como ejercicio al lector averiguar qué ocurre si los arreglos son mezclas. (Yo no lo sé.)</li>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">array_fill</span> no puede crear arreglos de tamaño cero, en lugar de eso emitirá una advertencia y devolverá falso.</li>
<li style="text-align: justify;">Todas de las (muchas&#8230;) funciones de ordenamiento operan en-el-lugar y no devuelven nada. No hay forma de crear una copia ordenada; hay que copiar el arreglo manualmente, luego ordenarlo, y luego usarlo.</li>
<li style="text-align: justify;">Pero <span style="font-family: 'courier new', courier;">array_reverse</span> devuelve un nuevo arreglo.</li>
<li style="text-align: justify;">Un listado de cosas ordenadas y algunos mapeos de claves a valores suena como una gran manera de manejar argumentos de funciones, pero no.</li>
</ul>
<h4>No arreglos</h4>
<ul>
<li style="text-align: justify;"><span style="line-height: 13px;">La librería estándar incluye &#8220;Quickhash&#8221;  una implementación OO de &#8220;clases específicas fuertemente tipadas&#8221; para implementar hashes. Y, efectivamente, hay cuatro clases, cada una tratando una combinación distinta de tipos de claves y valores. No está claro por qué la implementación incorporada de arreglos no puede optimizar para estos casos extremadamente comunes, o lo que la performance relativa es.</span></li>
<li style="text-align: justify;">Hay una clase <span style="font-family: 'courier new', courier;">ArrayObject</span> (que implemente <em>cinco</em> interfaces distintas) que puede envolver a un arreglo y permitirle actuar como objeto. Las clases de usuario pueden implementar las mismas interfaces. Pero sólo tienen un puñado de métodos, la mitad de los cuales no se parecen a las funciones incorporadas, y las funciones incorporadas de arreglos no saben cómo operar con un <span style="font-family: 'courier new', courier;">ArrayObject</span> o cualquier otra clase parecida a arreglos.</li>
</ul>
<h4>Funciones</h4>
<ul>
<li style="text-align: justify;">Las funciones no son datos. Las clausuras son de hecho objetos, pero las funciones comunes no. No puedes referirte a ellas con sus nombres; <span style="font-family: 'courier new', courier;">var_dump(strstr)</span> emite una advertenia y asume que querías la cadena <span style="font-family: 'courier new', courier;">literal &#8220;strstr&#8221;</span>. No hay manera de discernir entre una cadena arbitraria y una &#8220;referencia&#8221; a función.</li>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">create_function</span> es básicamente un wrapper alrededor de <span style="font-family: 'courier new', courier;">eval</span>. Crea una función con un nombre común y la instala globalmente (para que nunca sea recolectada por el recolector de basura &#8212; ¡no la uses en un bucle!). De hecho no sabe nada sobre el ámbito actual, por lo que no es una clausura. El nombre contiene un byte <span style="font-family: 'courier new', courier;">NUL</span> para que nunca pueda entrar en conflicto con una función común (porque el parser de PHP falla si hay un <span style="font-family: 'courier new', courier;">NUL</span> en el archivo, en algún lado).</li>
<li style="text-align: justify;">Declarar una función llamada <span style="font-family: 'courier new', courier;">__lambda_func</span> romperá <span style="font-family: 'courier new', courier;">create_function</span> &#8212; la implementación real es llamar a <span style="font-family: 'courier new', courier;">eval</span>, crear la función llamada <span style="font-family: 'courier new', courier;">__lambda_func</span>, e internamente renombrarla al nombre roto. Si <span style="font-family: 'courier new', courier;">__lamda_func</span> ya existe, la primera parte arrojará un error fatal.</li>
</ul>
<h4>Otros</h4>
<ul>
<li style="text-align: justify;"><span style="line-height: 13px;">Incrementar (<span style="font-family: 'courier new', courier;">++</span>) un <span style="font-family: 'courier new', courier;">NULL</span> produce <span style="font-family: 'courier new', courier;">1</span>. Decrementar (<span style="font-family: 'courier new', courier;">&#8211;</span>) un <span style="font-family: 'courier new', courier;">NULL</span> produce <span style="font-family: 'courier new', courier;">NULL</span>. Decrementar una cadena de la misma forma la deja sin cambios.</span></li>
<li style="text-align: justify;">No hay generadores.</li>
</ul>
<h3>Framework web</h3>
<h4>Ejecución</h4>
<ul>
<li style="text-align: justify;"><span style="line-height: 13px;">Un único archivo <span style="font-family: 'courier new', courier;">php.ini</span> compartido controla partes <em>masivas</em> de la funcionalidad de PHP e introduce reglas complejas respecto de qué se antepone a qué y cuándo. El software PHP que espera ser instalado en máquinas arbitrarias tiene que reescribir configuraciones de todos modos para normalizar su entorno, lo que derrota en mayor parte el uso de un mecanismo como php.ini de todos modos.</span>
<ul>
<li>PHP busca a <span style="font-family: 'courier new', courier;">php.ini</span> en varios lugares, por lo que puede (o puede que no) ser posible que se anteponga al de tu host. Sólo <em>un</em> archivo de esos será parseado, sin embargo, por lo que no puedes sobreescribir un par de configuraciones y terminar ahí.</li>
</ul>
</li>
<li style="text-align: justify;">PHP básicamente corre como CGI. Cada vez que una página es alcanzada, PHP recompila toda la cosa antes de ejecutarse. Incluso los frameworks de juguete de servidores de Python no actúan así.<br />
Esto ha llevado a un mercado completo de &#8220;aceleradores de PHP&#8221; que sólo compilan una vez, acelerando PHP hasta el nivel de cualquier otro lenguaje. Zend, la compañía detrás de PHP, ha hecho esto parte de su <a href="http://www.zend.com/products/server/">modelo de negocios</a>.</li>
<li style="text-align: justify;">Por un tiempo algo largo, los errores PHP iban al cliente por defecto &#8212; supongo que para ayudar durante el desarrollo. No creo que esto siga siendo verdad, pero todavía veo el error de mysql siendo escupido al principio de alguna página.</li>
<li style="text-align: justify;">PHP está lleno de extraños &#8220;huevos de pascua&#8221;, como <a href="http://phpsadness.com/sad/11">producir el logo de PHP con el argumento correcto</a>. No sólo es esto completamente irrelevante a construir <em>tu</em> aplicación, sino que permite a cualquiera detectar si estás usando PHP (y quizá incluso estimar aproximadamente la versión), a pesar de cuántas configuraciones <span style="font-family: 'courier new', courier;">mod_rewrite</span>, FastCGI, proxy inverso o <span style="font-family: 'courier new', courier;">Server:</span> tengas.</li>
<li style="text-align: justify;">Las líneas en blanco antes o después de los tags <span style="font-family: 'courier new', courier;">&lt;?php &#8230; ?&gt;</span>, incluso en librerías, cuentan como texto literal y es interpolado en la respuesta (o causa errores de &#8220;cabeceras ya enviadas&#8221;). Tus opciones son o estrictamente evitar líneas extras al final de cada archivo (el siguiente luego de <span style="font-family: 'courier new', courier;">?&gt;</span> no cuenta), o simplemente evitar el token de cerrado <span style="font-family: 'courier new', courier;">?&gt;</span>.</li>
</ul>
<h4>Implantanción</h4>
<p style="text-align: justify;">La implantación por lo general se cita como una de las mayores ventajas de PHP: copiar algunos archivos y listo. En verdad, eso es mucho más fácil que correr un proceso completo como puede que tengas que hacer en Python, Ruby o Perl. Pero PHP deja mucho que desear.</p>
<p style="text-align: justify;">En todas partes estoy en favor de correr las aplicaciones web como servidores de aplicación y hacer proxies reversos a ellos. Toma un esfuerzo mínimo configurar esto y los beneficios son muchos: puedes manjar tu servidor web y tu aplicación separadamente, puedes correr tantos o tan pocos procesos de la aplicación en tantas máquinas como quieras sin necesitar más servidores web, puedes correr la aplicación con un usuario diferente con cero esfuerzo, puedes cambiar de servidores web, puedes bajar la aplicación sin tocar el servidor web, puedes hacer implantación continua solo cambiando unos puntos fifo, etc. Malear tu aplicación a tu servidor web es absurdo y no hay una buena razón para hacerlo más.</p>
<ul>
<li style="text-align: justify;"><span style="line-height: 13px;">PHP está naturalmente atado a Apache. Correrlo separadamente, o con cualquier otro web server requiere igual de trabajo (posiblemente más) que implantar cualquier otro lenguaje.</span></li>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">php.ini</span> se aplica a cada aplicación en cualquier lugar. Hay un único archivo <span style="font-family: 'courier new', courier;">php.ini</span>, y aplica globalmente; si estás en un server compartido y necesitas cambiarlo, o si corres dos aplicaciones que necesitan configuraciones distintas, no tuviste suerte; tienes que aplicar la unión de todas las configuraciones y diferenciarlas desde dentro de las aplicaciones mismas usando <span style="font-family: 'courier new', courier;">init_set</span> o en el archvio de configuración de Apache o en .htaccess. Si puedes. También wow, hay un montón de lugares que necesitas checkear para darte cuenta de cómo una configuración está obteniendo su valor.</li>
<li style="text-align: justify;">Similarmente, no hay forma de &#8220;aislar&#8221; una aplicación PHP y sus dependencias del resto del sistema. ¿Correr dos aplicaciones que requieren diferentes versiones de una librería, o incluso de PHP mismo? Comienza construyendo una segunda copia de Apache.</li>
<li style="text-align: justify;">La aproximación de &#8220;un montón de archivos&#8221;, aparte de hacer el ruteo un gran dolor de trasero, también significa que debes cuidadosamente abilitar o deshabilitar lo que está de hecho visible, porque tu jerarquía de URLs es también tu árbol de código entero. Los archivos de configuración otros &#8220;parciales&#8221; necesitan guardas C-simil para prevenir que sean cargados directamente. El ruido de control de versiones (e.g., <span style="font-family: 'courier new', courier;">.svn</span>) necesita protección. Con mod_php, <em>todo</em> en tu sistema es un punto potencial de entrada; con un servidor de aplicación, hay un sólo punto de entrada y la única URL controla si es invocada.</li>
<li style="text-align: justify;">No puedes hacer una actualización continua de un montón de archivos que corren estilo-CGI, a menos que quieras crashes y comportamiento indefinido a medida que los usuarios llegan a tu sitio a medio camino de la actualización.</li>
<li style="text-align: justify;">A pesar de lo &#8220;simple&#8221; que es de configurar Apache para que corra PHP, hay trampas sutiles incluso ahí. Mientras la documentación de PHP sugiere usar <span style="font-family: 'courier new', courier;">SetHandler</span> para hacer que los archivos .php corran como PHP, <span style="font-family: 'courier new', courier;">AddHandler</span> parece funcionar igual de bien, y de hecho Google me da el doble de resultados para él. Aquí está el problema.<br />
Cuando usas <span style="font-family: 'courier new', courier;">AddHandler</span>, le estás diciendo a Apache que &#8220;ejecutar esto como php&#8221; es <em>una posible </em>forma de ejecutar archivos .php. ¡<strong>Pero</strong>! Apache no tiene la misma idea de las extensiones de archivos que cualquier otro humano en el planeta tiene. Está diseñado para soportar, digamos, <span style="font-family: 'courier new', courier;">index.html.en</span> siendo reconocido ambos como inglés y como HTML. Para apache, un archivo puede tener <em>cualquier número</em> de extensiones simultáneamente.<br />
Imagina que tienes un formulario de subida de archivos en un directorio público. Para asegurarte que nadie suba archivos php, solo verificas que no tengan una extensión <span style="font-family: 'courier new', courier;">.php</span>. Todo lo que un atacante tiene que hacer es subir un archivo llamado <span style="font-family: 'courier new', courier;">foo.php.txt</span>; tu formulario no verá el problema, pero Apache <em>lo reconocerá</em> como PHP y lo ejecutará alegremente.<br />
El problema aquí no es &#8220;usar el nombre de archivo original&#8221; o &#8220;no validar mejor&#8221;, el problema es que tu servidor web está configurado para correr cualquier código con el que se encuentre &#8212; precisamente la misma propiedades que hace a PHP &#8220;fácil de implantar&#8221;. CGI requería, <span style="font-family: 'courier new', courier;">+x</span>, que era <em>algo</em>, pero PHP ni siquiera eso. Y esto no es un problema teórico; he encontrado muchos sitios actuales con este problema.</li>
</ul>
<h4>Características faltantes</h4>
<p style="text-align: justify;">Considero todas estas ser de distinto nivel de crítico para construir una aplicación web. Parece razonable que PHP, con su mayor punto de venta siendo que es un &#8220;lenguaje web&#8221;, debería tener algunas de ellas.</p>
<ul>
<li style="text-align: justify;"><span style="line-height: 13px;">No hay sistema de templates. Está PHP en sí mismo, pero nada que funcione como un gran interpolador más que un programa.</span></li>
<li style="text-align: justify;">No hay filtros de XSS. No, &#8220;recuerda usar <span style="font-family: 'courier new', courier;">htmlspecialchars</span>&#8221; no es un filtro XSS. <a href="https://pypi.python.org/pypi/MarkupSafe">Esto es</a>.</li>
<li style="text-align: justify;">No hay protección CSRF. Te toca hacerlo a tí.</li>
<li style="text-align: justify;">No hay API estándar de base de datos. Cosas como PDO tienen que envolver cada llamada individual a la API para abstraer las diferencias.</li>
<li style="text-align: justify;">No hay ruteo. Tu website se ve exactamente igual que tu sistema de archivos. Muchos desarrolladores han sido engañados en pensar que <span style="font-family: 'courier new', courier;">mod_rewrite</span> (y <span style="font-family: 'courier new', courier;">.htaccess</span> en general) es un sustituto aceptable.</li>
<li style="text-align: justify;">No hay autenticación o autorización.</li>
<li style="text-align: justify;">No hay servidor de desarrollo. (&#8220;Arreglado&#8221; en 5.4. Llevó a la vulnerabilidad de <span style="font-family: 'courier new', courier;">Content-Length</span> de más abajo. También, tienes que portar todas tus reglas de rewrite a una cosa que envuelve PHP, porque no hay ruteo.)</li>
<li style="text-align: justify;">No hay debugging interactivo.</li>
<li style="text-align: justify;">No hay un mecahismo de implantación coherente; sólo &#8220;copiar todos estos archivos al servidor&#8221;.</li>
</ul>
<h3>Seguridad</h3>
<h4>Límites del lenguaje</h4>
<p style="text-align: justify;">La reputación de seguridad pobre de PHP es en mayor parte porque toda datos arbitrarios de un lenguaje y los tira en otro. Esto es mala idea. <span style="font-family: 'courier new', courier;">&#8220;&lt;script&gt;&#8221;</span> puede no significar nada en SQL, pero ciertamente lo hace en HTML.</p>
<p style="text-align: justify;">Haciendo esto peor está el grito común por &#8220;sanitizar tus entradas&#8221;. Esto está completamente <em>equivocado</em>; no puedes mover una varita mágica para hacer que un montón de datos estén inherentemente &#8220;limpios&#8221;. Lo que necesitas es hablar el lenguaje: usar placeholders con SQL, usar listas de argumentos cuando se generan procesos, etc.</p>
<ul style="text-align: justify;">
<li>PHP completamente <em>alienta</em> el &#8220;sanitizado&#8221;: hay una <a href="http://www.php.net/manual/en/book.filter.php">extensión de filtrado de datos</a> entera para hacer eso.</li>
<li>Todos los <span style="font-family: 'courier new', courier;">addslashes</span>, <span style="font-family: 'courier new', courier;">stripslashes</span> y otros sinsentidos relacionados-a-slashes son distracciones que no ayudan en nada.</li>
<li>No hay, hasta lo que puedo decir, una forma segura de instanciar un proceso. SÓLO puedes ejecutarlo a través de una cadena por la línea de comandos. Tus opciones son escapar como loco y esperar que la línea de comandos por defecto use el escapado correcto, o <span style="font-family: 'courier new', courier;">pcntl_fork</span> y <span style="font-family: 'courier new', courier;">pcntl_exec</span> <em>manualmente</em>.</li>
<li>Ambos <span style="font-family: 'courier new', courier;">escapeshellcmd</span> y <span style="font-family: 'courier new', courier;">escapeshellarg</span> existen con descripciones vagamente similares. Noten que en Windows, <span style="font-family: 'courier new', courier;">escapeshellarg</span> no funciona (porque asume semántica de la línea de comandos Bourne) y <span style="font-family: 'courier new', courier;">escapeshellcmd</span> sólo reemplaza un montón de puntuación con espacios porque nadie puede entender cómo funciona el escapado de comandos de Windows (que puede silenciosamente romper todo lo que estés intentando hacer).</li>
<li>Los bindeos originales incorporados para MySQL, todavía ampliamente usados, no tienen forma de crear instrucciones preparadas.</li>
</ul>
<p style="text-align: justify;">Al día de hoy, <a href="http://www.php.net/manual/en/security.database.sql-injection.php">la documentación de PHP sobre inyección SQL</a> recomienda prácticas locas como checkeo de tipos, usando <span style="font-family: 'courier new', courier;">sprintf</span> y <span style="font-family: 'courier new', courier;">is_numeric</span>, manualmente usando <span style="font-family: 'courier new', courier;">mysql_real_escape_string</span> en todos lados, o manualmente usar <span style="font-family: 'courier new', courier;">addslashes</span> en todos lados (que ¡&#8221;puede ser útil&#8221;!). No hay mención de PDO o parametrización, excepto en los comentarios de los usuarios. Me quejé de este hecho específicamente a <em>un desarrollador de PHP</em> al menos hace dos años, estaba alarmado, y la página nunca cambió.</p>
<h4>Inseguro-por-defecto</h4>
<ul>
<li style="text-align: justify;"><span style="line-height: 13px;"><span style="font-family: 'courier new', courier;">register_globals</span>. Está desactivado por defecto desde hace un tiempo ya, y se fue en 5.4. No me importa. Es una <em>vergüenza</em>.</span></li>
<li style="text-align: justify;"><span style="font-family: 'courier new', courier;">include</span> aceptando URLs HTTP. Igual.</li>
<li style="text-align: justify;">Comillas mágicas. Tan cerca a seguro-por-defecto y aún así tan lejos de comprender el concepto totalmente. E, igual.</li>
<li style="text-align: justify;">Puedes, digamos, <a href="http://www.idontplaydarts.com/2011/02/scanning-the-internal-network-using-simplexml/">escanear una red</a> usando el soporte XML de PHP, y abusando su soporte ubicuo de nombres-de-archivos-como-URLs. Sólo <span style="font-family: 'courier new', courier;">libxml_disable_entity_loader()</span> puede arreglar esto, y el problema sólo está mencionado en los comentarios del manual.</li>
</ul>
<h4>Núcleo</h4>
<p style="text-align: justify;">El intérprete de PHP mismo ha tenido algunos problemas de seguridad <em>fascinantes</em><em>.</em></p>
<ul style="text-align: justify;">
<li><span style="line-height: 13px;">En 2007 el intérprete tuvo una vulnerabilidad de desbordamiento de enteros. El arreglo comenzó con if (size &gt; INT_MAX) return NULL; y se fue <a href="http://use.perl.org/use.perl.org/_Aristotle/journal/33448.html">en picada desde allí</a>. (Para aquellos que no estén cómodos con el C: <span style="font-family: 'courier new', courier;">INT_MAX</span> es el mayor entero que entrará en una variable, nunca. Espero que puedan darse cuenta del resto desde ahí.)</span></li>
<li>Más recientemente, PHP 5.3.7 se las arregló para incluir una función crypt() que permitiría, en efecto, a <a href="https://bugs.php.net/bug.php?id=55439">cualquiera loggearse sin un password</a>.</li>
<li>El servidor de desarrollo de PHP 5.4 es vulnerable a una denegación de servicio, porque toma el header <span style="font-family: 'courier new', courier;">Content-Length</span> (que cualquiera puede setear a cualquier cosa) y trata de alocar eso en memoria. <a href="http://www.exploit-db.com/exploits/18665/">Esto es una mala idea</a>.</li>
</ul>
<p style="text-align: justify;">Podría seguir desenterrando más, pero el punto no es que hay X exploits &#8212; el software siempre tiene bugs, pasa, no importa. La <em>naturaleza</em> de estos es horripilante. Y no me puse a buscar estos; sólo aparecieron en mi puerta en los últimos meses.</p>
<hr style="width: 75%;" width="75%" />
<h2>Conclusión</h2>
<p style="text-align: justify;">Algún comentarista ha correctamente señalado que no tengo una conclusión. Y, bueno, no tengo una conclusión. Si llegaste hasta aquí, asumo que estabas de acuerdo conmigo antes de haber comenzado. :)</p>
<p style="text-align: justify;">Si sólo sabes PHP y estás curioso de aprender algo más, dale un intento al <a href="http://docs.python.org/2/tutorial/">tutorial de Python</a> y trata con <a href="http://flask.pocoo.org/">Flask</a> para la parte web. (No soy un fanático de su lenguaje de templates, pero cumple con su trabajo.) Desarma las piezas de tu aplicación, pero son aún las mismas piezas y deberían ser lo suficientemente familiares. Podría escribir un post real sobre esto más tarde; una intrducción remolino a un lenguaje entero y tecnologías web no pertenece aquí abajo.</p>
<p style="text-align: justify;">Más tarde o para projectos más grandes podrías querer <a href="http://www.pylonsproject.org/">Pyramid</a>, que es nivel-medio, o <a href="https://www.djangoproject.com/">Django</a>, que es una monstruosidad compleja que trabaja muy bien para construir sitios como el de Django.</p>
<p style="text-align: justify;">Si no eres un desarrollador para nada pero aún leiste esto por alguna razón, no estaré feliz hasta que cualquiera en el planeta haya pasado por <a href="http://learnpythonthehardway.org/">Aprender Python de la Manera Difícil</a>, así que ve a hacer eso.</p>
<p style="text-align: justify;">Está también Ruby on Rails y algunos competidores que no he usado nunca, y Perl sigue vivo y coleando con Catalyst. Lee cosas, aprende cosas, construye cosas, vuélvete loco.</p>
<h2>Créditos</h2>
<p style="text-align: justify;">Gracias a los siguientes por la inspiración:</p>
<ul style="text-align: justify;">
<li><a href="http://alokmenghrajani.github.io/wtf/php.html"><span style="line-height: 13px;">PHP Turtles</span></a></li>
<li><a href="http://phpsadness.com/">PHP Sadness</a></li>
<li><a href="http://www.phpwtf.org/">PHP WTF</a></li>
<li><a href="https://wiki.theory.org/YourLanguageSucks#PHP_sucks_because%3A">YourLanguageSucks</a></li>
<li><a href="http://tnx.nl/php.html">PHP in contrast to Perl</a></li>
<li><a href="http://two-pi-r.livejournal.com/622760.html">La densa, furiosa e inspiracional bronca de Pi</a></li>
<li><a href="http://tracks.ranea.org/post/13908062333/php-is-not-an-acceptable-cobol">PHP is not an acceptable COBOL</a></li>
<li><a href="http://www.php.net/manual/en/index.php">La documentación PHP</a></li>
<li>un montón de fanáticos y contra-fanáticos PHP</li>
<li>y, por supuesto, Rasmus Lerdorf por su salvaje mala interpretación de la mayoría de Perl</li>
</ul>
<p style="text-align: justify;">Háganme saber si tienen adiciones, o si estoy (¡con hechos!) equivocado sobre algo.</p>

<div class="wp_rp_wrap  wp_rp_plain" ><div class="wp_rp_content"><h3 class="related_post_title">Posts relacionados:</h3><ul class="related_post wp_rp" style="visibility: visible"><li data-position="0" data-poid="in-2218" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2010/07/14/link-del-dia-ahora-hay-que-reaprender-php/" class="wp_rp_title">Link del día: Ahora hay que reaprender PHP</a></li><li data-position="1" data-poid="in-3877" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2012/05/11/pruebas-con-vs11-dia-uno/" class="wp_rp_title">Pruebas con VS11: Día uno</a></li><li data-position="2" data-poid="in-2028" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2010/04/13/link-del-dia-snippets-de-codigo-listos-para-usar/" class="wp_rp_title">Link del día: Snippets de código listos para usar</a></li><li data-position="3" data-poid="in-2145" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2010/05/31/link-del-dia-consejitos-jquery-mysql-ajax-y-php/" class="wp_rp_title">Link del día: Consejitos jQuery, MySQL, AJAX y PHP</a></li><li data-position="4" data-poid="in-2799" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2011/02/04/link-del-dia-seguridad-ante-robos/" class="wp_rp_title">Link del día: Seguridad ante robos</a></li></ul></div></div>
<img src="http://feeds.feedburner.com/~r/zorri/~4/hiG34ZjTpA4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.alphasmanifesto.com/2013/04/15/php-un-fractal-de-un-mal-diseno/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://blog.alphasmanifesto.com/2013/04/15/php-un-fractal-de-un-mal-diseno/</feedburner:origLink></item>
		<item>
		<title>Películas Misceláneas</title>
		<link>http://feedproxy.google.com/~r/zorri/~3/-Gh1YMsls6Q/</link>
		<comments>http://blog.alphasmanifesto.com/2013/04/15/peliculas-miscelaneas/#comments</comments>
		<pubDate>Mon, 15 Apr 2013 23:32:24 +0000</pubDate>
		<dc:creator>Alpha</dc:creator>
				<category><![CDATA[Películas]]></category>
		<category><![CDATA[animación]]></category>
		<category><![CDATA[bizarro]]></category>
		<category><![CDATA[chistes]]></category>
		<category><![CDATA[comedia]]></category>
		<category><![CDATA[drama]]></category>
		<category><![CDATA[paranormal]]></category>
		<category><![CDATA[película]]></category>
		<category><![CDATA[reseña]]></category>
		<category><![CDATA[review]]></category>
		<category><![CDATA[terror]]></category>

		<guid isPermaLink="false">http://blog.alphasmanifesto.com/?p=4585</guid>
		<description><![CDATA[Entre finales del año pasado y comienzos de este vi varias películas que nunca comenté por aquí. Tengo mis ideas anotadas al respeto pero pasado el tiempo no creo que valga la pena dedicarle un post a cada una. Las razones son dos: por un lado habría demasiado post sobre películas, y por otro lado, [...]]]></description>
				<content:encoded><![CDATA[<p><img class="aligncenter size-full wp-image-4753" alt="Movies!" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/04/MooVees-small.jpg" width="800" height="511" /></p>
<p style="text-align: justify;">Entre finales del año pasado y comienzos de este vi varias películas que nunca comenté por aquí. Tengo mis ideas anotadas al respeto pero pasado el tiempo no creo que valga la pena dedicarle un post a cada una. Las razones son dos: por un lado habría demasiado post sobre películas, y por otro lado, han perdido relevancia al no ser tan actuales.</p>
<p style="text-align: justify;">Entonces, las películas que recibirán mi calificación aquí serán (sin ningún orden en particular):</p>
<ul>
<li style="text-align: justify;">Hotel Transylvania</li>
<li style="text-align: justify;"><span style="line-height: 13px;">Paranormal Activity 4</span></li>
<li style="text-align: justify;">Wreck it Ralph</li>
<li style="text-align: justify;">The Man With the Iron Fists</li>
<li style="text-align: justify;">Life of Pi</li>
<li style="text-align: justify;">Don&#8217;t be afraid of the dark</li>
<li style="text-align: justify;">Cirque Du Soleil: Worlds Away</li>
<li style="text-align: justify;">Mama</li>
<li style="text-align: justify;">The Croods</li>
</ul>
<p><span id="more-4585"></span></p>
<h2>Hotel Transylvania</h2>
<p style="text-align: justify;">Una de las películas del 2012 que más me gustó fue Hotel Transylvania. A pesar de lo predecible e infantil de su trama, realmente está llena de pequeños gags que la hacen divertida desde comienzo a final.</p>
<p style="text-align: justify;">Es raro ver una película de animación que le de un tono renovado a los monstruos de terror, aunque lo sea ligeramente. Esta es una de esas, en donde, más allá de algunos ridículos, eso se da y con un pre-supuesto algo razonable: según la historia, Drácula construyó un hotel para monstruos, porque la humanidad les tiene miedo y se vuelve violenta hacia ellos. Por tanto, viven en el secreto y sólo se juntan una vez por año para celebrar en Halloween, cuando viajar y ser vistos no es un gran problema.</p>
<p style="text-align: justify;">Pero la trama se centra en una historia más personal. La hija de Drácula, Mavis, siempre vivió encerrada en su castillo/hotel y se muere por conocer el mundo. Cumpliendo ahora ciento diechiocho años (adolescente para vampiros) quiere salir a conocer el mundo y su padre sabe cómo tratar con ese problema&#8230; hasta que un humano mismo entra, perdido, al hotel.</p>
<p style="text-align: justify;">No hay mucho más que decir, la historia no es profunda y la animación es muy buena, pero no sobresaliente. La película en sí es tierna cuando debe serlo y graciosa cuando tiene la oportunidad. Quizá resaltaría que hay un poco de profundidad para Drácula cuando él comparte u historia y motivación personal. Para aquellos que sepan a qué momento me refiero, yo creo que podría haber sido más interesante si resultara que un personaje común a él y a Mavis tuviera más en común con Jonathan. Ustedes entenderán.</p>
<p style="text-align: justify;">En fin, es una película entretenida, colorida y graciosa. Más de lo que en general puedo decir de las peliculas de Adam Sandler, pero la voy a aceptar. <strong>Le doy 3 zorrinitos de 5.</strong></p>
<h2>Paranormal Activity 4</h2>
<p style="text-align: justify;">Realmente no esperaba mucho de esta película, y no obtuve demasiado. La primera película me había gustado mucho: era novedosa en la forma en la que presentaba los hechos (bueno, medianamente), y parecía tener una historia por detrás. La segunda la extendió un poco, intentando explicar algunas cosas pero sin ahondar demasiado. La tercera fue una película que podría perderse en la historia sin lamentos para la humanidad y la cuarta fue irrelevante. En serio, irrelevante, porque la conexión con las películas anteriores es demasiado vaga.</p>
<p style="text-align: justify;">No puedo decir que me gustara porque abusan del recurso del shock-terror, es decir, simplementer asustar a uno con ruidos fuertes y cosas que aparecen súbitamente. El terror psicológico que la historia generaba lo tenía más elaborado en las primeras dos películas.</p>
<p style="text-align: justify;">Otra película que nadie recordará el siglo que viene. <strong>Le otorgo 2 de 5 zorrinitos.</strong></p>
<h2>Wreck it Ralph</h2>
<p style="text-align: justify;">Por el contrario, Wrick it Ralph me sorprendió para bien. Ciertamente no esperaba una historia compleja, y si bien no requiere de una atención detallista, esta película le da a su historia algunos vuelcos sorprendentes, quizá predecibles, pero comprensibles y factibles. No me pareció que ninguno de los hechos que ocurrieron fueran sacados de la galera y me agradó mucho la forma en la que los problemas se complicaron de muchas formas.</p>
<p style="text-align: justify;">Más aún, me encantó que esta, como tantas otras películas, le da al villano buenas razones. Bueno, realmente no, pero no quiero spoilear la película. Digamos que mientras transcurren los eventos, se ven distintos puntos de vista sobre un problema, y cada punto de vista es, en cierta forma, válido. Eso hace el conflicto moral muy interesante, y ciertamente aquí ocurrió.</p>
<p style="text-align: justify;">Por último, tiene muchos chistes ingeniosos y para los amantes de los videojuegos, miles de referencias para buscar.</p>
<p style="text-align: justify;"><strong>Le doy 4 de 5 zorrinitos.</strong></p>
<h2>The Man With the Iron Fists</h2>
<p style="text-align: justify;">Esta película califica de bizarra, y no estoy seguro de si esa fue la intención. Al menos yo, es lo que esperaba y no me desilusionó, pero no la categorizaría de esencialmente buena. La historia se presenta en una mezcla de película de artes marciales con un héroe americano (¿por qué?) y una historia de clanes y traiciones. La realización del título de la película aparece ya muy avanzada la trama y no es racional. Sólo mirenlá sin expectativas y no se aburrirán.</p>
<p style="text-align: justify;">Debo decir que lo que más me gustaron fueron las escenas de acción. De la forma en la que lo esperaba, muchas de ellas se mostraron como hermosas coreografías con violencia y gore incluido.</p>
<p style="text-align: justify;"><strong>Le otorgo 2 de 5 zorrinitos.</strong></p>
<h2>Life of Pi</h2>
<p style="text-align: justify;">Me gustó el concepto, pero me decepcionó el final. Por alguna razón, es de esas películas extremadamente largas que no resultan divertidas pero tampoco aburren completamente. Lentamente cultiva conceptos que luego utiliza en otras partes de la historia, a veces a modo de enseñanza y a veces con la intención de demostrarnos que es fácil equivocarse. Está llena de pequeños chistes e ironías que no siempre son graciosos, de alguna forma haciéndolo similar a la vida real, y de historias que parecen ser iluminadoras sólo según la vista que se les de. Creo que muchos la encontrarán similar a <em>Big Fish</em>.</p>
<p style="text-align: justify;">Sé que está basada en un libro del mismo nombre, pero no he leído nada al respecto.</p>
<p style="text-align: justify;"><strong>Le doy 3 de 5 zorrinitos.</strong></p>
<h2>Don&#8217;t be afraid of the dark</h2>
<p>Esta película me llamó la atención porque la estaría &#8220;remixando&#8221; Guillermo del Toro, quién se ha hecho en su fama un director que sabe utilizar el terror psicológico como un elemento para sus películas. Sin mayores rodeos, me sentí profundamente decepcionado, en múltiples niveles. La película no es más que una recopilación de clichés de terror, uno tras el otro, incluyendo el final y todo.</p>
<p>Aún así, a defensa de Guillermito, puedo decir que esta película no es de él, sino que él sólo quiso rehacerla por lo que personalmente significaba para él. Es posible que él se haya encontrado muy limitado por una película que en definitiva él no había escrito, y era aterrorizante en los 70&#8242;s.</p>
<p><strong>En fin, le doy un sólo zorrinito de 5.</strong></p>
<h2>Cirque Du Soleil: Worlds Away</h2>
<p style="text-align: justify;">Siendo de Cirque Du Soleil, esperaba un gran despliegue de habilidades, luces y colores, y sin duda lo obtuve. La trama es simple pero la forma en la que se desarrolla no lo es, y lo menciono como algo positivo. El desarrollo es puramente interpretativo, mucha danza y acrobacia, en ocasiones de forma simultánea. Juegos de luces, música de distintos estilos, agua, plataformas móviles, acróbatas de destreza increíble, de fuerza sorprendente o de coreografìas magníficas.</p>
<p style="text-align: justify;">Más aún, toda la película transcurre con al menos unas pocas palabras, y el resto es puramente no-verbal. Y de hecho, casi totalmente desprovista de referencias culturales específicas, excepto por un puñado de personajes.</p>
<p style="text-align: justify;">Es una película ciertamente distinta de a lo que estamos acostumbrados. <strong>Yo le otorgo 3 de 5 zorrinitos.</strong></p>
<h2 style="text-align: justify;">Mama</h2>
<p style="text-align: justify;">Le dí otra oportunidad a Guillermo Del Toro, esta vez con una película que, por su trailer, aparentaba jugar con la adaptación de la sociedad a monstruos. Obviamente no me quedó muy claro el trailer porque la película no tenía nada que ver con eso. De hecho, de alguna forma también cayó en el cliché, y de alguna forma sigue la misma estructura que seguía Don&#8217;t Be Afraid of The Dark, como había comentado antes.</p>
<p style="text-align: justify;">Dos pequeñas que no se adaptan a la sociedad ven algo que nadie más ve y&#8230; bueno, el resto lo pueden adivinar sin que lo escriba.</p>
<p style="text-align: justify;"><strong>Le doy 2 zorrinitos de 5</strong>, sólo porque me cayó bien la personaje principal.</p>
<h2 style="text-align: justify;">The Croods</h2>
<p style="text-align: justify;"><del>Brave</del> The Croods es la nueva película de <del>Pixar</del> Dreamworks, en este caso sobre una familia cavernícola que sobreviven gracias al miedo <del>de la guerra</del> de lo salvaje y a la protección de sus tradiciones. Pero <del>Mérida</del> Eep, la hija pelirroja, siente que su vida no puede continuar de esa forma y decide desafiar a su padre cuando descubre que hay una forma distinta de hacer las cosas. Ella se deja llevar por <del>la brujería</del> la ciencia de Guy y la batalla entre tradición y nuevas ideas comienza con altas y bajas para que eventualmente todos encuentren un final feliz en la capacidad de aceptar cosas nuevas y el punto de vista de los demás.</p>
<p style="text-align: justify;">Ahora que está de moda el planteo de ciencia vs. religión me habría gustado que esta película planteara un sutil argumento de posiciones dogmáticas contra ideas abiertas. Parecía ir para aquel lado, pero creo que podría haber utilizado muchos más elementos que, además de hacer la analogía más exacta, le habría dado más dramatismo a la película. ¿Recuerdan como siempre menciono que las películas animadas caen en un doble-dramatismo? (¿En el momento en donde algo ocurre mal, algo ocurre peor y ya nadie confía en el héroe?) Bueno, no ocurrió aquí.</p>
<p style="text-align: justify;">Por otro lado, me causó mucha gracia pensar que estaba viendo una versión cavernícola de Family Guy, en algún capítulo en donde el personaje principal sea Meg.</p>
<p style="text-align: justify;">Realmente creía que me habría gustado esta película. Me entretuvo, pero no mucho más que eso. De todos modos, hay gags interesantes, un perezoso musical (que curiosamente andan de moda en internet) y la invención de cosas que riman con Grug.</p>
<p style="text-align: justify;"><strong>Le doy 2 zorrinitos de 5 por la buena base.</strong></p>

<div class="wp_rp_wrap  wp_rp_plain" ><div class="wp_rp_content"><h3 class="related_post_title">Posts relacionados:</h3><ul class="related_post wp_rp" style="visibility: visible"><li data-position="0" data-poid="in-4427" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2012/10/10/the-theatre-bizarre/" class="wp_rp_title">The Theatre Bizarre</a></li><li data-position="1" data-poid="in-3802" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2012/04/21/the-cabin-in-the-woods/" class="wp_rp_title">The Cabin in the Woods</a></li><li data-position="2" data-poid="in-4574" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2013/02/27/frankenweenie/" class="wp_rp_title">Frankenweenie</a></li><li data-position="3" data-poid="in-4246" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2012/07/29/rec%c2%b3-genesis/" class="wp_rp_title">[Rec]³ Génesis</a></li><li data-position="4" data-poid="in-4188" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2012/07/18/the-amazing-spiderman/" class="wp_rp_title">The Amazing Spiderman</a></li></ul></div></div>
<img src="http://feeds.feedburner.com/~r/zorri/~4/-Gh1YMsls6Q" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.alphasmanifesto.com/2013/04/15/peliculas-miscelaneas/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.alphasmanifesto.com/2013/04/15/peliculas-miscelaneas/</feedburner:origLink></item>
		<item>
		<title>Programando Arkanoid – Parte 2</title>
		<link>http://feedproxy.google.com/~r/zorri/~3/-RFeT6ER9SU/</link>
		<comments>http://blog.alphasmanifesto.com/2013/04/01/programando-arkanoid-parte-2/#comments</comments>
		<pubDate>Tue, 02 Apr 2013 01:23:58 +0000</pubDate>
		<dc:creator>Alpha</dc:creator>
				<category><![CDATA[Proyectos]]></category>
		<category><![CDATA[Tecnología]]></category>
		<category><![CDATA[Canvas]]></category>
		<category><![CDATA[clases]]></category>
		<category><![CDATA[coordenadas]]></category>
		<category><![CDATA[herencia]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[objetos]]></category>
		<category><![CDATA[OOP]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[prototipo]]></category>
		<category><![CDATA[proyecto]]></category>

		<guid isPermaLink="false">http://blog.alphasmanifesto.com/?p=4718</guid>
		<description><![CDATA[En la entrega pasada hablamos sobre cómo comenzó el juego de Arkanoid, ahora continuaremos ese camino sobre la construcción del escenario de juego. En esa instancia cubrimos la estructura general de los archivos, la inicialización del objeto canvas, los estilos a usar y la inicialización de las opciones. Dejamos algo pendiente, que era el escenario, en un [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/04/Building2lq.jpg"><img class="aligncenter" alt="Building ball" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/04/Building2lq.jpg" width="803" height="495" /></a></p>
<p style="text-align: justify;"><a href="http://blog.alphasmanifesto.com/2013/03/13/programando-arkanoid-parte-1/">En la entrega pasada</a> hablamos sobre cómo comenzó el <a title="Arkanoid" href="http://randomjs.alphasmanifesto.com/arkanoid-canvas/arkanoid.html">juego de Arkanoid</a>, ahora continuaremos ese camino sobre la construcción del escenario de juego.</p>
<p><span id="more-4718"></span></p>
<p style="text-align: justify;">En <a title="Programando Arkanoid - Parte 1" href="http://blog.alphasmanifesto.com/2013/03/13/programando-arkanoid-parte-1/">esa instancia</a> cubrimos la estructura general de los archivos, la inicialización del objeto <span style="font-family: 'courier new', courier;">canvas</span>, los estilos a usar y la inicialización de las opciones. Dejamos algo pendiente, que era el escenario, en un objeto <span style="font-family: 'courier new', courier;">ArkanoidStage</span>. En ese post no expliqué qué hacía este objeto o como trabajaba. Hoy comenzaremos por ahí. Lo que describiremos en este post está cubierto en el commit <a href="https://github.com/AlphaGit/random-javascript/commit/90e6540100631e1a3ae590c3bde4a21b74f7abd9">90e6&#8230;abd9</a>.</p>
<p><script src="https://gist.github.com/AlphaGit/5158029.js"></script></p>
<h2>Introducción del escenario</h2>
<h2><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/04/arkanoidescenario.jpg"><img class="aligncenter" alt="arkanoidescenario" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/04/arkanoidescenario.jpg" width="956" height="577" /></a></h2>
<p style="text-align: justify;">Ya tenemos generado el objeto <span style="font-family: 'courier new', courier;">canvas</span> y las opciones para comenzar a dibujar sobre el contexto. Ahora, toda esa lógica de dibujado debería ser encerrada en algún objeto que pueda coordinar los elementos a dibujar &#8212; o a no dibujar (por ejemplo, cuando un bloque desaparezca). Por otra parte, este objeto podrá hacer los cálculos de tamaños según el tamaño del escenario (una de las opciones que ya inicializamos).</p>
<p style="text-align: justify;">Para eso introducimos la clase <span style="font-family: 'courier new', courier;">ArkanoidStage</span>.</p>
<p><script src="https://gist.github.com/AlphaGit/5218647.js"></script></p>
<p style="text-align: justify;">Como podrán ver, la declaración de clases en JavaScript no es realmente muy distinta de una función. En realidad, <em>es</em> una función, que funciona como generadora de los objetos y ámbito limitador de sus acciones. Los argumentos de esta función serán los parámetros actuales que son pasados al constructor (no hablaré de los parámetros formales porque no son realmente necesarios para el pasaje de los mismos). Como preferencia personal, declaro los parámetros a recibir para tener en cuenta en el futuro. Más aún, es más fácil hacer validaciones sobre ellos si es que quisiéramos.</p>
<p style="text-align: justify;">Los parámetros que <span style="font-family: 'courier new', courier;">ArkanoidStage</span> recibirá son tres: el contexto sobre el que se dibujará, el alto y el ancho del escenario. Asumiremos desde ahora que todas las distancias están medidas en píxeles, y que la coordenada (0, 0) es la esquina superior izquierda de la pantalla, aumentando hacia abajo y hacia la derecha.</p>
<p style="text-align: justify;">Una buena idea para el cálculo de los dibujos a realizar es plantear una grilla. Para eso, decidiremos primero el tamaño de los bloques como una porción del ancho y alto disponible. De esta forma, el juego será siempre el mismo independientemente del tamaño de la ventana del navegador. Para eso, el escenario calcula <span style="font-family: 'courier new', courier;">blockHeight</span> y <span style="font-family: 'courier new', courier;">blockWidth</span>. Estamos considerando que en una pantalla de juego podrán entrar 10 bloques horizontalmente, y 50 bloques verticalmente. ¿Cómo surgieron estos números? Simplemente me gustaron, y encontré que la proporción entre ellos era bastante aceptable. Por supuesto, esto puede cambiar a gusto.</p>
<p style="text-align: justify;">Ya que estamos calculando tamaños, es importante notar que hay un elemento que no sigue esta regla: la pelota del juego. A ella la haremos un poco más grande que el tamaño de un bloque, algo así como un bloque y medio de alto (su menor dimensión). Para eso entonces, calcularemos el radio de la pelota como un 80% del tamaño de un bloque, lo que nos dará una pelota de 1.6 bloques-alto de diámetro.</p>
<p style="text-align: justify;">Por último, el escenario comenzará dibujando nuestro primer objeto: El jugador. Como el jugador posee lógica propia (movimiento fuera de la grilla, velocidad incremental), vamos a hacer una clase propia para este objeto. Pero por ahora, vamos a instanciarlo y a pedirle que se dibuje (líneas 7 y 8). Lo que el jugador necesitará es:</p>
<ul>
<li style="text-align: justify;">el contexto (para dibujarse),</li>
<li style="text-align: justify;">un color (para dibujarse),</li>
<li style="text-align: justify;">el alto de un bloque (ya calculado para sus dimensiones)</li>
<li style="text-align: justify;">el ancho de un bloque (ya calculado para sus dimensiones)</li>
<li style="text-align: justify;">el ancho del escenario (para poder calcular sus movimientos)</li>
<li style="text-align: justify;">el alto del escenario (sólo por consistencia &#8212; pero en retrospectiva, podría haber eliminado esta parte)</li>
</ul>
<p style="text-align: justify;">Finalmente, nuestro escenario no tiene nada que devolver porque es quién se encargará de todo en el futuro. Por supuesto que la decisión podría ser otra, pero este es el camino que decidí tomar.</p>
<p style="text-align: justify;">Como nota extra, notarán que no me preocupó escribir esto en el global scope. Como toda la lógica estará encerrada en cada uno de los objetos, me parece aceptable. Para aplicaciones reales o más complejas, aconsejaría encerrar en un namespace, que no sería más que una variable global a la que estas funciones se le van anexando. En este caso, no lo veo realmente necesario.</p>
<h2>El jugador</h2>
<p><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/04/Building1lq.jpg"><img class="aligncenter size-full wp-image-4736" alt="Building player" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/04/Building1lq.jpg" width="803" height="495" /></a></p>
<p style="text-align: justify;">El jugador será el primero de los elementos que se dibuje en nuestra pantalla, y eso ya agrega varias responsabilidades a resolver. El dibujado en sí no debería ser una responsabilidad del jugador, sino las características que lo hacen un jugador (como su posición y su movimiento). Por supuesto, también debe dibujarse pero esa no es una característica única de él. ¡Esto suena a herencia de objetos!</p>
<p style="text-align: justify;">Por tanto, planteando que tendremos varios objetos que van a dibujarse, podemos partir desde entidades básicas que sabrán dibujarse. Llamemos a esa <span style="font-family: 'courier new', courier;">DrawableEntityBase</span>. Siguiente a esto, habrá  dos tipos de entidades distintas que se dibujarán. Unas de ellas son bloques (cuadrados), como los bloques objetivos y el jugador. La otra será la pelota, que tendrá forma circular. Como el dibujado actual varía entre estos, <span style="font-family: 'courier new', courier;">DrawableEntityBase</span> deberá delegar a sus clases hijas el dibujado, por lo que deberemos emular una clase abstracta, o una virtual que no haga nada por defecto. Prefiero emular una abstracta por mayor consistencia y <em>forzar</em> a que las clases hijas implementen su dibujado.</p>
<p style="text-align: justify;">Por ahora nos ocuparemos de los bloques, y a estos los llamaremos <span style="font-family: 'courier new', courier;">DrawableBlock</span>, heredando de <span style="font-family: 'courier new', courier;">DrawableEntityBase</span>.</p>
<p style="text-align: justify;">Y finalmente, entre los bloques, tendremos tanto a los bloques objetivos como al jugador. Concentrémosnos en el jugador por ahora, y creemos una clase para él: <span style="font-family: 'courier new', courier;">ArkanoidPlayer</span>, heredando de <span style="font-family: 'courier new', courier;">DrawableBlock</span>. Hasta este momento, esta es nuestra herencia de clases:</p>
<p><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/03/DrawableEntityBaseDrawableBlockArkanoidPlayer.png"><img class="aligncenter size-full wp-image-4719" alt="DrawableEntityBaseDrawableBlockArkanoidPlayer" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/03/DrawableEntityBaseDrawableBlockArkanoidPlayer.png" width="832" height="72" /></a></p>
<p style="text-align: justify;">Vamos a un poco de código.</p>
<h3>DrawableEntityBase</h3>
<p><script src="https://gist.github.com/AlphaGit/5218769.js"></script></p>
<p style="text-align: justify;">Lo primero a determinar es qué necesitará cualquier objeto que se pueda dibujar en pantalla. Está claro que necesitará el contexto 2D del canvas para dibujarse, y finalmente un color a ser usado para dibujarse. Esto tiene sentido si asumimos que cualquier entidad tendrá un único color, el cual es nuestro caso. Si no fuera así, cada tipo de entidad debería decidir cuántos colores recibe entre sus parámetros.</p>
<p style="text-align: justify;">Lo primero de lo primero es validar que tenemos lo necesario. No me preocupa tanto el color, pero sí el contexto. Verificamos entonces, que el <span style="font-family: 'courier new', courier;">drawingContext</span> exista. En JavaScript existe algo llamado <em>falsy values</em>, objetos y elementos que a pesar de no valer estrictamente <span style="font-family: 'courier new', courier;">false</span>, aún así evalúan como <span style="font-family: 'courier new', courier;">false</span> ante una expresión condicional. Estos son: <span style="font-family: 'courier new', courier;">false</span> (obviamente), <span style="font-family: 'courier new', courier;">0</span> (el número cero), <span style="font-family: 'courier new', courier;">&#8220;&#8221;</span> (la cadena vacía), <span style="font-family: 'courier new', courier;">null</span> (objeto nulo), <span style="font-family: 'courier new', courier;">undefined</span> (objeto no definido) y <span style="font-family: 'courier new', courier;">NaN</span> (números no numéricos &#8212; por contradictorio que suene). Para más detalles sobre valores <em>truthy</em> y <em>falsy</em>, les recomiendo leer <a href="http://www.sitepoint.com/javascript-truthy-falsy/">Truthy and Falsy: When All is Not Equal in JavaScript</a>.</p>
<p style="text-align: justify;">Como en nuestra situación, cualquiera de esas es totalmente inválida para un contexto, podemos verificar con un simple negador. Por supuesto, que de ser más estricto podríamos verificar por el contexto siendo una instancia de las clases que los navegadores exponen como contextos, pero en mi opinión ya es mucha paranoia. Si este objeto no tiene los métodos que necesitamos, no tardaremos mucho en saberlo.</p>
<p style="text-align: justify;">Como segundo acto, nos guardaremos referencias al contexto y al color, y declararemos nuestra función de dibujado: <span style="font-family: 'courier new', courier;">draw</span>. Sin embargo, no podemos implementarla realmente &#8212; como dije, <span style="font-family: 'courier new', courier;">DrawableEntityBase</span> debe comportarse como una clase abstracta. Lo que haremos es entonces arrojar una excepción dejando claro que una clase hija debe implementar este método. Eso prevendrá que podamos utilizarla (aunque no instanciarla individualmente, lo cual no es enteramente malo).</p>
<p style="text-align: justify;">Por último, devolveremos nuestro método disponible para exponerlo como público a cualquier elemento que cree una instancia nuestra.</p>
<h3>DrawableBlock</h3>
<p style="text-align: justify;">Algún texto esotérico que leí decía que <em>crear es limitar</em>. <span style="font-family: 'courier new', courier;">DrawableEntityBase</span> es muy genérica y por eso no hace demasiado. Ahora la limitaremos y le daremos más funcionalidad, lentamente creando nuestro resultado.</p>
<p><script src="https://gist.github.com/AlphaGit/5218835.js"></script></p>
<p style="text-align: justify;">Lo primero es crear nuestra nueva clase, y hacerla heredar de la clase base. Hay varias formas de hacer esto, y las más recomendadas incluyen librerías que ya se encargan de problemas de sobrecarga y múltiple herencia, pero yo quería hacer esto sin ninguna otra herramienta que mis dedos contra el teclado. De todas formas, las mejores recomendaciones vienen del señor John Resig, quien sabe mucho de JavaScript y nos cuenta de su forma de hacer herencia en <a title="Simple JavaScript Inheritance [John Resig]" href="http://ejohn.org/blog/simple-javascript-inheritance/">su post sobre herencia JavaScript</a>.</p>
<p style="text-align: justify;">Para poder tener esta herencia, debemos, por supuesto, declarar la función, y agregar la clase base a su prototipo, lo que le dará al principio toda esa funcionalidad. Sin embargo, esto debe ocurrir <em>antes</em> de la implementación de la función. Si esto les resulta raro, tengan en cuenta que declaración e implementación son dos momentos distintos aunque se escriban en el mismo lugar. En el caso de JavaScript, el hecho de declarar la función la hace disponible tanto para el código posterior como el anterior, y eso es lo que nos permite utilizar su prototipo antes de darle cuerpo. Si bien el cuerpo será ejecutado después, me agrada la idea de mantener la información de herencia a la cabeza de la función.</p>
<p style="text-align: justify;">El prototipo base debe tener una instancia de la clase base &#8212; ¿pero cómo creamos una instancia si no tenemos los parámetros necesarios? La forma más simple es hacer <span style="font-family: 'courier new', courier;">new DrawableEntityBase()</span> sin pasar parámetros, lo que aún generaría la instancia. Esto, sin embargo, no nos sirve a nosotros porque tenemos validaciones que pueden arrojar errores. Para esto entonces podemos utilizar <span style="font-family: 'courier new', courier;"><a href="https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/create">Object.create()</a></span>, disponible desde JavaScript 1.8.5.</p>
<p style="text-align: justify;">Por último, asignamos la función base al constructor de nuestro nuevo prototipo y comenzamos con el cuerpo de la función.</p>
<p style="text-align: justify;">Lo primero es la declaración, con los argumentos que necesitaremos para construir y dibujar un bloque. Estos son:</p>
<ul style="text-align: justify;">
<li><span style="line-height: 13px;">contexto para dibujar (la clase base lo necesita) &#8212; <span style="font-family: 'courier new', courier;">drawingContext</span></span></li>
<li>color para dibujar (la clase base lo necesita) &#8212; <span style="font-family: 'courier new', courier;">color</span></li>
<li>coordenada x de la esquina superior derecha &#8212; <span style="font-family: 'courier new', courier;">posX</span></li>
<li>coordenada y de la esquina superior derecha &#8212; <span style="font-family: 'courier new', courier;">posY</span></li>
<li>el alto del bloque a dibujar &#8212; <span style="font-family: 'courier new', courier;">height</span></li>
<li>el ancho del bloque a dibujar &#8212; <span style="font-family: 'courier new', courier;">width</span></li>
</ul>
<p style="text-align: justify;">Lo segundo a hacer, pero primero en el cuerpo de la función, es llamar al constructor base, para que las variables internas necesarias sean inicializadas, y cualquier lógica de inicialización también sea ejecutada. Eso lo haremos utilizando el método <span style="font-family: 'courier new', courier;">call</span>, que nos permite pasar como primer argumento el contexto de la función. Esto significa que la función se ejecutará como si se estuviera ejecutando en este mismo objeto. Para más información sobre <span style="font-family: 'courier new', courier;">call</span>, pueden ver su documentación y algunos usos interesantes: <a href="https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/call">MDN: <span style="font-family: 'courier new', courier;">Function.prototype.call</span></a>.</p>
<p style="text-align: justify;">Lo tercero a hacer es guardarnos los valores que necesitemos, y paso posterior, es darle una implementación a la función draw. Para esto sólo tenemos que utilizar el contexto y setear el color con el que se va a dibujar (<span style="font-family: 'courier new', courier;">fillStyle</span>, que también tiene otras opciones), y pedirle dibujar un rectángulo utilizando <span style="font-family: 'courier new', courier;">fillRect</span>, y pasando coordenadas y tamaños. Noten que la referencia a <span style="font-family: 'courier new', courier;">color</span> que uso no está prefijada con <span style="font-family: 'courier new', courier;">self.</span> como las demás. Esto es un error, y es importante si tenemos una clase compleja: la referencia a <span style="font-family: 'courier new', courier;">color</span> sin prefijar se refiere al argumento pasado en la instanciación de ese objeto, que será único y no cambiará a menos que lo alteremos a mano. Sin embargo, si nuestra clase posee varios niveles de herencia, mixins o múltiples padres, sería posible que la referencia guardada en <span style="font-family: 'courier new', courier;">self.color</span> cambiara, mientras que la que fue pasada por argumento no. Nostros perderíamos ese cambio por no utilizar la referencia correcta. Lo recomendable para mí es siempre utilizar las referencias almacenadas; no por alguna razón técnica, sino sólo por consistencia y organización.</p>
<h3>ArkanoidPlayer</h3>
<p style="text-align: justify;">Siguiendo la misma técnica para la herencia de clases, ahora debemos declarar <span style="font-family: 'courier new', courier;">ArkanoidPlayer</span> herendado de <span style="font-family: 'courier new', courier;">DrawableBlock</span>. Podríamos requerir más argumentos en su constructor, específicos de <span style="font-family: 'courier new', courier;">ArkanoidPlayer</span>, pero dado que no son realmente necesarios, vamos a calcularlos por defecto. Este es el caso de su posición en la pantalla.</p>
<p style="text-align: justify;">Los parámetros que necesitaremos, entonces, son:</p>
<ul>
<li style="text-align: justify;"><span style="line-height: 13px;">contexto para dibujar (la clase base lo necesita) &#8212; <span style="font-family: 'courier new', courier;">drawingContext</span></span></li>
<li style="text-align: justify;">color para dibujar (la clase base lo necesita) &#8212; <span style="font-family: 'courier new', courier;">color</span></li>
<li style="text-align: justify;">alto del bloque (la clase base lo necesita) &#8212; <span style="font-family: 'courier new', courier;">blockHeight</span></li>
<li style="text-align: justify;">ancho del bloque (la clase base lo necesita) &#8212; <span style="font-family: 'courier new', courier;">blockWidth</span></li>
<li style="text-align: justify;">alto del escenario (para calcular la posición del jugador) &#8212; <span style="font-family: 'courier new', courier;">stageHeight</span></li>
<li style="text-align: justify;">ancho del escenario (para calcular la posición del jugador) &#8212; <span style="font-family: 'courier new', courier;">stageWidth</span></li>
</ul>
<p><script src="https://gist.github.com/AlphaGit/5229666.js"></script></p>
<p style="text-align: justify;">Nos guardamos las referencias a las variables nuevas y creamos dos más: la posición X y la posición Y, que se referirán a la esquina superior izquierda (desde la cual comenzaremos a dibujar el bloque). Es importante que estemos actualizando estas variables porque el redibujado debe utilizarlas para mover al jugador.</p>
<p style="text-align: justify;">Como paso siguiente, llamamos al constructor de <span style="font-family: 'courier new', courier;">DrawableBlock</span> pasando un default para la posición X y la posición Y , que serán correspondientes a:</p>
<ul style="text-align: justify;">
<li><span style="line-height: 13px;">el punto X de la pantalla a dibujar el jugador para que el bloque esté centrado &#8211; <span style="font-family: 'courier new', courier;">(stageWidth &#8211; blockWidth)/2</span><br />
</span></li>
<li>el punto Y de la pantalla a dibujar el jugador para que el bloque esté casi al final de la pantalla &#8212; <span style="font-family: 'courier new', courier;">stageHeight &#8211; blockHeight * 2</span></li>
<li>el ancho del bloque a dibujar: <span style="font-family: 'courier new', courier;">blockWidth</span></li>
<li>el alto del bloque a dibujar: <span style="font-family: 'courier new', courier;">blockHeight</span></li>
</ul>
<p style="text-align: justify;">También debemos proveer la posibilidad de centrar al jugador, cuando el juego comience o cuando debamos resetear la partida o avanzar de nivel. En este caso, vamos a actualizar las coordenadas. Declaramos la función <span style="font-family: 'courier new', courier;">centerPlayer</span> y su cuerpo sólo actualizará la coordenada X, puesto que la coordenada Y del jugador nunca cambiará.</p>
<p style="text-align: justify;">Para asegurarnos de tener los datos consistentes, llamamos a esa función y por último, devolvemos nuestro objeto con las funciones públicas disponibles.</p>
<h2>La pelota</h2>
<p style="text-align: justify;">Teniendo toda esta base, plantear el dibujado de un círculo para representar la pelota con la que se interactúa no es demasiado difícil. Extendemos <span style="font-family: 'courier new', courier;">DrawableEntityBase</span> para declarar <span style="font-family: 'courier new', courier;">DrawableCircle</span> y redefinimos sus propiedades para basarse en el centro (y no una esquina) y el radio (y no ancho/alto) y reescribimos la implementación de <span style="font-family: 'courier new', courier;">draw()</span> para que llame a la función correspondiente del contexto.</p>
<p><script src="https://gist.github.com/AlphaGit/5289147.js"></script></p>
<p style="text-align: justify;">Para este caso, invocaremos a <span style="font-family: 'courier new', courier;">ellipse()</span>, <a href="http://docs.webplatform.org/wiki/apis/canvas/CanvasRenderingContext2D/ellipse">quién recibe los siguientes parámetros</a>:</p>
<ul style="text-align: justify;">
<li><span style="line-height: 13px;">el punto X del centro del círculo</span></li>
<li>el punto Y del centro del círculo</li>
<li>el radio en la dimensión X</li>
<li>el radio en la dimensión Y (en nuestro caso, el mismo)</li>
<li>la rotación &#8212; en nuestro caso cero, será un círculo perfecto y la rotación no cambiaría nada, sólo agregaría procesamiento extra</li>
<li>el ángulo de comienzo de la elipse &#8212; en nuestro caso, cero</li>
<li>el ángulo de fin de la elipse &#8212; en nuestro caso, cero, para una vuelta completa</li>
<li>si debe dibujarse en sentido antihorario &#8212; en nuestro caso <span style="font-family: 'courier new', courier;">false</span>, pero es indiferente</li>
</ul>
<p style="text-align: justify;">Hasta ahora, entonces, nuestra jerarquía de objetos se vería así:</p>
<p><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/04/hierarchy2.png"><img class="aligncenter size-full wp-image-4740" alt="hierarchy2" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/04/hierarchy2.png" width="835" height="157" /></a></p>
<p style="text-align: justify;">No será la última vez que trabajemos con la pelota, porque además de la capacidad de dibujarse, hay otras características que deberemos tratar más adelante.</p>
<p style="text-align: justify;">Con todo esto, ya tenemos los elementos principales para comenzar a trabajar en el orden y la interacción de elementos entre sí. Material que dejaré para otros posts.</p>

<div class="wp_rp_wrap  wp_rp_plain" ><div class="wp_rp_content"><h3 class="related_post_title">Posts relacionados:</h3><ul class="related_post wp_rp" style="visibility: visible"><li data-position="0" data-poid="in-4626" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2013/03/13/programando-arkanoid-parte-1/" class="wp_rp_title">Programando Arkanoid &#8211; Parte 1</a></li><li data-position="1" data-poid="in-2271" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2010/08/09/link-del-dia-a-dibujar-html5-full-powered/" class="wp_rp_title">Link del día: A dibujar, HTML5 full powered</a></li><li data-position="2" data-poid="in-3158" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2011/08/01/link-del-dia-monadas-en-javascript/" class="wp_rp_title">Link del día: Mónadas en JavaScript</a></li><li data-position="3" data-poid="in-4310" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2012/08/22/vs2012-dia-cuatro/" class="wp_rp_title">VS2012, día cuatro</a></li><li data-position="4" data-poid="in-2777" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2011/01/12/link-del-dia-proyectos-agiles-de-verdad/" class="wp_rp_title">Link del día: Proyectos ágiles de verdad</a></li></ul></div></div>
<img src="http://feeds.feedburner.com/~r/zorri/~4/-RFeT6ER9SU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.alphasmanifesto.com/2013/04/01/programando-arkanoid-parte-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.alphasmanifesto.com/2013/04/01/programando-arkanoid-parte-2/</feedburner:origLink></item>
		<item>
		<title>¿Es el desarrollo de software un arte?</title>
		<link>http://feedproxy.google.com/~r/zorri/~3/qk65PWGpcJA/</link>
		<comments>http://blog.alphasmanifesto.com/2013/03/21/es-el-desarrollo-de-software-un-arte/#comments</comments>
		<pubDate>Thu, 21 Mar 2013 18:56:03 +0000</pubDate>
		<dc:creator>Alpha</dc:creator>
				<category><![CDATA[Misceláneos]]></category>
		<category><![CDATA[análisis]]></category>
		<category><![CDATA[arte]]></category>
		<category><![CDATA[desarrollo]]></category>
		<category><![CDATA[disciplina]]></category>
		<category><![CDATA[estructuras]]></category>
		<category><![CDATA[procesos]]></category>

		<guid isPermaLink="false">http://blog.alphasmanifesto.com/?p=4706</guid>
		<description><![CDATA[Hoy me venía este pensamiento a la mente: ¿es el desarrollo de software un arte? Sé que muchos estarían de acuerdo en decir que sí, pero quiero plantear la pregunta con un rigor científico, algo que la frase que comúnmente usamos no contiene. Por lo general hablamos de una disciplina siendo un arte cuando tiene [...]]]></description>
				<content:encoded><![CDATA[<p style="text-align: justify;">Hoy me venía este pensamiento a la mente: ¿es el desarrollo de software un arte? Sé que muchos estarían de acuerdo en decir que sí, pero quiero plantear la pregunta con un rigor científico, algo que la frase que comúnmente usamos no contiene.</p>
<p style="text-align: justify;">Por lo general hablamos de una disciplina siendo un arte cuando tiene cierta belleza en sí (apreciada o inapreciada) y cuando requiere de mucha habilidad para hacerlo bien. Sin embargo, para que algo sea considerado <em>arte</em> realmente, hay otros requisitos. No soy un experto en el tema, pero quería intentar darle una mirada a esta pregunta y ver a dónde me lleva.</p>
<p><span id="more-4706"></span></p>
<h2>El desarrollo de software</h2>
<p style="text-align: justify;">Esta disciplina es, como mínimo, <em>rara</em>. Alguien alguna vez la describió como &#8220;construir castillos en el cielo&#8221;. La disciplina de generar estructuras y procesos desde la absoluta nada. Tanta flexibilidad, tanta libertad puede fácilmente caer en el caos, y esto es algo que ha sido muy fácilmente observado por los desarrolladores de varias décadas en el pasado. Como el desorden genera complejidad innecesaria, y esa complejidad se observa como flujos sin dirección clara, el término de <a href="http://en.wikipedia.org/wiki/Spaghetti_code">Spaghetti Code</a> fue acuñado tiempo atrás, incluso llevando consigo varios otros términos del mundo de la pasta.</p>
<p style="text-align: justify;">Sin embargo, estructuras, métodos y paradigmas surgieron. Formas de hacer las cosas que nos aseguran que diferentes partes tengan significados diferentes, y partes similares estén juntas. Métodos que nos aseguran separar distintos conceptos en distintas entidades (como lógica de cálculo vs. almacenamiento de datos). Métodos que nos aseguran que cada cambio agregará o cambiará algo sin afectar a nada más. Métodos que nos permiten medir la velocidad de trabajo o el avance. Métodos que se pueden reusar una y otra vez para resolver problemas similares.</p>
<p style="text-align: justify;">Y la complejidad de estos métodos creció tanto que comenzaron a hablarse de patrones de arquitecturas, una palabra que denota una actividad compleja y difícil: construir objetos complejos desde partes simples, que requiere a alguien con más habilidad que un trabajador normal. (Del griego: <em>arkhi</em>: jefe, <em>tekton</em>: construir.) Las arquitecturas a su vez se acoplan, se mezclan y se redefinen cada vez que el mercado hace disponible una nueva tecnología por hardware más barato y software más potente. Los sabios de la disciplina hablan de simplificar. <a href="http://en.wikipedia.org/wiki/You_aren't_gonna_need_it">YAGNI</a> (<em>You Ain&#8217;t Gonna Need It</em> &#8212; no lo vas a necesitar) para evitar complejidad injustificada, <a href="http://en.wikipedia.org/wiki/KISS_principle">KISS</a> (<em>Keep It Simple Stupid</em> &#8212; mantenlo simple y estúpido), para concientemente abocar por la simplicidad.</p>
<p style="text-align: justify;">Está claro que la disciplina es compleja, y que existen no sólo reglas de cómo hacer las cosas bien o &#8220;mejor de lo común&#8221;, sino que además existe una amplia gama de posibilidades en cuanto a complejidad. En mi desarrollo personal he encontrado que hay distintos tipos de persona que disfrutan de distintos niveles de complejidad para una misma solución. La complejidad no es inherentemente mala, sino que es un precio a pagar por mayor flexibilidad o robustez. Todos ellos tienen una idea distinta de lo que un software <em>bello</em> es, y esa belleza no se encuentra en el producto, sino en la estructura interior y el proceso.</p>
<h2>El arte</h2>
<p style="text-align: justify;">El arte no carece de reglas u opiniones, y, a pesar de la opinión popular, no cualquier cosa es arte. También existen reglas básicas que definen qué es y qué no lo es. He aquí algunas cuantas, pero no son todas. Cabe aclarar que aún así, <a title="Disputas de clasificación de arte [Wikipedia]" href="http://en.wikipedia.org/wiki/Art#Classification_disputes">existen muchas disputas sobre esto</a>, pero muy básicamente, algunas cosas pueden decirse.</p>
<p style="text-align: justify;"><strong>1. El propósito de la obra debe ser la evocación de un sentimiento.</strong> Todo arte se hace con el objetivo de alimentar el sentimiento. (Del artista o de la audiencia.) Como todo ser humano posee en cierta medida la necesidad de experimentar sentimientos, la necesidad también puede convertirse en negocio. Nadie discutiría que el cine y la música son artes, incluso aunque sean un negocio millonario. Incluso aunque se hagan con objetivo de vender, puede cumplir el propósito de evocar sentimientos.</p>
<p style="text-align: justify;"><strong>1. a.</strong> Como extensión de lo anterior, <strong>la obra no debe ser utilizada como herramienta.</strong> Es por esto que el arte se exhibe para ser experimentado y no se usa como medio para algo más. Esto define una línea muy fina entre el arte y el diseño (que también juega con el concepto de belleza y experiencias de uso). Un martillo no es arte. Un martillo bonito no es arte. Un martillo colgado en el centro en una habitación vacía para causar confusión podría ser arte. Un martillo destruyendo una obra clásica para señalar lo etéreo de todo lo material es arte.</p>
<p style="text-align: justify;"><strong>2. La obra debe transmitir un mensaje.</strong> Muchas corrientes artísticas quieren desafiar este concepto, pero ese desafío ya es un mensaje en sí. Cada obra tiene algo que decir, algo que quiere expresar. Las distintas corrientes artísticas se enfocan en distintos mensajes, en distintas formas de hacer llegar ese mensaje o en distintas formas de apreciar el mismo concepto. El arte abstracto es, muy a mi pesar, arte que habla de la belleza sin necesidad de formas. El arte conceptual busca el mensaje profundo en el mundo ordinario. El expresionismo utiliza el color como herramienta principal para enviar un mensaje. El romanticismo utiliza nuestra posición en un universo vasto para transmitir el mensaje.</p>
<p style="text-align: justify;"><strong>2. a.</strong> Como consecuencia, <strong>el mensaje debe poder ser transmitido.</strong> Cuando el mensaje no encuentra su camino y no provoca el sentimiento que debe provocar, falló en su propósito. Esto se pone interesante cuando el propósito de la obra en sí es producir confusión. Pero si el mensaje en general no se entiende, no se considera una forma de arte. Considérenlo de esta forma: ¿era la literatura un arte cuando sólo los monjes sabían leer y escribir? Probablemente no. ¿Era un arte la cinematografía cuando las primeras películas fueran inventadas por los hermanos Lumière? Sí, porque cualquiera que viera la obra la comprendería y obtendría su mensaje.</p>
<h2>Desarrollo y arte</h2>
<p style="text-align: justify;">Teniendo esas ideas en mente, volvamos a analizar el desarrollo de software.</p>
<p style="text-align: justify;"><strong>1. ¿Es su propósito evocar un sentimiento? Por lo general, no.</strong> (El software no cuenta: es un producto del desarrollo, no desarrollo en sí.) Sin embargo, estos últimos tiempos han mostrado más y más casos en donde se desarrolla por el placer de desarrollar. A la vez, muchas técnicas han permitido exaltar el valor interesante del desarrollo más allá de su producto, y de la forma en la que sus partes interactúan. Estos procesos y estos objetivos se alinean con el objetivo original del desarrollo &#8212; obtener un producto &#8212; pero no tiene el mismo objetivo.</p>
<p style="text-align: justify;">Por otro lado, dado que ya entre muchas comunidades no se entregan sólo productos sino código, y muchas veces, no el código en sí, sino la creatividad detrás del código. (Y tengo <a href="http://codegolf.stackexchange.com/q/3245/2415">un ejemplo favorito</a>.) En ellas muchas veces se transmite lo bueno o lo malo de las estructuras, lo bello de la sincronización, lo bizarro de las decisiones mal tomadas. A veces, el propósito es el mensaje.</p>
<p style="text-align: justify;">Consideremos esto como un punto semi-aceptable.</p>
<p style="text-align: justify;"><strong>1. a. ¿Es utilizado como herramienta? Sí, lo es.</strong> En más del 90% de los casos, el desarrollo de software es la herramienta que nos dará el producto que estamos buscando. En esa minoría, existen casos en donde el propósito es el desarrollo en sí y la experiencia que este brinda. Creo que fácilmente podremos estar todos de acuerdo con esto. Las estructuras y los diseños buscan hacer este proceso más simple, y buscan brindar un sentido de significancia al proceso y a las entidades internas del software. La elegencia y la belleza de un buen diseño hablan por sí mismas, pero no tuvieron propósito de estar ahí.</p>
<p style="text-align: justify;"><strong>2. ¿Transmite un mensaje?</strong> Sí, pero es un mensaje puramente funcional en lugar de emocional. Casos excepcionales existen. Las estructuras correctamente usadas generan el sentimiento de orden y tranquilidad, mientras que el spaghetti code y un código mal escrito genera incomodidad interna. Pero el mensaje no va más allá de su propia función o propósito. Creo que en este caso deberemos responder que <strong>no</strong>.</p>
<p style="text-align: justify;"><strong>2. a. ¿Puede ser efectivamente transmitido su mensaje? No.</strong> De la misma forma que ocurría con la literatura cuando nadie podía leer, es el caso que sufre el desarrollo de software al ser una disciplina muy específica. Sólo aquellos que estén entrenados y educados de la manera suficiente podrán apreciar la belleza o la aspereza de las buenas soluciones.</p>
<h2>Conclusión</h2>
<p style="text-align: justify;">Me sorprendo a mí mismo ahora. Comencé a escribir este post imaginando argumentar que el desarrollo de software es un arte y dar buenas razones al respecto, y me contradije a mí mismo llegando a la respuesta opuesta. Aparentemente, <strong>no podremos declarar que el desarrollo de software sea un arte</strong>.</p>
<p style="text-align: justify;">Sin embargo, para todos aquellos que me leen en este momento, comparto con ustedes la decepción de la conclusión: sé de las bellezas ocultas que esconde un buen software. Sé de la creatividad e ingeniosidad, la inspiración que transmiten soluciones simples y elegantes ante problemas complejos. Sé de la habilidad, casi intuitiva, que es necesaria para encontrar esas soluciones y esas oportunidades. Incluso ese hijo del desarrollo de software, la seguridad, es una disciplina con tanta variedad e intuición que parecería obvio que podríamos declararla arte. Sé que existen obras maestras en el mundo del software, y que existen bolas de barro que alguien tipeó en una noche de borrachera.</p>
<p style="text-align: justify;">Por último, y como consolación, esto no quiere decir que no podamos <a title="Arte generativo [Wikipedia]" href="http://en.wikipedia.org/wiki/Generative_art">utilizar el software como medio para generar arte</a>.</p>

<div class="wp_rp_wrap  wp_rp_plain" ><div class="wp_rp_content"><h3 class="related_post_title">Posts relacionados:</h3><ul class="related_post wp_rp" style="visibility: visible"><li data-position="0" data-poid="in-3873" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2012/05/16/hackearon-mi-server/" class="wp_rp_title">&#8220;Hackearon mi server&#8221;</a></li><li data-position="1" data-poid="in-4219" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2012/07/30/la-confianza-por-el-equipo/" class="wp_rp_title">La confianza por el equipo</a></li><li data-position="2" data-poid="in-3922" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2012/05/30/analisis-de-la-batalla-naval/" class="wp_rp_title">Análisis de la Batalla Naval</a></li><li data-position="3" data-poid="in-3460" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2012/01/10/link-del-dia-ajaxmytop/" class="wp_rp_title">Link del día: AjaxMyTop</a></li><li data-position="4" data-poid="in-4427" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2012/10/10/the-theatre-bizarre/" class="wp_rp_title">The Theatre Bizarre</a></li></ul></div></div>
<img src="http://feeds.feedburner.com/~r/zorri/~4/qk65PWGpcJA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.alphasmanifesto.com/2013/03/21/es-el-desarrollo-de-software-un-arte/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.alphasmanifesto.com/2013/03/21/es-el-desarrollo-de-software-un-arte/</feedburner:origLink></item>
		<item>
		<title>Yo jugando Mass Effect 3</title>
		<link>http://feedproxy.google.com/~r/zorri/~3/hf7rJLggeCw/</link>
		<comments>http://blog.alphasmanifesto.com/2013/03/20/yo-jugando-mass-effect-3/#comments</comments>
		<pubDate>Thu, 21 Mar 2013 03:40:01 +0000</pubDate>
		<dc:creator>Alpha</dc:creator>
				<category><![CDATA[Juegos]]></category>
		<category><![CDATA[Videos]]></category>
		<category><![CDATA[juego]]></category>
		<category><![CDATA[Mass Effect]]></category>
		<category><![CDATA[video]]></category>
		<category><![CDATA[Youtube]]></category>

		<guid isPermaLink="false">http://blog.alphasmanifesto.com/?p=4711</guid>
		<description><![CDATA[Soy alguien que cuando juega realmente busca divertirse. En mi caso, se trata de hablar un poco &#8212; quizá mucho &#8212; comentando sobre los juegos. Me recomendaron que me grabara para compartir la experiencia con otra gente. Lo probé y tras ver los videos, no me pareció tan mala idea. Por tanto, voy a estar [...]]]></description>
				<content:encoded><![CDATA[<p style="text-align: justify;">Soy alguien que cuando juega realmente busca divertirse. En mi caso, se trata de hablar un poco &#8212; quizá mucho &#8212; comentando sobre los juegos.</p>
<p style="text-align: justify;">Me recomendaron que me grabara para compartir la experiencia con otra gente. Lo probé y tras ver los videos, no me pareció tan mala idea.</p>
<p style="text-align: justify;"><span id="more-4711"></span></p>
<p style="text-align: justify;">Por tanto, voy a estar compartiendo mi experiencia de jugar a <strong>Mass Effect 3</strong>, uno de los juegos que actualmente ando disfrutando.</p>
<p style="text-align: justify;">Sólo llevo unas tres horas jugadas y unos pocas misiones del mismo. Pueden ver los videos en mi canal de Youtube, pero para el interesado, aquí los puede encontrar.</p>
<p style="text-align: justify;">¿El objetivo de estos videos? Principalmente, divertirme yo. Algo de comedia (aunque no soy gracioso), algo de crítica (aunque no soy muy detallista en la trama del juego), algo de drama (aunque no me mezclo mucho con los personajes). En fin, un intento de un poco de todo. Si a alguien le causa una sonrisa o algún feedback positivo, los videos habrán superado sus expectativas.</p>
<p style="text-align: justify;">Por supuesto, acepto sugerencias de cómo mejorar mi experiencia con el juego.</p>
<p><iframe width="500" height="281" src="http://www.youtube.com/embed/sEafcr9TDP4?feature=oembed" frameborder="0" allowfullscreen></iframe></p>
<p><iframe width="500" height="281" src="http://www.youtube.com/embed/0TAq8MqUYfk?feature=oembed" frameborder="0" allowfullscreen></iframe></p>
<p><iframe width="500" height="281" src="http://www.youtube.com/embed/DWEo_O6gW6k?feature=oembed" frameborder="0" allowfullscreen></iframe></p>
<p><strong>Update 21/3/13:</strong></p>
<p><iframe width="500" height="281" src="http://www.youtube.com/embed/vsVlDFkRfTU?feature=oembed" frameborder="0" allowfullscreen></iframe></p>
<p><strong>Update 12/5/13:</strong></p>
<p style="text-align: justify;">Notarán más calidad en los videos a continuación &#8212; aprendí a codificar correctamente los videos para los requerimientos HD de Youtube. 720p, en este caso, porque 1080 generaba videos muy largos que luego tardaban eternidades en subirse, y me parecen aceptables de todos modos.</p>
<p><iframe width="500" height="281" src="http://www.youtube.com/embed/dsDcmx2Zq0c?feature=oembed" frameborder="0" allowfullscreen></iframe></p>
<p><iframe width="500" height="281" src="http://www.youtube.com/embed/YIurTg1rnnc?feature=oembed" frameborder="0" allowfullscreen></iframe></p>
<p><iframe width="500" height="281" src="http://www.youtube.com/embed/SWatlzMCoAo?feature=oembed" frameborder="0" allowfullscreen></iframe></p>

<div class="wp_rp_wrap  wp_rp_plain" ><div class="wp_rp_content"><h3 class="related_post_title">Posts relacionados:</h3><ul class="related_post wp_rp" style="visibility: visible"><li data-position="0" data-poid="in-1997" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2010/04/01/link-del-dia-muchas-dimensiones-y-evento-de-semana-santa/" class="wp_rp_title">Link del día: Muchas dimensiones, y evento de semana santa</a></li><li data-position="1" data-poid="in-2931" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2011/04/29/link-del-dia-juegos-con-conceptos-novedosos/" class="wp_rp_title">Link del día: Juegos con conceptos novedosos</a></li><li data-position="2" data-poid="in-2757" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2011/01/03/link-del-dia-juegos-elecciones-y-moral/" class="wp_rp_title">Link del día: Juegos, elecciones y moral</a></li><li data-position="3" data-poid="in-2985" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2011/05/16/portal-2/" class="wp_rp_title">Portal 2</a></li><li data-position="4" data-poid="in-4550" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2013/02/27/black-mesa/" class="wp_rp_title">Black Mesa</a></li></ul></div></div>
<img src="http://feeds.feedburner.com/~r/zorri/~4/hf7rJLggeCw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.alphasmanifesto.com/2013/03/20/yo-jugando-mass-effect-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.alphasmanifesto.com/2013/03/20/yo-jugando-mass-effect-3/</feedburner:origLink></item>
		<item>
		<title>Programando Arkanoid – Parte 1</title>
		<link>http://feedproxy.google.com/~r/zorri/~3/OrwjvMcN4cU/</link>
		<comments>http://blog.alphasmanifesto.com/2013/03/13/programando-arkanoid-parte-1/#comments</comments>
		<pubDate>Thu, 14 Mar 2013 01:46:58 +0000</pubDate>
		<dc:creator>Alpha</dc:creator>
				<category><![CDATA[Proyectos]]></category>
		<category><![CDATA[Tecnología]]></category>
		<category><![CDATA[Canvas]]></category>
		<category><![CDATA[código]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[CSS3]]></category>
		<category><![CDATA[desarrollo]]></category>
		<category><![CDATA[desarrollo web]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://blog.alphasmanifesto.com/?p=4626</guid>
		<description><![CDATA[Haciendo ya mucho tiempo que no trabajaba en JavaScript sin la utilización de ningún framework, me propuse crear algo simple que a la vez fuera divertido. Pensé en algunas opciones y la ganadora fue un juego de Arkanoid (que, ahora me entero, es una de las tantas copias del Breakout, y para mi el nombre original [...]]]></description>
				<content:encoded><![CDATA[<p style="text-align: justify;"><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/03/arkanoid.jpg"><img class="aligncenter size-full wp-image-4694" alt="" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/03/arkanoid.jpg" width="752" height="443" /></a></p>
<p style="text-align: justify;">Haciendo ya mucho tiempo que no trabajaba en JavaScript sin la utilización de ningún framework, me propuse crear algo simple que a la vez fuera divertido. Pensé en algunas opciones y la ganadora fue un juego de <a href="http://en.wikipedia.org/wiki/Arkanoid">Arkanoid</a> (que, ahora me entero, es <a href="http://en.wikipedia.org/wiki/Breakout_clones">una de las tantas copias del Breakout</a>, y para mi el nombre original siempre fue Arkanoid, en fin).</p>
<p style="text-align: justify;">El resultado final lo pueden ver <a href="http://randomjs.alphasmanifesto.com/arkanoid-canvas/arkanoid.html">aquí</a> y el código fuente está en mi <a href="https://github.com/AlphaGit/random-javascript">repositorio de GitHub</a>, pero no es tanto el resultado sino el viaje lo que fue interesante, y <strong>quiero describir las cosas que aprendí en ese camino</strong>.</p>
<p style="text-align: justify;">Vengan y acompáñenme en mi viaje.</p>
<p><span id="more-4626"></span></p>
<h2>Documentación:</h2>
<p style="text-align: justify;">Como todo principante, o incluso como todo experto que cada tanto necesita verificar el estado de los estándares, la documentación de referencia es importante. Para hacer este pequeño proyecto me basé en algo de mi experiencia previa, y en la documentación disponible en los siguientes sitios:</p>
<ul>
<li style="text-align: justify;"><span style="line-height: 13px;"><a href="https://developer.mozilla.org/">Mozilla Developer Network</a>, impagable, la calidad de la documentación es increíble.</span></li>
<li style="text-align: justify;"><a href="http://www.webplatform.org/">WebPlatform.org</a>, acabo de enterarme de este sitio por la clase de juegos HTML5 en Udacity, pero está también muy completa</li>
<li style="text-align: justify;"><a href="http://www.w3schools.com/">W3Schools</a> para refrescar cosas básicas (&#8220;¿cómo eran los parámetros a array.slice?&#8221; y similares)</li>
</ul>
<h2>El contenedor:</h2>
<p style="text-align: justify;">(Lo que escribiré desde ahora se puede ver en el <a href="https://github.com/AlphaGit/random-javascript/commit/90e6540100631e1a3ae590c3bde4a21b74f7abd9">commit 90e6&#8230;4f7abd9</a>.)</p>
<p style="text-align: justify;">Lo primero y principal, y lo más simple fue setear el HTML y los estilos necesarios. <strong>Todo estará hecho en HTML5 Canvas</strong> y siendo manejado a través de JavaScript, nuestra estructura en el DOM en sí no debería ser demasiado compleja. Sí necesitamos, sin embargo, un documento válido y limpio.</p>
<p><script src="https://gist.github.com/AlphaGit/5156953.js"></script></p>
<p style="text-align: justify;">Esto está claro: sólo tenemos un DOM HTML5, en donde asignamos un título, una referencia a un archivo CSS para que nos de los estilos a la página. Luego, por supuesto, la referencia a nuestro script, en donde se encontrará toda la lógica de la aplicación. Vamos a suponer por ahora que este archivo JavaScript expone un objeto llamado <span style="font-family: 'courier new', courier;">arkanoid</span>, el cuál tiene un método llamado <span style="font-family: 'courier new', courier;">.init()</span> al que podemos llamar. Eso lo hacemos, por supuesto, en el momento en que la página carga.</p>
<p style="text-align: justify;">Ahora, los estilos no deben ser complejos tampoco. Todo lo que necesitamos es que en el cuerpo de la página exista un canvas y que este se vea como ocupando todo el espacio disponible. Por supuesto que esto significa poner los márgenes y los paddings a cero, pero lo que yo no sabía es que para evitar tener scrollbars o espaciados innecesarios, debemos indicar específicamente que el objeto canvas va a comportase como bloque, y que <strong>todo</strong> en la página carezca de espaciados. Esto lo aprendí de <a href="http://stackoverflow.com/questions/4288253/html5-canvas-100-width-height-of-viewport">una respuesta de StackOverflow</a>.</p>
<p style="text-align: justify;">Para esto podemos usar muy apropiadamente el selector de CSS *, que matcheará absolutamente todo elemento. Este selector se llama <a href="http://www.w3.org/TR/selectors/#universal-selector">Universal Selector</a> y está disponble para los navegadores que soporten características de CSS3. Por supuesto, estamos trabajando en Canvas con lo que es muy factible que los navegadores que soportan el segundo también soporten el primero.</p>
<p style="text-align: justify;">Nuestro CSS se ve, entonces, así:</p>
<p><script src="https://gist.github.com/AlphaGit/5156967.js"></script></p>
<h2>El código</h2>
<p style="text-align: justify;">Para proceder a la parte de JavaScript, ya teníamos una limitación particular: debemos crear un objeto <span style="font-family: 'courier new', courier;">arkanoid</span> que tenga la función <span style="font-family: 'courier new', courier;">init()</span>. De una forma simplista entonces instanciaremos el objeto arkanoid asignándole un valor al objeto window, o podríamos haberla declarado de forma independiente. Para mayor seguridad, podemos devolver los resultados de una función auto-ejecutable, de forma que todas las variables que creemos sean locales y no estén manchando el namespace global.</p>
<p style="text-align: justify;">Como también estaremos codificando lógica interna, seguramente querremos tener varias funciones y variables privadas. Nuestra función autoejecutable tiene solo que devolver entonces aquello que queramos hacer público, en nuestro caso, la función <span style="font-family: 'courier new', courier;">init()</span>.</p>
<p><script src="https://gist.github.com/AlphaGit/5158029.js"></script></p>
<p style="text-align: justify;">Vayamos analizando ese código línea a línea:</p>
<ul>
<li style="text-align: justify;"><span style="line-height: 13px;"><strong>La línea 1</strong> <strong>define el objeto <span style="font-family: 'courier new', courier;">arkanoid</span> que necesitábamos</strong>. Lo define como el resultado de una función que será llamada, y tiene la capacidad de recibir parámetros que serán las opciones del usuario. Esto es, en caso en que quisiéramos pasar información al momento de inicializarlo.</span></li>
<li style="text-align: justify;"><strong>Las líneas 4 a 6 definen variables locales</strong>, solamente disponibles para este objeto arkanoid, que serán utilizadas por las demás funciones interiores. Estas no estarán disponibles a los objetos externos al momento de devolver el resultado, y más aún, tampoco se encontrarán disponible a elementos que hagan referencias a <span style="font-family: 'courier new', courier;">this</span> o a <span style="font-family: 'courier new', courier;">self</span>. Si eso los confunde, a mí también me ocurrió, checkeen esta pregunta en StackOverflow: <a href="http://stackoverflow.com/q/15046910/147507">JavaScript local scoping: var vs. this</a>.</li>
<li style="text-align: justify;"><strong>Las líneas 8 a 13 definen otra variable local</strong>, pero esta será un objeto literal, para agrupar las posibles opciones con valores por defecto que tomaremos en caso en que el usuario (quien llama a esta función) no las provea.</li>
<li style="text-align: justify;"><strong>Las líneas 17 a 21 definen la función <span style="font-family: 'courier new', courier;">initOptions</span></strong>, que se encargará de identificar el conjunto de opciones válidas a utilizar, basado tanto en lo provisto por el usuario, los defaults, y la lógica interna. En este caso, obtendremos el override de lo que proveyó el usuario sobre lo default, y verificaremos que si estamos trabajando a pantalla completa (<span style="font-family: 'courier new', courier;">fullWidth</span> y <span style="font-family: 'courier new', courier;">fullHeight</span>), actualizaremos las variables de ancho y alto para que sean consistentes (<span style="font-family: 'courier new', courier;">stageWidth</span> y <span style="font-family: 'courier new', courier;">stageHeight</span>).</li>
<li style="text-align: justify;"><strong>Las líneas 23 a 28 hacen la magia de obtener el conjunto de opciones desde los defaults y con lo que el usuario proveyó.</strong> La lógica es tan simple como copiar todo lo que el usuario nos dio sobre el objeto de las opciones por default. Cabe destacar que aquí estamos escribiendo sobre el objeto de destino, por lo que si quisiéramos volver al valor por defecto, ya lo habríamos perdido. Una forma simple de haber hecho esto es, en lugar de llamarlo así:<br />
<span style="font-family: 'courier new', courier;">options = mergeObjects(defaultOptions, userOptions);</span><br />
Deberíamos llamarlo así:<br />
<span style="font-family: 'courier new', courier;">options = mergeObjects({}, defaultOptions); // creates a copy</span><br />
<span style="font-family: 'courier new', courier;">options = mergeObjects(options, userOptions); // overrides defaults</span></li>
<li style="text-align: justify;"><strong>Las líneas 30 a 39 inicializan el objeto canvas</strong> que se utilizará. Muy básicamente se obtiene el objeto <span style="font-family: 'courier new', courier;">body</span>, se crea un objeto <span style="font-family: 'courier new', courier;">canvas</span> y se le anexa, con el tamaño apropiado según las opciones. Para uso posterior, se almacenan las referencias al canvas y al contexto de dibujo 2D.</li>
<li style="text-align: justify;"><strong>Las líneas 41 a 46 realizan ese trabajo en sucesión</strong> llamando a las funciones apropiadas, e inicializa el stage sobre el que la magia ocurrirá.</li>
<li style="text-align: justify;">Por último, <strong>las líneas 49 a 51 devuelven el objeto</strong> exponiendo sólo la última función, y dándole el nombre de <span style="font-family: 'courier new', courier;">init</span>.</li>
</ul>
<p style="text-align: justify;">Por ahora nos detendremos aquí y continuaremos en la parte dos. Mientras lo preparo, estoy dispuesto a responder preguntas, y seguramente las preguntas y los comentarios ayudarán a generar las partes posteriores.</p>
<p>&nbsp;</p>

<div class="wp_rp_wrap  wp_rp_plain" ><div class="wp_rp_content"><h3 class="related_post_title">Posts relacionados:</h3><ul class="related_post wp_rp" style="visibility: visible"><li data-position="0" data-poid="in-2065" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2010/04/26/link-del-dia-html5-ilustrado/" class="wp_rp_title">Link del día: HTML5 Ilustrado</a></li><li data-position="1" data-poid="in-2960" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2011/05/09/link-del-dia-performance-html5-css3-y-dom-parte-1-intro/" class="wp_rp_title">Link del día: Performance HTML5, CSS3 y DOM, Parte 1: Intro</a></li><li data-position="2" data-poid="in-3939" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2012/06/01/front-end-code-standards/" class="wp_rp_title">Front-end code standards</a></li><li data-position="3" data-poid="in-2958" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2011/05/06/link-del-dia-html5-snippets/" class="wp_rp_title">Link del día: HTML5 Snippets</a></li><li data-position="4" data-poid="in-4310" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2012/08/22/vs2012-dia-cuatro/" class="wp_rp_title">VS2012, día cuatro</a></li></ul></div></div>
<img src="http://feeds.feedburner.com/~r/zorri/~4/OrwjvMcN4cU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.alphasmanifesto.com/2013/03/13/programando-arkanoid-parte-1/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://blog.alphasmanifesto.com/2013/03/13/programando-arkanoid-parte-1/</feedburner:origLink></item>
		<item>
		<title>Alpha’s Manifesto ahora tiene menú configurable</title>
		<link>http://feedproxy.google.com/~r/zorri/~3/m1eWoE-fsyA/</link>
		<comments>http://blog.alphasmanifesto.com/2013/03/12/alphas-manifesto-ahora-tiene-menu-configurable/#comments</comments>
		<pubDate>Wed, 13 Mar 2013 04:24:53 +0000</pubDate>
		<dc:creator>Alpha</dc:creator>
				<category><![CDATA[Proyectos]]></category>
		<category><![CDATA[Tecnología]]></category>
		<category><![CDATA[administración]]></category>
		<category><![CDATA[Alpha's Manifesto]]></category>
		<category><![CDATA[desarollo]]></category>
		<category><![CDATA[desarrollo web]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[theme]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://blog.alphasmanifesto.com/?p=4675</guid>
		<description><![CDATA[Como parte del proceso de dejar el theme listo para publicar, estuve trabajando en el WordPress Theme Testing. El proceso es largo y detallado, y la documentación también, pero yo estoy trackeando mi progreso en este issue en Github. Una de las partes es lograr que los menúes de navegación sean configurables, y es algo [...]]]></description>
				<content:encoded><![CDATA[<p style="text-align: justify;"><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/03/configurableMenu.jpg"><img class="aligncenter size-full wp-image-4676" style="border: 1px solid black;" alt="Menu configurable" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/03/configurableMenu.jpg" width="746" height="201" /></a></p>
<p style="text-align: justify;">Como parte del proceso de dejar el theme listo para publicar, estuve trabajando en el <a title="Theme Testing Process, de WordPress Codex" href="http://codex.wordpress.org/Theme_Development#Theme_Testing_Process">WordPress Theme Testing</a>. El proceso es largo y detallado, y la documentación también, pero yo estoy trackeando mi progreso en <a title="Setup WordPress Theme Testing" href="https://github.com/AlphaGit/alphasmanifesto/issues/10">este issue en Github</a>. Una de las partes es lograr que los menúes de navegación sean configurables, y es algo que se cumplió hoy para <strong>Alpha&#8217;s Manifesto</strong>.</p>
<p><span id="more-4675"></span></p>
<h2 style="text-align: justify;">Cómo funcionaba antes</h2>
<p style="text-align: justify;">La implementación anterior recorría las categorías disponibles en el blog y las mostraba una por una, generando un slug desde el nombre de la categoría que usaba para generar un URL de una imagen. La carpeta misma del theme tenía varios de los iconos con esos mismos nombres, y un archivo <span style="font-family: 'courier new', courier;">.htaccess</span> se usaba para devolver el icono por default de la carpeta vacía si es que el nombre de la categoría no existía como archivo.</p>
<p style="text-align: justify;">En esta aproximación, el usuario no tenía que configurar nada excepto las categorías del blog y ya tenía el menu disponible. Existían varios problemas con esto que ahora fueron solucionados:</p>
<ul style="text-align: justify;">
<li><strong>El menú no se podía deshabilitar: </strong>no había una forma desde el theme por la que uno pudiera quitar el menú si no lo quisiera. Las opciones eran modificar el theme manualmente, o no tener ninguna categoría en el blog. Eso o romperlo a través de JavaScript para que no se viera. Ninguna de las opciones es totalmente recomendable.</li>
<li><strong>No se podían elegir qué imágenes uno quería</strong> más que agregando imágenes en la carpeta del theme. Tampoco recomendable, pero tenía cierto encanto, ya que el theme se encargaba de dar imágenes por defecto si estas no existían. Lo malo es que uno requería utilizar la conexión FTP directa al servidor (si la tenía) y estaba forzado a usar imágenes de él.</li>
<li><strong>No se podía elegir el orden de las categorías,</strong> sino que el theme las elegía por uno.</li>
<li><strong>Sólo se podían ver categorías en este menú,</strong> es decir que no se podían incluir ningún otro tipo de links. Ni a links externos ni a páginas (page).</li>
<li><strong>El .htacess debía ser distinto en la configuración de desarrollo y la de producción.</strong> Si bien esto no es un problema para el usuario común del theme, es un problema si uno lo quiere tener instalado en una versión local. Para alguien que lo use profesionalmente, para desarrollar con él, y para mi, para desarrollar sobre él. El problema de que <span style="font-family: 'courier new', courier;">RewriteBase</span> tuviera que ser distinto según el servidor en donde lo tenía me generaba sospechas de que estaba haciendo algo mal.</li>
<li><strong>No se podía elegir qué categorías mostrar u ocultar, </strong>porque el theme automáticamente escaneaba todas para mostrarlas.</li>
</ul>
<p style="text-align: justify;">Con los cambios introducidos, esto se solucionó.</p>
<h2>Cómo funciona hoy</h2>
<p style="text-align: justify;">Hoy se usa la característica de Menus expuesta por WordPress, en donde uno puede configurar menús personalizados y asignarlos a secciones que el theme soporte.</p>
<p><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2013/03/alphasManifestoCurrentMenuConfiguration.jpg"><img class="aligncenter size-full wp-image-4678" alt="Configuracion de menú actual" src="http://blog.alphasmanifesto.com/wp-content/uploads/2013/03/alphasManifestoCurrentMenuConfiguration.jpg" width="793" height="643" /></a></p>
<p style="text-align: justify;">En la configuración actual, el theme dispone de una localización llamada <em>Menu al pie</em>, para el cual uno puede definir el menú a utilizar, de entre el listado de menúes particulares que uno haya generado en la sección de administración. Como extra, cada item debe actualizarse para que tenga incluida la imagen que se usará en la representación del menú. Esto es, simple y llanamente, la URL de esa imagen en particular.</p>
<p style="text-align: justify;">El orden de los ítems se puede actualizar simplemente arrastrando los items hasta que tengan el orden deseado.</p>
<p style="text-align: justify;">Cabe aclarar que por la forma del menú actual, no se permite una representación jerárquica de la navegación. Esto quiere decir que los ítems hijos, o los ítems de un nivel inferior no serán mostrados. Por el momento, esto es a drede, ya que no habría una forma s imple de mostrar esa relación. Entusiastas de diseño y UX, <strong>los invito a proveer sugerencias</strong> e ideas de cómo podría indicarse esto conservando el estilo poco intrusivo del menú.</p>
<h2>Cómo se implementó</h2>
<p style="text-align: justify;">Si sos un desarrollador de WordPress o estás pensando en hacer un theme, esto puede ser muy valioso para vos, especialmente si tienes necesidades particulares de controlar el HTML generado para los items. (Y especialmente dado que parece no haber mucha documentación de cómo lograr esto.)</p>
<p style="text-align: justify;">Según explica el <a href="http://codex.wordpress.org/Theme_Development#Template_File_Checklist">Template File Checklist</a> de WordPress Theme Development, la navegación debe implementarse a través de la función <a href="http://codex.wordpress.org/Function_Reference/wp_nav_menu"><span style="font-family: 'courier new', courier;">wp_nav_menu()</span></a>. La utilización de dicha función es bastante simple si estamos en las siguientes situaciones:</p>
<ul>
<li style="text-align: justify;"><span style="line-height: 13px;">Generar el menú con listas sin ordenar es suficiente para nosotros (<span style="font-family: 'courier new', courier;">ul &gt; li</span>)</span></li>
<li style="text-align: justify;">El soporte a la anidación se hará también con listas sin ordenar (<span style="font-family: 'courier new', courier;">ul &gt; li &gt; ul &gt; li</span>)</li>
<li style="text-align: justify;">Queremos cambiar las clases o los IDs que recibe la lista sin ordenar (<span style="font-family: 'courier new', courier;">ul</span>)</li>
<li style="text-align: justify;">Queremos agregar atributos propios a la lista (<span style="font-family: 'courier new', courier;">ul</span>)</li>
<li style="text-align: justify;">Queremos que la lista se encuentre contenida en algún otro elemento del DOM</li>
</ul>
<p style="text-align: justify;">Todo lo anterior se puede lograr con distintos valores de los parámetros <span style="font-family: 'courier new', courier;">container</span>, <span style="font-family: 'courier new', courier;">menu_class</span>, <span style="font-family: 'courier new', courier;">menu_id</span>, e <span style="font-family: 'courier new', courier;">items_wrap</span>. Notesé que no <strong>existe forma de manipular el output de cada item de la lista</strong>, al menos no entre los parámetros. Para estos casos es en donde WordPress recomienda utilizar un <em>walker</em>, que es una herencia de la clase <a href="http://phpdoc.wordpress.org/trunk/WordPress/Nav_Menus/Walker_Nav_Menu.html"><span style="font-family: 'courier new', courier;">Walker_Nav_Menu</span></a>.</p>
<h3>Modificando la generación del menú</h3>
<p style="text-align: justify;"><span style="font-family: 'courier new', courier;">Walker_Nav_Menu</span> es una clase que implementa la forma en la que se genera el HTML de la lista y de cada item interior. Podemos siempre extender la clase e incluirla en el scope de nuestro theme, e indicar que queremos usar esta clase en lugar de la clase default de WordPress.</p>
<p style="text-align: justify;">Por ejemplo, <strong>este es el footer del theme</strong> de Alpha&#8217;s Manifesto. Vean cómo se indica la forma en la que se quiere utilizar un walker propio:</p>
<p><script src="https://gist.github.com/AlphaGit/5149170.js"></script></p>
<p style="text-align: justify;">Y por supuesto, la implementación del mismo. Mucho del mismo no es más que una copia de <span style="font-family: 'courier new', courier;">Walker_Nav_Menu</span>, localizado en el archivo <span style="font-family: 'courier new', courier;">/wp-includes/nav-menu-template.php</span>. Sólo tienen que cambiar lo que quieren, y los métodos que no cambien pueden dejarse sin implementar.</p>
<p><script src="https://gist.github.com/AlphaGit/5149182.js"></script></p>
<h3>Permitir al usuario agregar la información necesaria</h3>
<p style="text-align: justify;">Si miran con atención, habrán visto que en el snippet de código anterior estoy usando <span style="font-family: 'courier new', courier;">$item-&gt;image_url</span> para la generación de la imagen del menú. Sin embargo, esta información no existe en la definición de los items, y mucho menos en la interfaz del usuario. Para esto es necesario registrar la información necesaria para que WordPress nos permita agregar esos datos. Esto fue difícil de lograr porque casi no existe documentación al respecto (o al menos yo no logré encontrarla).</p>
<p style="text-align: justify;">El código en general lo pueden encontrar en <a href="https://github.com/AlphaGit/alphasmanifesto/blob/8517782b4b4bfeeedbb5aa684bc690540d9ab479/custom_menu_setup.php">el archivo custom_menu_setup.php del theme</a>, pero pasaré a explicarlo por partes.</p>
<p style="text-align: justify;">Como cualquier atributo extra que se agregue no se leerá o guardará para el item por defecto, podemos usar filtros y acciones que nos permitirán hacer esa operación cuando los items se lean o se guarden a la base de datos. De esta forma, extendemos WordPress para trabajar con esa información extra.</p>
<p><script src="https://gist.github.com/AlphaGit/5149216.js"></script></p>
<p style="text-align: justify;">Tras poder guardar y leer esa información, falta una parte crucial: mostrar un lugar en la interfaz en donde el usuario pueda editarlo. Esto fue muy difícil de lograr, y me basé en algunas aproximaciones distintas:</p>
<p style="text-align: justify;">En <a title="How to add a custom field in the advanced menu properties?" href="http://wordpress.stackexchange.com/a/33495/28848">una respuesta de WordPress.SE</a>, el usuario djrmom hace lo siguiente:</p>
<ul style="text-align: justify;">
<li><span style="line-height: 13px;">Agrega los filtros y acciones necesarias para guardar / leer la propiedad nueva a los items (como hicimos más arriba)</span></li>
<li>Registra un custom Walker para la edición de los menús</li>
<li>En la implementación de este Walker, copia la generación del form original para agregar al final su propio campo</li>
</ul>
<p style="text-align: justify;">El usuario Cek (Frank) tomó un paso más y creó <a title="Wordpress Menu Item Meta Fields" href="http://changeset.hr/blog/code/wordpress-menu-item-meta-fields">un plugin para WordPress que permite agregar campos custom</a>, que utiliza casi la misma técnica para extender la funcionalidad de WordPress, con una diferencia: él no reescribe el código del Walker de WordPress, sino que utiliza <a href="https://code.google.com/p/phpquery/">phpQuery</a> para que la clase base genere su HTML y él anexar al final del formulario su propios datos al formulario.</p>
<p style="text-align: justify;">Si bien su aproximación me resultó muy interesante y simple, preferí no seguirla por dos razones:</p>
<ol>
<li style="text-align: justify;"><span style="line-height: 13px;">No me agrada del todo la idea de un theme (el que estoy desarrollando) cargando phpQuery en memoria y usándolo sólo una fracción del tiempo.</span></li>
<li style="text-align: justify;">La complejidad del Walker no desapareció, sólo ahora lo ejecuta otra clase y la nuestra le anexa algunas cosas</li>
</ol>
<p style="text-align: justify;">Por eso, preferí la aproximación general y reescribir el contenido del Walker de WordPress. En el códifo de Cek, se está extendiendo una clase llamada <span style="font-family: 'courier new', courier;">Walker_Nav_Menu_Edit</span>, pero esta clase no se encuentra definida completamente en todos los ámbitos en donde el theme se ejecuta. Él incluye una condición para tratar con eso, pero yo sólo encontré problemas que rompían la administración de WordPress. Por eso, en este caso, también extendí Walker_Nav_Menu (<span style="font-family: 'courier new', courier;">Walker_Nav_Menu_Edit</span> es una implementación de <span style="font-family: 'courier new', courier;">Walker_Nav_Menu</span> y no agrega métodos propios) y lo registramos de otra forma, utilizando la función add_action con <span style="font-family: 'courier new', courier;">wp_edit_nav_menu_walker</span> como primer parámetro.</p>
<p>El código general de esta clase lo pueden ver en <span style="font-family: 'courier new', courier;"><a href="https://github.com/AlphaGit/alphasmanifesto/blob/master/custom_menu_setup.php">custom_menu_setup.php</a></span> del theme, pero la parte importante es la siguiente:</p>
<p><script src="https://gist.github.com/AlphaGit/5149321.js"></script></p>
<p>Aquí pueden ver lo que se hizo:</p>
<ul>
<li style="text-align: justify;"><span style="line-height: 13px;">Se copió código para generar un campo más, usando las mismas clases de WordPress para dar estilos</span></li>
<li style="text-align: justify;">Se generan cadenas únicas para la descripción de los campos y IDs</li>
<li style="text-align: justify;">El nombre del campo (<span style="font-family: 'courier new', courier;">name</span>) es la propiedad que definimos a leer (ver variable <span style="font-family: 'courier new', courier;">$_POST</span> en los ejemplos anteriores) y el índice de ese array es el ID del item (ver funciones de save/restore más arriba)</li>
</ul>
<p style="text-align: justify;">Con esto, ya nuestro campo está disponible para ser editado por el usuario.</p>
<p style="text-align: justify;">Espero que esto les haya sido de ayuda.</p>

<div class="wp_rp_wrap  wp_rp_plain" ><div class="wp_rp_content"><h3 class="related_post_title">Posts relacionados:</h3><ul class="related_post wp_rp" style="visibility: visible"><li data-position="0" data-poid="in-4347" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2012/08/22/alphas-manifesto-deployment/" class="wp_rp_title">Alpha&#8217;s Manifesto deployment</a></li><li data-position="1" data-poid="in-2680" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2010/11/25/link-del-dia-consejos-de-base-de-datos/" class="wp_rp_title">Link del día: Consejos de base de datos</a></li><li data-position="2" data-poid="in-2101" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2010/05/07/link-of-the-day-open-source-project-management/" class="wp_rp_title">Link of the day: Open Source Project Management</a></li><li data-position="3" data-poid="in-4537" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2013/04/15/php-un-fractal-de-un-mal-diseno/" class="wp_rp_title">PHP: Un fractal de mal diseño</a></li><li data-position="4" data-poid="in-2145" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2010/05/31/link-del-dia-consejitos-jquery-mysql-ajax-y-php/" class="wp_rp_title">Link del día: Consejitos jQuery, MySQL, AJAX y PHP</a></li></ul></div></div>
<img src="http://feeds.feedburner.com/~r/zorri/~4/m1eWoE-fsyA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.alphasmanifesto.com/2013/03/12/alphas-manifesto-ahora-tiene-menu-configurable/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.alphasmanifesto.com/2013/03/12/alphas-manifesto-ahora-tiene-menu-configurable/</feedburner:origLink></item>
		<item>
		<title>Black Mesa</title>
		<link>http://feedproxy.google.com/~r/zorri/~3/OtkU_QoWo94/</link>
		<comments>http://blog.alphasmanifesto.com/2013/02/27/black-mesa/#comments</comments>
		<pubDate>Thu, 28 Feb 2013 02:23:58 +0000</pubDate>
		<dc:creator>Alpha</dc:creator>
				<category><![CDATA[Juegos]]></category>
		<category><![CDATA[half life]]></category>
		<category><![CDATA[juego]]></category>
		<category><![CDATA[reseña]]></category>
		<category><![CDATA[review]]></category>

		<guid isPermaLink="false">http://blog.alphasmanifesto.com/?p=4550</guid>
		<description><![CDATA[Como buen fanático de la saga de Half Life, el primer día que Black Mesa estuvo disponible lo bajé y probé. No mucho tiempo después, lo había terminado. A continuación, mi opinión de esta visita nostálgica de la primera parte de esta épica saga. Black Mesa es la re-edición de Half Life 1 por parte [...]]]></description>
				<content:encoded><![CDATA[<p style="text-align: justify;"><a href="http://blog.alphasmanifesto.com/wp-content/uploads/2012/12/BWMesa.jpg"><img class="aligncenter size-full wp-image-4623" alt="Black and White Mesa" src="http://blog.alphasmanifesto.com/wp-content/uploads/2012/12/BWMesa.jpg" width="800" height="468" /></a></p>
<p style="text-align: justify;">Como buen fanático de la saga de <strong>Half Life</strong>, el primer día que Black Mesa estuvo disponible lo bajé y probé. No mucho tiempo después, lo había terminado. A continuación, mi opinión de esta visita nostálgica de la primera parte de esta épica saga.</p>
<p style="text-align: justify;"><span id="more-4550"></span></p>
<p style="text-align: justify;"><strong>Black Mesa es la re-edición de Half Life 1</strong> por parte de un gupo de fans. Según lo que leí, este grupo de fans estaba haciendo un buen trabajo desde el comienzo y más tarde Valve mismo apoyaba el trabajo que ellos estaban hacendo. Black Mesa es totalmente gratis gracias a su esfuerzo y se encuentra disponible para cualquiera con una PC, en su sitio <a title="Black Mesa Source" href="http://www.blackmesasource.com/">Black Mesa Source</a>.</p>
<p style="text-align: justify;">La historia en Black Mesa es, por tanto, la misma de Half Life 1, específicamente hasta que se crea el portal a Xen. Luego de eso la historia se detiene y muchos nos quedamos con las ganas de saltar al otro mundo (literalmente). El equipo dice que lo tendrán listo eventualmente pero no hay fechas ni promesas.</p>
<p style="text-align: justify;">Lo más bonito de este juego, fuera de la <strong>nostalgia de revivir la historia</strong>, es la nueva calidad gráfica que permite el nuevo motor. Esto y los años de entrenamiento que los otros juegos de la saga nos han dado nos permiten revisitar esta parte con más atención a la sucesión de eventos, las pruebas lógicas y las batallas desafiantes (que, de hecho, me parecieron un poco más desafiantes que en el juego original).</p>
<p style="text-align: justify;">Por alguna razón no me fue nada difícil en esta versión encontrar glitches. No sé cuánto de esto se deba al motor gráfico o cuanto al remake. Parecería incluso que la inteligencia de los NPC es la misma que la del juego viejo, haciendo las estrategias muy fáciles, pero la física es ciertamente de los nuevos juegos. Si quieren ver algunos screenshots de estos glitches, pueden <a title="Glitches en Black Mesa Source" href="http://imgur.com/a/6n0nc">ver los tres que encontré</a>.</p>
<p style="text-align: justify;">No hay mucho que pueda comentar sobre la historia o sobre la mecánica del juego, ya que toda pertenece a Half Life, en sus años de antaño. Si bien sigue siendo un muy buen juego, creo que gran parte de sus desafíos quedaron opacados por el tiempo, y Black Mesa no vino a cambiar eso.</p>
<p style="text-align: justify;">En definitiva, es una linda forma de revivir el juego mientras todos esperamos la salida del famoso Half Life 3.</p>
<p style="text-align: justify;">Le doy 3 zorrinitos de 5.</p>

<div class="wp_rp_wrap  wp_rp_plain" ><div class="wp_rp_content"><h3 class="related_post_title">Posts relacionados:</h3><ul class="related_post wp_rp" style="visibility: visible"><li data-position="0" data-poid="in-3893" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2012/05/11/mass-effect/" class="wp_rp_title">Mass Effect</a></li><li data-position="1" data-poid="in-3920" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2012/05/28/diablo-iii/" class="wp_rp_title">Diablo III</a></li><li data-position="2" data-poid="in-4508" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2012/11/08/quantum-conundrum/" class="wp_rp_title">Quantum Conundrum</a></li><li data-position="3" data-poid="in-4239" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2012/08/15/q-u-b-e/" class="wp_rp_title">Q. U. B. E.</a></li><li data-position="4" data-poid="in-2985" data-post-type="none" ><a href="http://blog.alphasmanifesto.com/2011/05/16/portal-2/" class="wp_rp_title">Portal 2</a></li></ul></div></div>
<img src="http://feeds.feedburner.com/~r/zorri/~4/OtkU_QoWo94" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.alphasmanifesto.com/2013/02/27/black-mesa/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://blog.alphasmanifesto.com/2013/02/27/black-mesa/</feedburner:origLink></item>
	</channel>
</rss><!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Page Caching using disk: enhanced
Database Caching 10/87 queries in 0.750 seconds using disk
Object Caching 1490/1596 objects using disk

 Served from: blog.alphasmanifesto.com @ 2013-05-18 05:42:32 by W3 Total Cache -->
