2009/11/12

Trabajando con MVC


Lo que suelo hacer es ir como el cangrejo, de atrás para adelante:
  • Hago una vista estática, con datos en duro. Lo pruebo.
  • Ubico los datos que podrían ser dinámicos y uso variables y lógica de vista para generar los datos en duro. Todo eso en la misma vista. Lo pruebo, debe funcionar igual que antes.
  • La lógica de vista queda en la vista, pero paso al controlador la asignación de valores en duro a las variables requeridas por la vista. Lo pruebo, debe funcionar igual que antes.
  • Paso a un modelo la generación de los datos en duro requeridos por el controlador para enviar a la vista. Lo pruebo, debe funcionar igual que antes.
  • Creo un sistema de tablas de donde el modelo pueda extraer los datos que he venido usando en duro. Lo pruebo, debe funcionar como antes.

En cada paso, me inclino por la solución más natural y simple disponible. Evito considerar requerimientos que podrían ser buenos para el futuro o para otro caso. De ese modo la solución tiene lo que se necesita y nada más. Evito compromisos innecesarios y disminuyo las probabilidades de efectos secundarios.

Luego que algo funciona, trato de eliminar duplicaciones, y luego optimizar. Es mejor postergar la optimización lo más que se pueda, ya que optimizar frecuentemente ensucia el código con trucos y técnicas que no dejan ver bien la lógica de la solución.

Programar código directamente optimizado es una trampa, una ilusión. Hace más lento el desarrollo y complica transitar cada escalón. Cuando algo falla, está todo tan enredado que prefieres descolgarte por la baranda que revisar la escalera.

Es mejor programar por niveles de complejidad, dejando la optimización para el final. Como cuando se construye una casa; los acabados no se ponen hasta el final. De otro modo los constructores gastarían energía y tiempo extra en cuidar un mobiliario y accesorios que les estorba el paso, y que encima nadie puede usar bien.

Breve crítica sobre el uso del idiomas y variables con prefijos

Reconozco que para resolver muchos tipos de problemas, así como para organizar las cosas suele ser más sencillo pensar de atrás hacia adelante, como en el inglés (me parece que no por nada los lenguajes de programación están en inglés). De afuera hacia adentro. De lo general a lo particular. La organización de directorios, nombres, etc se hace más clara y más compatible con otras organizaciones, que si se fuerza a usar español sólo porque sí.

Sin embargo, si mis conceptos están en español, las variables directamente relacionadas con ellos también aparecerán en español (por ejemplo los nombres de las tablas, modelos, controladores), pero todas las demás variables internas (como los contadores), prefijos, sufijos, etc mantienen el estandar de un desarrollo en inglés. No es práctico traducir el nombre de las entidades, porque frecuentemente habrán conversaciones sobre ellas y carga el desarrollo llevar un tabla de equivalencias y pensar con esas equivalencias encima. Cuantos más ligeros, mejor.

Así, uso producto_precio en lugar de precio_producto, entidad_caracteristica en lugar de caracteristica_entidad.

Además, uso setPrecio(), getProducto(), etc, porque es más corto que establecerPrecio(), obtenerProducto(), etc. Hay IDEs, como Eclipse, que tienen generadores de getters y setters.

Esta forma práctica de usar el idioma no tiene que ver con el respeto a la lengua materna o lo que recomiende la RAE para hablar. Eso es otro asunto. Lo importante es que el desarrollo sea claro, práctico, el mantenimiento fácil, y que el programa funcione.

Por otro lado, me parece innecesario el uso de prefijos sólo para señalar que cierta variable pertenece a tal módulo asociado a tal tabla de la base de datos del proyecto tal. Quizás puedan ayudar a ubicar la variable dentro del contexto del proyecto, pero es poca ganancia comparado con el lastre que significará usar esas variables en el día a día. Es mejor usar variables nombradas lo más naturalmente y simple que se pueda.

Además, siguiendo un orden natural y claro no se necesitará señalar 'que cierta variable pertenece a tal módulo asociado a tal tabla de la base de datos del proyecto tal'; todo eso se podrá deducir por contexto.

Claro que todo esto no es algo rígido. Son simplemente pautas que trato de seguir y que voy corrigiendo conforme veo más casos, me equivoco y aprendo.

2009/11/08

Hello World en Kohana

Kohana es un framework PHP derivado de CodeIgniter. Los desarrolladores de Kohana decidieron que participara más la comunidad, que se adoptara PHP5, y que hubiera un ORM para acceder a la base de datos, entre otras mejoras que venían reclamándose hacía tiempo en los foros de CodeIgniter.

He usado CodeIgniter para un proyecto. Pude aprender a usuarlo mucho más rápidamente que CakePHP (de hecho, fueron varios disgustos sucesivos al reaprender varias de las bibliotecas principales de Cake lo que me animó a buscar afuera y probar CI).

Usar CI es simple, claro, directo. Permite incorporar fácilmente muchas de las cosas que ya sepamos de PHP, en lugar de forzarnos a reaprenderlas, como me sucedió con Cake.
Además me gusta mucho la forma en que permite organizar los controladores y, principalmente, las vistas.
Sin embargo, extraño algunas cosas de Cake, como la forma de acceder a la base de datos y la forma de mantener disponibles los datos del formulario una vez enviado.

Leí que Kohana es interesante como alternativa a CI (mis siguientes pasos serían probar también Yii y Adventure PHP Framework), y he decidido probarla.

2009/10/20

La importancia de comprender el proceso de solución

Muchas veces me he preguntado por qué frecuentemente parece tan problemático aplicar en proyectos del mundo real los esquemas de trabajo que aprendemos al estudiar.

El desarrollo de un sistema real suele ser un problema impreciso, a diferencia de los libros de texto, donde cada problema suele aparecer expresado de modo preciso.
Aún en los proyectos aparentemente simples, es normal encontrar imprecisiones en lo que el cliente tiene, lo que el cliente quiere y lo que realmente necesita.

Pero, aunque eso es un problema adicional al principal, pienso que no es la principal razón de las dificultades al desarrollar un proyecto.

Me parece que la principal razón es un problema de actitud frente a los problemas debido, básicamente, a la falta de comprensión de cómo se solucionan.

Muchas personas no han hecho nunca el intento de resolver algo desde cero. Casi siempre han podido solucionar lo que necesitaban adaptando o configurando una solución general desarrollada por alguien más.
Sin embargo, se les pone en proyectos de desarrollo que implican desarrollar desde cero, y entonces empiezan a ocurrir problemas.

Pienso que cuando una persona se ha acostumbrado a renunciar a buscar sus propias soluciones para usar las de otros, con el tiempo puede empezar a tener una visión distorsionada de lo que una solución es y del proceso necesario para lograrla.
Como las soluciones de otros suelen venir acabadas, pulidas y empaquetadas, una persona que no ha tenido experiencia hallando sus propias soluciones suele mirar con desconfianza el proceso de solución de otras personas.
Le es difícil entender la presencia de código auxiliar, y las sucesivas aproximaciones, simplificaciones y pruebas que ocurren en el proceso. Cree que las soluciones se deben construir tal cual se presentan al final, lo cual es como pretender que una casa se puede construir colocando cada parte con su cubierta y acabado final, cuando en realidad el proceso de construcción es por etapas.

George Polya escribió sobre el proceso de solución de problemas por uno mismo. Primero comprender el problema; familiarizarse con él; en qué consiste. Luego usar alguna estrategia de solución; quizás dividirlo, quizás simplificarlo, quizás expresarlo de otro modo, o en términos de problemas cuya solución conozcamos; probar y probar. Hallada la solución, comprobarla; ver si realmente satisface el problema. Finalmente, ver si puede hacerse de otro modo, quizás más rápido o con menos recursos.
Primero resolver la cuestión, luego optimizar la solución.

Pero cuando no se ha sido educado en solucionar problemas por uno mismo, sino en asimilar la solución de problemas tipo resueltos por otros, uno se puede llegar a acostumbrar a eso. Y, con el tiempo, llegar a pensar que todos los problemas se pueden resolver de ese modo.
Así, no es poco frecuente hallar personas que creen que toda solución debe aparecer ya optimizada.
La solución de un problema tipo puede aparecer optimizada porque ya es conocida.
La solución de un problema nuevo, en cambio, se construye gradualmente.

Muchas veces se dice que hay que evitar reinventar la rueda, y se mira con cierto desdén a una persona que lo intenta. Sin embargo, es importante. Porque quien lo hace entrena su mente en distinguir soluciones, y en construir el camino para hallarlas. Puede sentir cuál será el siguiente paso.

Quién sólo aplica soluciones es como alguien confinado a ir siempre por caminos ya trazados. Quizás tan temeroso que evita, aproximarse a los bordes, o siquiera mirar a los lados. Y, posiblemente, obstaculizando constantemente a quienes quisieran aventurarse más allá. Sin entender que los caminos no aparecen pavimentados de golpe, sino que deben construirse y, aún antes, descubrirse.

Solucionar un problema por uno mismo puede ser un proceso de exploración y descubrimiento, como aventurarse en un bosque. O también puede ser un proceso de sembrar, cultivar y cosechar.

Por supuesto que aplicar la solución de otro también tiene su mérito. Es una cuestión de técnica. De cómo, hecho el camino, lo puedo recorrer. Pero, ¿quién hace el camino?

Admitiendo que un proyecto tiene partes que desarrollar desde cero, debería dejarse espacio para el proceso de exploración y evolución que una solución desde cero necesariamente requerirá. ¿Lo hace usted?

2009/09/24

Conociendo PHP

Una presentación que hice para el Instituto José Pardo.
Viéndola desde SlideShare está además disponible el ppt original y las animaciones que no aparecen en la versión adaptada.

2009/08/28

Enviando emails con PHP



El envío de emails con PHP puede ser relativamente sencillo.
Pero, dependiendo de cómo sea el mensaje, las cosas pueden requerir algo más de trabajo.


Explorando en la red encontramos ejemplos que usan la función nativa mail(). Esto funciona bien para el caso relativamente sencillo de enviar ASCII (ó ISO-8859-1).

Si uno quiere enviar HTML o Unicode (UTF-8), o ASCII junto con HTML (como suelen hacer los servicios email), entonces las cosas se complican un poco, y los tutoriales son más escasos. Quizás optan por usar alguna biblioteca auxiliar, como PEARL. Es posible seguir haciéndolo con mail(), pero no encontrará mucho al respecto.

Las complicaciones aumentan un poco más si se quiere adjuntar un documento al mensaje. Sigue siendo posible seguir haciéndolo con mail(), pero 'tampoco encontrará mucha información sobre cómo hacerlo.

Para hacerlo, es importante fijarse en los headers que se envían. Estos contienen la descripción del contenido del mensaje. Y hay que colocar también ciertas marcas de separación en la estructura del mensaje.

Un mensaje ASCII + HTML tiene un mensaje con una estructura similar a:

(declaración de separador alterno)

--separador alterno
(descripción del contenido de texto)
(contenido de texto)

--separador alterno
(descripción de contenido html)
(contenido html)
--separador alterno--

Un mensaje ASCII + HTML + adjunto tiene un mensaje con una estructura similar a:

(declaracion de separador mixto)

--separador mixto

(declaración de separador alterno)

--separador alterno
(descripción del contenido de texto)
(contenido de texto)

--separador alterno
(descripción de contenido html)
(contenido html)
--separador alterno--

--separador mixto
(descripción de contenido adjunto)
(contenido adjunto)
--separador mixto--

Se puede observar que los separadores finales tienen un par de quiones extra al final (--).

Se puede comprobar esto explorando el código fuente de algunos email que se hayan recibido, o algunos simples que ilustren estos tres casos.

A continuación coloco el código de algunos scripts que desarrollé basado en las ideas que encontré en PHP: Sending Email (Text/HTML/Attachments) y mucha prueba y error hasta que funcionaron :)

simple_email.php


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<?php
// akobashikawa@gmail.com, 20090828

$from = isset($_POST['from'])?$_POST['from']:'';
$to = isset($_POST['to'])?$_POST['to']:'';
$subject = isset($_POST['subject'])?$_POST['subject']:'';
$message = isset($_POST['message'])?$_POST['message']:'';
if (isset($_POST['submit'])) {
$headers = "From: $from\r\nReply-To: $from";
$mail_sent = mail( $to, $subject, $message, $headers );
}
?>
<title>Simple Email</title>
<style type="text/css">
</style>

<script type="text/javascript">
</script>
</head>
<body>
<h1><a href="simple_email.php">Simple Email</a></h1>
<form action="simple_email.php" method="POST">
From:<br/>
<input type="text" name="from" value="<?php echo $from; ?>"><br/>
To:<br/>
<input type="text" name="to" value="<?php echo $to; ?>"><br/>
Subject:<br/>
<input type="text" name="subject" value="<?php echo $subject; ?>"><br/>
Message:<br/>
<textarea name="message"><?php echo htmlentities($message); ?></textarea><br/>
<input type="submit" name="submit" value="Send"/>
</form>
<p>
<?php echo isset($mail_sent)?($mail_sent? "Mail sent":"Mail failed"):''; ?>
</p>
</body>
</html>


html_email.php


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<?php
// akobashikawa@gmail.com, 20090828

$from = isset($_POST['from'])?$_POST['from']:'';
$to = isset($_POST['to'])?$_POST['to']:'';
$subject = isset($_POST['subject'])?$_POST['subject']:'';
$message = isset($_POST['message'])?$_POST['message']:'';
if (isset($_POST['submit'])) {
$random_hash = md5(date('r', time()));
?>
<?php ob_start(); ?>
--PHP-alt-<?php echo $random_hash; ?>
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: base64

<?php echo base64_encode(strip_tags($message)); ?>

--PHP-alt-<?php echo $random_hash; ?>
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: base64

<?php echo base64_encode($message); ?>

--PHP-alt-<?php echo $random_hash; ?>--
<?php $_message = ob_get_clean(); ?>
<?php
$headers = "From: $from\r\nReply-To: $from";
$headers .= "\r\n".'MIME-Version: 1.0';
$headers .= "\r\n"."Content-Type: multipart/alternative; boundary=\"PHP-alt-".$random_hash."\"";
$mail_sent = mail( $to, $subject, $_message, $headers );
}
?>
<title>HTML Email</title>
<style type="text/css">
</style>

<script type="text/javascript">
</script>
</head>
<body>
<h1><a href="html_email.php">HTML Email</a></h1>
<form action="html_email.php" method="POST">
From:<br/>
<input type="text" name="from" value="<?php echo $from; ?>"><br/>
To:<br/>
<input type="text" name="to" value="<?php echo $to; ?>"><br/>
Subject:<br/>
<input type="text" name="subject" value="<?php echo $subject; ?>"><br/>
Message:<br/>
<textarea name="message"><?php echo htmlentities($message); ?></textarea><br/>
<input type="submit" name="submit" value="Send"/>
</form>
<p>
<?php echo isset($mail_sent)?($mail_sent? "Mail sent":"Mail failed"):''; ?>
</p>
</body>
</html>


attachment_email.php


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<?php
// akobashikawa@gmail.com, 20090828

$from = isset($_POST['from'])?$_POST['from']:'';
$to = isset($_POST['to'])?$_POST['to']:'';
$subject = isset($_POST['subject'])?$_POST['subject']:'';
$message = isset($_POST['message'])?$_POST['message']:'';
if (isset($_POST['submit'])) {
$random_hash = md5(date('r', time()));
if (isset($_FILES['uploadedfile'])) {
$filename = basename($_FILES['uploadedfile']['name']);
$filetype = $_FILES['uploadedfile']['type'];
$tmp_file = $_FILES['uploadedfile']['tmp_name'];
$attachment = chunk_split(base64_encode(file_get_contents($tmp_file)));
}
?>
<?php ob_start(); ?>
--PHP-mixed-<?php echo $random_hash; ?>
Content-Type: multipart/alternative; boundary="PHP-alt-<?php echo $random_hash; ?>"

--PHP-alt-<?php echo $random_hash; ?>
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: base64

<?php echo base64_encode(strip_tags($message)); ?>

--PHP-alt-<?php echo $random_hash; ?>
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: base64

<?php echo base64_encode($message); ?>

--PHP-alt-<?php echo $random_hash; ?>--

--PHP-mixed-<?php echo $random_hash; ?>
Content-Type: <?php echo $filetype; ?>; name="<?php echo $filename; ?>"
Content-Disposition: attachment; filename="<?php echo $filename; ?>"
Content-Transfer-Encoding: base64

<?php echo $attachment; ?>
--PHP-mixed-<?php echo $random_hash; ?>--

<?php $_message = ob_get_clean(); ?>
<?php
$headers = "From: $from\r\nReply-To: $from";
$headers .= "\r\n".'MIME-Version: 1.0';
$headers .= "\r\n"."Content-Type: multipart/mixed; boundary=\"PHP-mixed-".$random_hash."\"";
$mail_sent = mail( $to, $subject, $_message, $headers );
}
?>
<title>Attachment Email</title>

<style type="text/css">
</style>

<script type="text/javascript">
</script>
</head>
<body>
<h1><a href="attachment_email.php">Attachment Email</a></h1>
<form enctype="multipart/form-data" action="attachment_email.php" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="100000" />
From:<br/>
<input type="text" name="from" value="<?php echo $from; ?>"><br/>
To:<br/>
<input type="text" name="to" value="<?php echo $to; ?>"><br/>
Subject:<br/>
<input type="text" name="subject" value="<?php echo $subject; ?>"><br/>
Message:<br/>
<textarea name="message"><?php echo htmlentities($message); ?></textarea><br/>
Attachment:<br/>
<input type="file" name="uploadedfile"/><br />
<input type="submit" name="submit" value="Send"/><br/>
</form>
<p>
<?php echo isset($mail_sent)?($mail_sent? "Mail sent":"Mail failed"):''; ?>
</p>
</body>
</html


Cada uno de estos scripts es una aplicación completa. Se presenta un formulario simple y se hace el envío de email.

Algo que es importante tener en cuenta al enviar Unicode es usar base64 para codificar el mensaje.

Y al enviar un adjunto es importante identificar el tipo de contenido, así como el nombre del archivo. Si no se coloca filename, además de name, en la descripción, el cliente email no reconocerá el adjunto (al menos no GMail).

Recuerde que para que funcione el envío, PHP debe estar configurado para reconocer algún servicio email, usualmente en el servidor local.

2009/08/19

Construyendo código

Al desarrollar una aplicación web me voy dando cuenta que el proceso es similar a cuando se dibuja, o se pinta algo. Pero también es útil pensar que es similar a cuando se construye algo.

De mismo modo que se ponen cimientos y una estructura base, uso un framework.

Uno podría hacer un framework aceptable. Afortunadamente hay frameworks estandar que puedo reutilizar y me ahorran mucho trabajo.

Pero quienes han hecho alguna vez un framework (quizás como yo, sin saber que así se llamaba), saben que es simplemente una forma de organización que va surgiendo conforme resuelves el problema. Es como un patrón de lugares comunes que van apareciendo en tu modo de resolver las cosas. Incluso aunque no hagas nada a propósito, el sólo hecho de intentar resolver el problema produce un framework.

Pienso que los framework estandar surgieron del mismo modo, pero por alguna razón (su simplicidad, elegancia, robustez, lo que sea), les pareció tan bueno a otros desarrolladores como para dedicarse a la tarea de mantenerlo y mejorarlo como un proyecto en común, un estandar.

Aún usando un framework estandar, para hacer algo nuevo se sigue la secuencia del bosquejo, funcionamiento, optimización. Es similar a levantar estructuras auxiliares, luego la estructura en sí, y después ir puliendo el trabajo.

Esa secuencia es como algo natural. Es demasiado complicado y propenso a errores tratar de desarrollar directamente 'en limpio'. Es como tratar de construir sin andamios, ni estructuras auxiliares, ni bosquejos, ni líneas guía.

El código va creciendo, simplificándose, creciendo, simplificándose. Pero entonces uno nota un problema. Si ya se tiene código funcional optimizado, las mejoras que se le puede hacer son relativamente pequeñas, del mismo modo que las correcciones que se pueden hacer sobre un edificio habitado, o sobre un dibujo ya terminado.

Sería interesante que se pudiera trabajar sobre el código original, con sus estructuras auxiliares y código aún sin optimizar, donde el espíritu de la solución es más palpable, y luego, de algún modo, iniciar un proceso de optimización estándar, una especie de compilación, que produzca el código optimizado para producción.

2009/08/18

Pintando código

Actualmente desarrollo una aplicación web que es un tablero de anuncios de trabajo. El lenguaje de programación es PHP. El framework, CodeIgniter.

He realizado todos los aspectos del desarrollo. Organicé los requerimientos, modelé las tablas, implementé los modelos, los controladores, y las vistas.
Trato de seguir el principio KISS, de mantener las cosas tan simples como sean posibles, pero no suele ser algo fácil.

Muchas veces he tenido la tentación de hacer algo que quede bien, para el futuro, o para cierto público exigente que me imagino debo complacer. Paso algo de tiempo divagando, pero eventualmente (afortunadamente) retomo la forma KISS.

Me parece que cuando uno ve código profesional, y está comenzando, puede tener la falsa impresión de que ese código se produce directamente tal cual lo vemos. Cuando vamos ganando experiencia es que notamos que es necesario pasar por soluciones intermedias para llegar a la solución final.

Pensándolo bien, así ocurre en otros tipos de desarrollo. Y puede que sea la forma natural de hacerlo.

