Por qué hay que enseñar a los niños a programar (entre otras cosas)

Creo que hay pocas experiencias más frustrantes que soportar que te enseñen cuando eres niño. Para empezar, quiero diferenciar claramente la enseñanza del aprendizaje pues cuando hablamos de la educación normalmente nos referimos a la enseñanaza, la cual, hoy en día, más parece que dificulta el aprendizaje antes que facilitarlo.

Opino que la raíz del problema consiste en destilar una serie de conocimientos y luego darle a los niños su ración de teoría y procedimientos sin ninguna explicación de cómo fueron descubiertos ni de cual es su propósito. Hasta que, perdidos entre tantos ejercicios, operan sin conocer los fundamentos.

Voy a enumerar algunas de las cosas que un programador sabe (sin darse cuenta de ellas). Estos son los fundamentos que un niño debería aprender de la programación (y que probablemente no le enseñen en el curso de informática del colegio).

Sobre la gestión de la complejidad

• Un programador sabe que nunca debe ponerse a hacer ninguna cosa sin una especificación de requisitos y un diseño. A priori, cada acción debe de servir para un propósito mayor definido con anterioridad.

• [Un programador sabe que] la única forma de resolver un problema grande y complejo es dividirlo en partes que se puedan resolver independientemente (divide y vencerás).

• Algunos problemas se pueden resolver aplicando repetidamente la misma operación sobre un conjunto de datos (por ejemplo una ordenación por burbuja).

• Cuando el problema es tan complejo que no se puede encontrar una solución exacta entonces hay que encontrar una solución aproximada y luego refinarla progresivamente observando los errores que se producen y pensando cómo podrían evitarse.

• Un sistema grande y complejo que no ha evolucionado a partir de otro más pequeño y simple, no funciona y, además, es imposible arreglarlo para que funcione.

• En cualquier proceso de intercambio de información, los datos deben estar siempre en la forma en que le conviene al receptor y no en la forma en que conviene al emisor.

• Todo está conectado con todo, la pantalla muestra sólo una ínfima porción del código. La tarea en curso son las cien líneas de código que se ven; pero hay otras cien mil líneas con interacciones con ellas y que no se ven.

• La complejidad del sistema de control es proporcional, y del mismo orden de magnitud, que el sistema controlado.

• Si has escrito más de 100 líneas de código y no sabes muy bien hacia dónde te diriges entonces es el momento de refactorizar el código y reconsiderar las estrategia de resolución del problema que estás aplicando.

• La complejidad se puede re-expresar u ocultar pero no se puede reducir. Lo único que se puede inventar son formas más fáciles de lidiar con la misma complejidad, no con menos complejidad.

• El mundo se describe con objetos, funciones y algoritmos. Los algoritmos explican cómo las funciones toman un objeto como entrada y producen otro como salida.

• Los objetos pueden tener un estado interno, aunque, en general, cuantas menos mutaciones pueda sufrir dicho estado mejor. Idealmente todos los objetos deberían ser inmutables (el estado interno de un objeto no puede ser modificado una vez establecido). Esta es la forma más segura de evitar que dos procesos concurrentes modifiquen simultáneamente el estado del mismo objeto dejándolo inconsistente.

Sobre la detección y corrección de errores

• Después de diseñar y escribir un programa hay que depurarlo. Se tarda más tiempo en depurar el programa que en escribirlo, durante la depuración es cuando se produce el verdadero aprendizaje acerca del problema que está siendo resuelto.

• Si se carece de una herramienta de depuración que te permita saber lo que está pasando dentro del sistema cuando no funciona correctamente entonces nunca conseguirás que funcione bien.

• El coste de corregir un error aumenta exponencialmente con cada etapa en la que la construcción del sistema avanza sin que sea detectado.

• La correción de errores siempre es prioritaria sobre la introducción de nuevas funcionalidades.

• Las funcionalidades de alto nivel sólo pueden implementarse sobre librerías base extraordinariamente sólidas y bien testeadas.

• Cualquier error, incluso el más aparentemente pequeño e inocente, puede hacer fallar todo el sistema.

• Cualquier protocolo de comunicación digno de tal nombre incluye siempre un mecanismo de detección y autocorrección de errores.

• Independientemente de la cantidad de control de errores que se realice, el sistema siempre encontrará una manera de irse a la porra de forma totalmente inesperada.

Sobre la sostenibilidad

• La mantenibilidad de un programa depende de su complejidad ciclomática (en el mundo offline el equivalente es que la mantenibilidad de un sistema depende de su carga burocrática).

• No basta con escribir código que funcione, además debe de estar escrito para que otros programadores lo entiendan (más sobre esto en porqué la mitad de la población no se entiende con la otra mitad).

