2017/04/04

Termux para programar en un android

Termux (https://termux.com) es una aplicacion que emula una consola Linux en el Android.

Una vez instalada, se puede instalar ssh:

$ apt update
$ apt install openssh
$ ssh myuser@myserver.com

Una vez conectado a un servidor, se puede usar los comandos Linux de ese servidor.

Yo probe entrar a un servidor en Digital Ocean, crear un proyecto React, usar el editor vim, ejecutar el proyecto y ver el resultado en una pagina web, abierta en Chrome en el mismo celular (Android reconocio alternar  entre aplicaciones con Alt+Tab).

Si ademas cuentas con un teclado conectado via bluetooth, la sensacion puede ser como la de tener una mini laptop con touchscreen ^^

Tip:
En Termux, para abrir mas de una consola, arrastrar el dedo desde afuera del borde izquierdo hacia adentro.

2017/02/22

Imprimir formas en consola

En un aviso de Workana encontré un pedido como este:

Escribir un programa que pregunte al usuario elegir una forma para dibujar en la pantalla.
La forma puede ser: Circle, X, Box y un Box con una X.
También el usuario indica cuántas filas se usarán para dibujar la forma.
La forma debe ser dibujada con asteriscos (*).

Me parece que se trata de un programa para correr en consola.

En mi caso, me pareció más práctico intentarlo con php.

shapes.php

<?php
do {
 print "1. Circle\n";
 print "2. X\n";
 print "3. Box\n";
 print "4. XBox\n";
 fscanf(STDIN, "%d\n", $option);
} while (!$option);

do {
 print "Number of rows: ";
 fscanf(STDIN, "%d\n", $rows);
} while (!$rows);

for ($i=0; $i<$rows; $i++) {
 for ($j=0; $j<$rows; $j++) {
  $print_dot = false;
  switch ($option) {
   case 1:
    $print_dot = is_circle($i, $j, $rows);
    break;
   case 2:
    $print_dot = is_x($i, $j, $rows);
    
    break;
   case 3:
    $print_dot = is_box($i, $j, $rows);
    break;
   case 4:
    $print_dot = is_xbox($i, $j, $rows);
    break;
  }
  if ($print_dot) {
   print "*";
  } else {
   print " ";
  }
 }
 print "\n";
}

function is_circle($i, $j, $rows) {
 $r = $rows - 1;
 $d = pow(($i - $r/2), 2) + pow(($j - $r/2), 2) - pow($r/2, 2);
 return abs($d) <= $rows/3;
}

function is_x($i, $j, $rows) {
 return ($i == $j) || ($j == ($rows-1) - $i);
}

function is_box($i, $j, $rows) {
 return ($i == 0) || ($j == 0) || ($i == $rows-1) || ($j == $rows-1);
}

function is_xbox($i, $j, $rows) {
 return is_x($i, $j, $rows) || is_box($i, $j, $rows);
}


El ejercicio me pareció interesante para ver una manera simple de tomar una entrada desde consola. Y cuando llegué a la parte de impresión de formas me pareció más interesante. En particular la del círculo, que dejé para el final.

Algunos conceptos de coordenadas y geometría analítica me ayudaron a completar el programa.

El problema del círculo es, en el fondo, cómo imprimir una imagen en un medio de baja resolución.

Esta es la forma en que se me ocurrió resolverlo, con una especie de detección de borde seteado a $rows/3, al tanteo (para que se vea bien el círculo en 4, 8 o 16 filas).

Seguramente hay muchas maneras de resolverlo. ¿Cómo lo harías tú?


2017/02/17

Invertir una cadena con javascript

¿Cómo harías una función que invirtiera una cadena dada?
Es decir que f("abcdef") sea "fedcba".


Yo pienso que no hay una "forma correcta" de resolverlo. Simplemente hay formas, y cualquiera que se te ocurra y haga el trabajo está bien.

De todas esas formas habrá algunas que logran hacerlo con menos variables o menos código, o usando técnicas esotéricas. Formas optimizadas.

Hay programadores que se familiarizan con esas técnicas optimizadas y las aplican luego directamente en los siguiente problemas que enfrentan. Puede ser impresionante, como cuando ves a un mago sacando del sombrero cosas que no creías posible. Igual que con los magos, se requiere de práctica y ensayo para lograr esas cosas. Pero, igual que con los magos, no significa que esa es la forma en que todo el mundo debería pretender hacer las cosas.

La optimización prematura es la raíz del mal, es la advertencia de Knuth, comprobada una y otra vez en la experiencia de los programadores. Está bien optimizar, por supuesto, pero tiene su momento, y definitivamente no es al inicio.

En la vida real, la solución de los problemas se produce por tanteo. Como en un cuarto oscuro, estiras los brazos y tientas. Tocas algo una y otra vez, formándote una idea de lo que hay. Así, descubres la puerta hacia la solución. Una vez que la descubriste, podrías volver al punto de partida y hacerlo más rápido, en menos tiempo o de manera más elegante. Recién ahí es que se realiza la optimización. Si intentaras salir a toda velocidad al inicio, sería muy probable que te lastimaras con algún obstáculo o fueras rápido en la dirección equivocada. También sería un poco raro hacer movimientos elegantes si ni siquiera sabes a dónde vas a ir.

Así que para este problema, quizás se te podría ocurrir algo como:

// recorrer la cadena en reversa
function f(s) {
 var result = "";
 for (var i=s.length; i>0; i--) {
  result = result + s[i-1];
 }
 return result;
}

Ok, es lo primero que se me ocurrió. Veamos si se puede hacer mejor. Quizás se pueda recorrer la cadena de otro modo:

// recorrer la cadena de frente pero acumular en reversa
function g(s) {
 var result = "";
 for (var i=0; i<s.length; i++) {
  result = s[i] + result;
 }
 return result;
}

¿Y si vemos como luce con reduce?:

// usando reduce y acumulando en reversa
function h(s) {
 return s.split("").reduce(function(result, c) {
  return c + result;
 });
}

¿Y usando la notación fat arrow?:

// usando reduce y fat arrow
function j(s) {
 return s.split("").reduce((result, c) => c + result);
}

Quizás con la práctica sea esta forma la que aparezca primero en tu cabeza en el futuro. Podría ser impresionante. Pero hay que recordar que las cosas empiezan tanteando. Y que está bien.

2017/01/28

Qué hacemos



Es diferente el sentimiento de desarrollar algo sin tener que hacerlo por cumplir sino porque realmente te interesa.

En lugar de simplemente cubrir las horas por las que te están pagando, o los tickets que se acordaron para el sprint, te encuentras jugando con la idea de cómo podría ser mejor. Y cuando sabes que esas ideas podrían aplicarse, sientes como la alegría de estar yendo por un bonito camino.

Me pregunto cómo en un trabajo pagado podría incentivar ese tipo de actitud.

Me parece que podría ser cuando hay claridad en lo que se quiere lograr, y el sentimiento de autonomía.


No es una buena idea recordar a alguien que se le está pagando por hacer cierto trabajo. Eso baja el nivel de la conversación hasta el primer peldaño de la pirámide de Maslow.

Es triste que  tu jefe o tu cliente crean que solo trabajas por el pago que recibes. Tú sabes que lo haces por un propósito mayor, o te gustaría que así fuera, pero esos comentarios motivan a cumplir solo lo mínimo necesario.

Más arriba en la pirámide de Maslow, cuando las necesidades básicas han sido cubiertas, trabajamos para ejercitar las habilidades que disfrutamos desarrollar. Si recibimos algo por ello, qué bien. Pero si no nos pagaran, igual lo haríamos.

Ese es el tipo de trabajo que es difícil de entender para quienes se han acostumbrado a trabajar para sobrevivir.

Hay personas que siguen pensando así aunque sean ricas y ya no tengan procupaciones económicas. Y lo transmiten a sus hijos, familiares, amigos o colegas o empleados.

Antes, quizás era necesario pensar así para poder sobrevivir. Dejar atrás lo sueños y sacrificarse por lograr un mérito material.

Pero hoy, pensar así conduce a la extinción.

Las soluciones de antes van quedando obsoletas. Hay que ir imaginando lo que construiremos mañana mientras van cayendo los edificios a nuestro alrededor.

Las nuevas soluciones están viniendo de la mano de gente apasionada por lo que hace. Logran ver cosas que nadie más. Logran hacer cosas que nadie más.

No puedes hacer que tu hijo se enamore de la mujer que te parece que más le conviene.

Tampoco puedes hacer que un empleado sienta pasión por lo que más conviene a la empresa.

Tienes que encontrar alguien que ya lo sienta, y cuidarlo.

También puedes orientar tu empresa para que aproveche lo que sus apasionados miembros son capaces de construir juntos.


Las empresas están descubriendo que, en lugar de vender lo que haces, hay más éxito vendiendo el por qué lo haces.

Pero no es lo mismo preguntárselo a alguien que trabaja por encargo que a alguien con pasión por ello.

2017/01/21

La importancia de solucionar algo

Amazing Grace

A Grace Hopper se le dio el encargo de elaborar el manual de instrucciones de una de las primeras computadoras creadas en los Estados Unidos.

A la Marina, le interesaba averiguar de qué modo podría aprovechar el potencial de la nueva máquina Mark I.

No era común que una mujer perteneciera a la armada, y tampoco tenía los estándares de peso y talla, pero sus habilidades matemáticas le ayudaron a ser admitida y abrirse camino.

Ella propuso organizar bajo nombres más asequibles las rutinas que había coleccionado con su equipo, y un esquema para reutilizarlas con más facilidad y automatizar la generación de las secuencias binarias que eran la forma normal de programar las computadoras en aquella época.

Normalmente, para programar la solución de un problema, había que enfrentarse con el hardware y los interruptores necesarios para implementar el programa. Era como tener que atravesar continuamente una bruma mental para distinguir lo que se quería conseguir.

En cambio, usar un compilador de código tenía la ventaja de permitr pensar con más claridad en el problema que se quería resolver.

Sin embargo, su propuesta fue desechada porque el código binario generado de ese modo era más largo y menos eficiente.

Grace persisitió en ello como un proyecto personal. Desarrollando lo que vendría a ser conocido como lenguaje ensamblador, o Assembler.

Uno de sus amigos, que había estado meses con un equipo tratando de programar la solución de un problema especialmente difícil, logró hacerlo en unas horas usando Assembler.

Poco a poco, el uso del Assembler se fue extendiendo.

Años después, creó COBOL, el primer lenguaje de programación, que permitía expresar un programa en algo parecido a sentencias en inglés.

Menos eficiente pero más eficaz

Hoy en día, prácticamente toda la programación se hace con ayuda de compiladores y los lenguajes de alto nivel que aparecieron luego del COBOL. De ese modo, los problemas no solo se resuelven con más rapidez, sino también con menos errores. Y si los hubiera, son mucho más fáciles de localizar.

La propuesta de Grace de usar lenguajes de más alto nivel para solucionar problemas encontró resistencia en otros programadores que desdeñaban el código binario repetitivo, largo e ineficiente que se producía de ese modo. Ellos podían hacerlo más simple, más elegante, del "modo correcto".

Los programadores que podían programar directamente en binario no eran muchos y quizás se sentían un poco como sumos sacerdotes. Los intermediarios exclusivos entre la gente y las máquinas todopoderosas.

Los lenguajes de alto nivel tuvieron la virtud de hacer la programación de computadoras accesible a más personas.

Sigue siendo cierta la observación de que el código binario producido por los compiladores es más repetitivo, largo y menos eficiente que el que se podría producir directamente. Sin embargo, con la mejora de la velocidad de procesamiento, la programación directa en binario ya es muy poco práctica.

Es más importante llegar primero a la solución de un problema. La eficiencia del resultado se podría ir mejorando luego de eso (finalmente reemplazando código por assembler y luego por binario si el rendimiento fuera algo vital).

Algo hecho es mejor que lo perfecto

¿Qué es mejor, una solución perfecta que tarda tanto que nunca llega, o una solución que funcione?

"Done is better than perfect" es una famosa frase acuñada por la gente de Facebook.

La comunidad hacker tiene además "Primero que funcione, luego optimizas".

Y Donald Knuth, la famosa "La optimización prematura es la raíz de todo lo malo".

No son opiniones. Expresan un hecho, comprobado una y otra vez en la experiencia de los programadores y los equipos de programadores y los proyectos de programación.

Aún así, de cuando en cuando encontrarás a otros programadores o desarrolladores de software insistiendo en buscar la perfección o hacer optimizaciones durante la solución.

Es la optimización mal entendida.

Optimizar algo está bien, pero su momento es después que haya una solución.

Solo puedes mejorar algo que tienes, si no, la optimización es una falacia (y las falacias son peligrosas porque suelen tener ese aire de verdad que hace que uno las acepte si no se anda con cuidado)

Código limpio

A la computadora le da igual si el código está limpio o no.

El código limpio es una optimización orientada a los programadores para facilitar el mantenimiento del programa.

Pero, igual que toda optimización, su momento es después que tengas una solución, no antes.

Hay que disfrutar garabateando con código, esbozando algoritmos, en el proceso de concretar una solución.

Pretender escribir código limpio durante el proceso de solución es tan contraproducente como pretender pintar la versión final de un retrato directamente sobre un lienzo en blanco.

Cómo odio a los haters :-)

Hay programadores que automáticamente tienen actitudes hostiles o de desdén hacia ciertos lenguajes de programación, ciertos frameworks o ciertas librerías.

"PHP es el peor lenguaje de programación jamás inventado"

"Javascript es un lenguaje de juguete que no se puede tomar en serio"

"Todos esos frameworks son basura que complica las cosas"

Pero minimizar lo que nos disgusta no hace que nuestras soluciones sean mejores. De hecho, impide ver las soluciones de otros.

PHP es un lenguaje que ha ayudado mucho a democratizar la programación en Internet. La valla es más baja y mucha más gente puede entrar y cometer errores que hacen sonreir con desdén a ciertos académicos y profesionales. Pero ha permitido que muchas ideas geniales vean la luz. Más de la mitad de los blogs en Internet están hechos en WordPress, que es un administrador de contenidos escrito en PHP. Wikipedia está escrita en PHP. La base de Facebook también estuvo escrita en PHP.

Javascript ha evolucionado. No es solo para hacer efectos especiales en una página web. Permite crear interfaces complejas. Y en el lado del servidor, facilita el desarrollo de soluciones ligeras, asíncronas y sin bloqueos. Paypal usa Javascript en el backend. Hay quienes consideran que actualmente Javascript tiene uno de los más completos ecosistemas de desarrollo web.

Los frameworks son herramientas para resolver problemas. Como un martillo, o una sierra. Puede tomar su tiempo conseguir maestría en su uso. Muchos dedos golpeados, cortes accidentales. Y puede que no sean para todo tipo de problemas. Quizás haya herramientas más sofisticadas, o más ligeras, pero posiblemente te enfrentarás a más problemas si intentas hacer carpintería con una piedra, un cuchillo, o una navaja suiza.

Creo que siempre es más constructivo tratar de ver las buenas partes, usar esas buenas partes y evitar las otras.

También aquí es cuestión de ver el vaso medio lleno.

Referencias

2017/01/13

La falacia de "hacerlo sin frameworks"

Hay una idea difundida entre muchos desarrolladores acerca de que es mejor no usar un framework en lo posible.

El Framework F tiene las deventajas a, b y c; por lo tanto, si no lo usan, evitarán esas desventajas, concluyen.

Veamos por qué esto es una falacia (un razonamiento errado que parece correcto). Las falacias son peligrosas porque parecen correctas.


Un framework es, en esencia, un conjunto de convenciones sobre cómo usar un conjunto de librerías.

Cuando usas un framework, vas notando cómo sus convenciones condicionan el modo en que abordas las tareas y resuelves los problemas. Poco a poco, empiezas a visualizar las soluciones en términos del framework.

Esa pauta que establece el framework puede ser de gran ayuda para mantener orden y estabilidad en un proyecto. Y también para darle continuidad.

Pero también puede ser que las convenciones sean demasiado reguladoras, restrictivas o limitantes. O que haya problemas que sean de solución muy dificil o imposible en términos del framework.

Entonces tenemos:

Framework F
Pros Contras
m a
n b
p c


Para analizar qué framework elegir, sería:

Framework F Framework G Framework H
Pros m
n
p
Contras a no no
b no no
c no no

Así que si esos frameworks tienen esas desventajas, no los usemos y así las evitaremos.


Suena lógico. Sin embargo, es un error.


Lo que realmente están proponiendo es esto:

Framework F Framework G Framework H Framework X
Pros m ?
n ?
p ?
Contras a no no ?
b no no ?
c no no ?

¿Qué es el Framework X?

Es el framework (propio aunque negado) que se irá definiendo (sobre la marcha).

Las preferencias de uso, las posibilidades y limitaciones, y el contexto de trabajo del equipo de desarrollo, determinarán un conjunto de librerías y cómo se deben usar.

Es decir, un framework.


Por eso, lo que realmente están proponiendo los desarrolladores que "evitan frameworks" es:

"No uses un framework conocido (con todas sus ventajas, horas de prueba, comunidad y documentación) y usa mi framework (que aún no existe pero va a ser mejor que todos ellos)"


Si aceptas esa propuesta, automáticamente estás asumiendo un proyecto extra que deberá correr en paralelo al que quieres realizar. Porque hacer un buen framework consumirá tiempo y recursos en codificación, documentación y capacitación.

No es que te estés ahorrando el costo de usar un framework; estás asumiendo el costo de hacer uno.

"No hemos usado ningún framework, así que no tienes que aprender nada nuevo para empezar".

No es verdad. Verás que tendrás que familiarizarte con el conjunto de funciones y librerías que están usando, la forma en que las llaman y la particular (o peculiar) manera como el proyecto se ha organizado (o ha resultado ser).

Si usas un framework conocido, puedes tener más apoyo de la comunidad, documentación, casos de ejemplo, etc. Habrán más personas que ya lo conocen y están disponibles para colaborar contigo.

Es cuestión también de saber ver el vaso medio lleno y valorar las virtudes del modelo open source.

El efecto Dunning-Kruger

Es un efecto psicológico que se observa en todas las personas, de pensar que son más competentes en aquellas cosas en que realmente tienen más limitaciones:

Why Do Incompetent People Think They're So Great?


¿Estamos siendo afectados por el efecto Dunning-Kruger?

Usando las buenas partes

Creo que es importante ser claro en lo que se hace, y tratar de mostrar claramente lo que sucede cuando nos damos cuenta que está sucediendo.

Porque solamente podemos construir castillos de verdad usando ladrillos de verdad.

Reinventar la rueda es muy util para desarrollar las habilidades de invención.

Poder hacer un propio framework que sea comparable con los frameworks conocidos es algo admirable.

Pero no es el mejor camino minimizar lo que esos frameworks conocidos son para que así la tarea de competir con ellos resulte más fácil o nuestro trabajo parezca más meritorio.


Siempre es posible encontrar algo desfavorable en un framework, algo que no puede hacer tan bien y que quizás nosotros podamos hacer mejor (en un contexto más simple, aisladamente).

Me parece más interesante juzgar los frameworks en función de las cosas favorables. De lo que nos permiten hacer. De los problemas que nos pueden ayudar a resolver.

Porque tampoco podemos construir castillos con ladrillos que no tenemos. Hay que usar lo que sí tenemos.


Hay una cita de Addy Osmani como recomendación acerca de los frameworks:

“First do it, then do it right, then do it better.”

Primero usa lo que hay, conócelo realmente. Si encuentras algo que mejorar, corrígelo. Luego intenta hacerlo mejor.

Buscar

Más artículos