Por ejemplo, una pintura que vemos colgada sobre una pared no es realizada directamente en limpio. Antes hubo un bosquejo, posiblemente sucio y horrible de ver, pero necesario para que llegara a existir. Un bosquejo que fue cambiado y corregido muchas veces antes de dar la primera pincelada. Luego, los colores se fueron aplicando por capas y zonas, de acuerdo a ciertos principios y técnicas, y también sufriendo cambios y correcciones mientras la imagen se aproximaba al ideal imaginado.

No tengo mucha técnica dibujando y mucho menos pintando, sin embargo, recuerdo algunas experiencias.

Recuerdo que, al comienzo, sin mucha guía, hubo veces que intentaba obtener directamente la versión final de una obra. Me concentraba en un área pequeña hasta completarla y luego avanzaba a un área siguiente.
No pasaba mucho tiempo hasta que notaba que algo andaba mal con el rostro que intentaba reproducir. Quizás cada parte por separado estuviera bien, pero el conjunto estaba, como se dice, descuadrado. Descubrí que me iba mejor si trazaba antes algunas líneas guía, que me ayudaran a recordar el tamaño, la posición y la forma aproximada de los ojos, la nariz, las orejas, y los labios, y luego recién desarrollar cada una de esas partes; es decir, bosquejar primero y desarrollar después.
Si se trataba de una imagen de cuerpo entero o donde aparecieran varios personajes, el bosquejo era mucho mejor opción que intentar lograr la composición directamente.

Puede ser que la costumbre de copiar dibujos es la que nos habituó a pensar que hacer una imagen por áreas, secuencialmente, era la única forma.
Pero es cuando uno trata de hacer una composición propia que descubre que es mejor trabajar por capas, iteradamente, mejorando cada vez la capa anterior.

Bailar es parecido. Al menos para mí. Aunque hay personas que insisten en tener memorizados pasos perfectos antes de comenzar a ensamblarlos, yo creo que es mucho mejor tener primero la secuencia, es decir el bosquejo de todo el baile y sus movimientos generales.
De ese modo puedo aproximarme con mas facilidad y menos frustraciones a la idea, y sentir cierta armonía que guía y ayuda a ir puliendo los pasos.

Planear la ruta de un largo viaje también es parecido. Es agotador, y hasta iluso, tener de antemano el detalle de cada tramo de la ruta, porque la práctica está llena de imprevistos. Es mejor hacer un bosquejo general, indicar los hitos principales, e ir desarrollando los tramos a medida que vamos avanzando.

Y para programar, he descubierto que también es similar.
No es malo hacer código repetitivo, usar muchas variables, ni otras cosas que muchos temen como si fueran pecados capitales.
No es malo, del mismo modo que no es malo garabatear una hoja cuando se está bosquejando.
Algunas veces para llegar a cierta posición, incluso puede ser necesario crear material auxiliar que luego se desecha.
Al inicio, lo principal no es la perfección ni la optimización, sino que simplemente funcione. Primero que funcione, luego se optimiza, me parece que dice un dicho de los hacker.

Claro que presentar código repetitivo, con demasiadas variables, o no optimizado, como versión final de un producto es como presentar un bosquejo en lugar del cuadro terminado. No te tomarán en serio, a menos que seas Leonardo.

Además, para desarrollar algo, es importante comenzar. No quedarse atorado en la trampa del perfeccionismo, ni esperar que todas las estrellas estén alineadas para dar el primer paso. Simplemente comenzar; dar el primer trivial paso; escribir código sucio quizá, pero que funcione. Luego se podrá factorizar, reorganizar, simplificar.

Factorizar es extraer el factor común de una expresión, de modo que se forma una expresión más simple o menos repetitiva. Es lo que se hace en álgebra.
Si alguien lo recuerda, no es conveniente factorizar una expresión cada vez que se le agrega algo; suele ser mejor esperar hasta que todos los términos estén presentes, para ver mejor el patrón. Si uno hace una factorización prematura, suele requerir un esfuerzo adicional desatar lo ya atado para ingresar el cambio y luego volverlo a atar.

De modo similar en programación. Es mejor no optimizar prematuramente el código, sino esperar hasta que esté completo para ver mejor el patrón, y luego factorizar. La optimización prematura puede fácilmente complicar el desarrollo. El código optimizado es mucho más difícil de depurar. Se debe optimizar, pero a su tiempo.

Más artículos