• No existe el “código autodocumentado”. El código más legible explica (en el mejor de los casos) lo que hace y cómo lo hace, pero no explica por qué lo hace de esa manera ni qué problemas surgen al hacerlo de otra manera.

• Las partes deben conectarse entre ellas sólo mediante interfaces bien definidos. Los detalles internos de cada parte deben estar encapsulados y ocultos a las otras partes.

Sobre el rendimiento

• El tiempo de ejecución depende de la clase de complejidad, no del tiempo individual que tomen cada una de las operaciones, el cual casi siempre puede reducirse introduciendo mejoras técnicas.

• La geometría del dispositivo físico utilizado es crucial para la elección del algoritmo óptimo (en el mundo offline esto quiere decir que la geografía y la orografía son muy relevantes para la toma de decisiones).

• El pico de carga que deberá soportar el sistema es 100 veces mayor del máximo previsto.

• Los sistemas que pueden procesar mayor carga de trabajo son aquellos en los que procesos operando en paralelo se comunican de forma asíncrona.

• Para eliminar los cuellos de botella y evitar el agotamiento de recursos, es necesario aplicar optimizaciones globales además de optimizaciones locales.

• Existe un número óptimo de tareas que un sistema puede realizar simultáneamente. Si el sistema opera en modo monotarea entonces demasiados recursos estarán ociosos la mayor parte del tiempo. Pero si hace demasiadas cosas a la vez entonces pasará más tiempo cambiando de contexto que haciendo nada útil realmente.

• La solución más simple es en el 90% de los casos la que funciona mejor.

Sobre la organización de equipos

• La estructura de un sistema es isomorfa a la estructura del equipo que lo creó.

• Las personas de mayor valor intelectual no deben realizar tareas de mantenimiento (véase garbage collectors).

• Ningún programador profesional trabaja sin un sistema de control de versiones que le permita deshacer fácilmente los últimos cambios.

• Los sprints con objetivos a corto plazo cada dos semanas que se van sumando producen a la postre mejores resultados que las planificaciones trimestrales.

Sobre la seguridad

• Es más fácil atacar que defenderse.

• La mayoría de los virus no pretenden destruir el sistema sino realizar actividades parasitarias a su costa sin ser detectados.

• Es más fácil impedir una infección viral que eliminarla.

• Cuando el sistema está demasiado contaminado lo mejor es reinstalarlo por completo.

• Para cualquier información existe siempre una copia de respaldo (política de contención de daños para el peor suceso imaginable) además, se conoce el tiempo que llevará la restauración en caso de desastre.

• La historia de todo lo sucedido debe encontrarse siempre en los logs de la aplicación. Los logs deben tener un formato que permita explotar su información con fines estadísticos.

Sobre la fiabilidad

• El sistema sólo es tan fiable como lo sea su parte más débil.

• Los sistemas auténticamente fiables son altamente redundantes y carecen de un Talón de Aquiles (single point of failure) que pueda hacer caer todo el sistema.

• Cuando se produce un error crítico el sistema debe emitir inmediatamente una alerta. Las alertas más severas desencadenan normalmente una parada temporal del sistema a la espera de que el administrador compruebe qué está sucediendo.

• Cada vez que añades una funcionalidad añades también un puñado de errores. Los mejores sistemas no son aquellos que hacen muchas cosas mal, sino los que hacen unas pocas cosas extraordinariamente bien.

• La probabilidad de encontrar nuevos fallos es directamente proporcional a la cantidad de fallos encontrados recientemente.

• Cuando el sistema está sobrecargado y funciona con lentitud una buena solución temporal suele ser reiniciarlo.

• La ejecución parcial es malísima. Las transacciones deben bien ejecutarse, bien no ejecutarse; pero no deben ejecutarse a medias (en el mundo offline el equivalente es que los contratos no deben cumplirse a medias).

• Cuando la misma información debe almacenarse en dos sitios por cuestiones de rendimiento, entonces debe existir un proceso de consolidación capaz de restaurar la información correcta en el caso de que las copias diverjan y tengan datos diferentes o desactualizados.

Posts relacionados:
Cómo Internet modifica nuestras capacidades intelectuales y sociales.
Poner PCs aumenta el fracaso escolar.
Las TIC tienen impacto negativo en el rendimiento escolar.

Compartir:
  • Twitter
  • Meneame
  • Facebook
  • Google Bookmarks
Esta entrada fue publicada en Software Libre & Educación. Guarda el enlace permanente.

Una respuesta a Por qué hay que enseñar a los niños a programar (entre otras cosas)

  1. Pingback: Código de sólo escritura | La Pastilla Roja

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *