Eso no es POO. Es CACA.

Viernes 16 de Octubre de 2009

Aparentemente, programar usando un diseño orientado a objetos significa hacer un dibujito UML, decirle a nuestro IDE que cree un montón de atributos (obviamente todos privados; no querríamos romper el encapsulamiento), y luego generar todos los accesores y mutadores, no vaya a ser que después no podamos cambiar algo.

Al final, terminamos con una clase Persona, a la que cualquiera le puede decir que se cambie el nombre, el DNI, y cualquier cosa que le corresponda.

Eh, no.

Preguntémosle a Alan Kay, a Barbara Liskov, a Bjarne Stroustrup… y tantos otros, y creo que lo primero que nos van a decir es “Eso no es una clase; es una estructura”, y “¿No se suponía que ibas a encapsular los atributos?”…

A una interfaz siempre se puede agregar más métodos, sin romper nada, pero si borramos el más inútil de nuestros métodos, siempre va a haber alguien que estaba usándolo. Por eso el primer paso a un buen diseño es «No agregar accesores hasta que se demuestre útil. No agregar mutadores hasta que sea totalmente necesario.».

Ah, y, de paso: Las Properties1 no son más que accesores y mutadores disfrazados.

Tell, Don’t Ask

Traduciendo libremente de The Art of Enbugging, “Supongamos que el diariero viene a la puerta a cobrar lo que le debés de la semana. Te das vuelta, y él saca tu billetera de tu bolsillo, toma dos dólares, y te la devuelve. En vez de eso, el diariero debería pedirle al cliente que le pague los $2,00.”.

Para ponerlo en código (porque sí):

Diariero::Cobrar(Cliente* cliente, int cantidad) throw (EsUnRataException) {
    Billetera* billetera = Cliente->getBilletera();
    if(billetera->contenido() < cantidad) {
        cliente->setBilletera(billetera);
        throw EsUnRataException;
    }
    billetera.remove(cantidad);
    Cliente.setBilletera(billetera);
}

vs.

Diariero::Cobrar(Cliente& cliente, int cantidad) throw (DineroInsuficienteException) {
    Cliente.cobrar(cantidad);
}

Y el primero probablemente necesite revisar si el cliente tiene una billetera, ver si usa monedero o nada, cosa que nos obliga a agregar varios if donde podríamos haber usado polimorfismo.

¿Y mis porotos?

Los Beans (Objetos con accesores y mutadores para cada atributo, más un constructor sin parámetros) parecen ser la necesidad básica del programador de Java moderno (?). Todo tiene que ser un bean, si vamos a usar Hibernate, JPA o <inserte sigla de moda>.

Para muchos, eso es todo lo que se necesita para decidir que todos los mutadores deben ser públicos: ¡Si no no puedo usar Hibernate!… pero no. Hibernate pide que existan, pero no necesariamente que sean públicos: si son protegidos, es más que suficiente.

Of course…

Por supuesto, hay lugares donde los accesores son útiles, y mucho mejores que un constructor repleto de parámetros. Para los que no me crean, revisen la API de Windows:

m_hWindow =
    ::CreateWindow("AppWindow",          /* class name */
                   m_pszTitle,           /* title to window */
                   WS_OVERLAPPEDWINDOW,  /* style */
                   CW_USEDEFAULT,        /* start pos x */
                   CW_USEDEFAULT,        /* start pos y */
                   m_nWidth,             /* width */
                   m_nHeight,            /* height */
                   NULL,                 /* parent HWND */
                   NULL,                 /* menu HANDLE */
                   hInstance,            /* */
                   NULL);                /* creatstruct param */

Todos los NULL y CW_USEDEFAULT podrían haber sido valores por defecto. The Little Manual of API Design, de los creadores de QT, ofrece una alternativa, más similar a la que se usa en QT4:

window = new Window;
window->setClassName("AppWindow");
window->setWindowTitle(winTitle);
window->setStyle(Window::Overlapped);
window->setSize(width, height);
window->setModuleHandle(moduleHandle);

Una opción indiscutiblemente mejor: Ocupa menos líneas, y no involucra memorizar el orden arbitrario de los 11 parámetros del constructor anterior. Podría parecer más larga de escribir, por todos los “window” que se repiten, pero podría reducirse aún más si la API2 soporta un estilo más fluido (cada método retorna this), permitiendo algo como:

window = new Window;
window->setClassName("AppWindow")
      ->setWindowTitle(winTitle)
      ->setStyle(Window::Overlapped)
      ->setSize(width, height)
      ->setModuleHandle(moduleHandle);

…de lo cual más de un smalltalker se reirá.

Colecciones

Un lugar donde se nota obviamente la bestialidad de los accesores y mutadores es cuando hay colecciones de por medio. Primero, porque exponer una colección elimina cualquier posibilidad de concurrencia: Si dos métodos quieren modificarla, el único resultado va a ser un bug.

Además, se expone el tipo interno de la colección, removiendo otra de las características de la orientación a objetos: la implementación tiene libertad sobre la interfaz.

Acá hay que aplicar uno de los refactoreos de Fowler (y esto ya debería llegar a volverse regla natural): Encapsulate collection. Es simple: Primero, matamos el setter. No cumple ninguna función útil. Nos aseguramos, además, de que en el constructor se cree la colección. Después procedemos a liberar la responsabilidad de la colección: El getter retorna una copia inmutable. Y, finalmente, agregamos métodos que se encarguen de agregar o remover objetos de la colección.

Voilá: Nuestro objeto está un paso más cerca de ser, bueno, orientado a objetos.

Ley Anti-mutantes

Le debo una a William Stryker.

Una vez, discutiendo sobre OO con un amigo, le dije que todo debería ser inmutable, excepto en raros casos. Me dijo «¡Pero el chiste de la Orientación a Objetos es la mutabilidad del estado!».

Bueno, sí y no.

Más vale no.

Siguiendo con las colecciones, algunas son más críticas que otras. Si sólo tenemos un array de objetos, no importa que cualquiera de sus valores cambie. Ahora, si tenemos una hashtable, más vale que el hash nunca cambie, o van a pasar cosas muy malas.

Cualquier valor del que dependa hashCode (en Java) tiene que ser inmutable. Si no, estaríamos violando el contrato, y sufriremos mil y un bugs sutiles.

¡Bueno, basta, prometo no hacerlo más, pero dejá de escribir!

No todos los atributos de un objeto merecen un getter: Por cada getter exponemos implementación.

Muy pocos atributos merecen un setter: Si tiene que cambiar, que lo haga el objeto sólo.

Las interfaces deben revelar lo menos posible: No digas HashSet donde podés decir Collection.

Encapsulá tus colecciones.

El primer paso a una buena orientación a objetos es la paranoia.

  1. que admito amar
  2. O el lenguaje, con un constructo with o similar

Listas vs. Tuplas

Martes 28 de Abril de 2009

En la lista de PyAr hace no mucho alguien preguntó, «¿Cuál es la diferencia entre una tupla y una lista?». Acá hago una síntesis de las respuestas, y agrego mis notas.

Esta duda surge en Python porque, a primera vista, la única diferencia es que una usa corchetes, y la otra paréntesis: No importa si tengo una lista o una tupla, puedo acceder a sus elementos con [indice], y con cualquiera puedo hacer asignación múltiple (a, b = [1, 2])…

Lentamente las diferencias empiezan a aparecer:

  • Las tuplas, como los strings, son inmutables: Una vez que una tupla tiene un valor, no se puede cambiar, sólo crear una nueva.
  • Debido a lo anterior, las tuplas son hasheables: Se puede crear un diccionario que use como índice tuplas—pero nunca listas.

Estas diferencias técnicas son las más importantes, y las que justamente las definen.

Ahora, ¿Cuándo es mejor cada una?… En muchos casos realmente no hay diferencia: Si a cualquiera de las dos puedo acceder por índice, o con for… Pero podemos tomar una pista de un lenguaje más estricto: Haskell.

En Haskell, una tupla de 2 elementos es de un tipo diferente al de una de 3 (y no se las puede acceder por índice). Además, las tuplas pueden ser heterogéneas, mientras que las listas son homogéneas. Eso es, puedo tener una tupla (int, String, String), pero una lista puede contener sólo un tipo de datos (Claro, ese tipo puede ser una tupla… pero divago).

Entonces, lo «correcto» (con comillas) es que, si a todos los elementos se los va a tratar de una misma forma (sea con un for, o con map), usamos una lista, pero si cada elemento tiene un significado diferente, lo mejor es una tupla.

Gente Molesta

Domingo 26 de Abril de 2009

Las personas que más me molestan son las que me agregan al MSN, y la tercera pregunta que me hacen (después de «¿Te puedo hacer una pregunta?» y «¿Por qué me insultás así?») es «Sabés robar una contraseña?».

Chiste pésimo

Viernes 27 de Marzo de 2009
  • Tordek: Y a ver cuando aprendes Lisp vos, ¿eh?
  • Baltha: ¡Ya se la mitad de Lisp, ¿sabés? ¡¿Sabés?!
  • Tordek: ¿Qué, sabés ‘(‘?

22

Domingo 8 de Marzo de 2009
void envejecer(struct persona_s *persona) {
    persona->edad++;
}
 
envejecer(tordek);

Edit: Epa. Si no, no compila…

Experimentando con Frameworks CSS

Martes 3 de Marzo de 2009

Hace mucho escuché sobre ellos, pero nunca los había probado. Una promesa de solución al problema del layout —la parte de la disposición de los elementos en el diseño—.

Al omnisciente Google emití una plegaria de ayuda para ver de qué venía tanta alharaca, y me choqué primero con 960 Grid System, que parece ser el más simple de la familia.

Lo usé para armar un diseño que necesitaba rápido, y en seguida vi la mayoría de sus ventajas y desventajas:

Pros:

  • Diseñar con “grillas” (grids) da resultados bastante buenos, con una apariencia ordenada.
  • Si nos mantenemos dentro de los márgenes que el sistema de grillas propone, armar los diseños es rapidísimo y simplísimo.
  • Todos los problemas de compatibilidad de navegadores son cosa del pasado. Claro, sólo en la parte de división en columnas y eso.
  • Los templates que traen para Photoshop y demás facilitan el diseño.

Contras:

  • ¿División de contenido y presentación? ¿Qué es eso?
  • Diseños fijos1.
  • Cambiar una columna implica cambiar las demás para realinear.
  • La necesidad de agregar la clase clearfix en un elemento vacío es poco semántico.
  • El tamaño no es algo que se pueda decir «minúsculo»2.

Los frameworks CSS tienen una utilidad innegable. Ayudan a armar un diseño muy rápidamente, sin tener que preocuparnos por si va a andar o no en “el otro navegador”.

Por otro lado, puristas de la separación3 se van a quejar de que usar un framework CSS vence el propósito de usar CSS: estamos poniendo en el HTML las clases que determinan el tamaño de cada columna, en vez de poner eso en el CSS, como corresponde. Al poner clases sin significado (¿Qué es un «grid_3»?) a los elementos, estamos agregando información que no es nada semántica, y no ayuda en nada a un parser, pero este problema se minimiza si usamos, además de las clases de grid, ids y clases significativos.

En fin, los frameworks pueden dar resultados excelentes si lo que buscamos se presta al diseño en grillas, además de hacerlo rápido y fácil, y sólo los muy extremistas tienen lugar para quejarse —y aún así, tienen una opción de usar los frameworks «correctamete», usándolos primero para «ver cómo va a quedar», y después armar su propia hoja de estilos destilada—.

  1. Claro que esto no siempre es malo
  2. la versión minimizada de 960.css mide 3.6kb, pero, siendo que el archivo no cambia, es perfectamente cacheable
  3. Me incluyo.

XMonad

Martes 10 de Febrero de 2009

Off Topic: Es irónico… hace un mes, o más, que no posteaba… por, no sé, nada en particular; simplemente no lo hacía… Lo gracioso es que desde esa época, mis visitas empezaron a subir… ¿Es una señal?

Acá estoy, probando mi nuevo Window Manager, XMonad. Es un “tiling window manager”, lo que significa que cada ventana ocupa todo el espacio disponible, dividiéndo la pantalla (en realidad, cada escritorio virtual) según lo necesite.

Entre las cosas más grosas que tiene:

(Casi) no necesito usar el mouse.
Hay unos cuantos que se oponen a que abandone a la rata. Algunos infractores son Amarok (el botón de menú de mi teclado no hace nada en la lista de canciones) y las aplicaciones en Java (que, directamente, no puedo usar). Casi todo lo demás, lo hago usando la tecla Windows, acompañada de alguna letra, para navegar las ventanas, o dividirlas, o demás.
Haskell.
Haskell ya es groso de por sí; que XMonad esté programado en Haskell significa el fin de cuelgues y caídas, porque es casi imposible poner un bug.
Las divisiones de ventanas.
Un screenshot habla más que 1k DWORDS1
Se banca dos monitores. Pero bien.
Lo que siempre quise con KDE era tener un escritorio en cada monitor, y XMonad sí me deja; con Mod-[1-9] cambio la pantalla actual (que elijo con Mod+{w,e}) a uno de los escritorios.

Lo único que no está tan bueno es toda la configuración que requiere para empezar a usarlo; aunque es extremadamente personalizable.

Pruébenlo, si creen en eso de que el mouse es malo y lento, o simplemente tienen ganas de probar algo nuevo. Yo lo uso porque me gusta maximizar mis ventanas tanto como tener varias a la vista :P…

  1. Especialmente uno de 2560×1024

Indirecta

Viernes 19 de Diciembre de 2008

[Comentario humorístico, indirectamente religioso]

Disclaimer: Esto es tan solo una traducción. No representa la opinión del autor de este blog, ni ninguno de sus participantes. Sólo lo estoy haciendo porque quiero visitas en mi blog, y estoy poniendo contenido que, aparentemente, no respeto, en un espacio personal.

Do what you mean. Do what I mean.

Jueves 4 de Diciembre de 2008

El diálogo de “¿Estás seguro?” es total y absolutamente inutil. Estuve discutiendo con un amigo, que dice que no es así, pero la única conclusión que tengo es: Si necesitás ese diálogo, tu sistema está mal diseñado.

—Pero, —algunos se quejarán— ¿y si me equivoqué? ¿Y si después de que lo hice me dí cuenta que no lo quería?

Bien, primero: Si te diste cuenta después, el botón de “estás seguro” no te salva. Obviamente, la opción no es “Ja, lástima, para qué hacés click ahí”. Existe una que sirve de verdad, y que hace mucho nos dimos cuenta que se puede: Deshacer.

Si en Windows se me ocurre borrar un archivo, va a la papelera. Si me equivoqué, lo recupero. Si en Thunderbird borro un mensaje, está en la basura.

Aparte, ¿para qué cambiar el significado de las cosas? Tengo un botón borrar. ¿Qué hace ese botón? ¿Borra? No. Me muestra una ventana que me pregunta “¿Estás seguro?”, y al hacer click en “Sí”, recién borra. ¿Desde cuando “Borrar” significa “Preguntame si quiero borrar”, y “Sí” significa borrar?

Y es imposible quejarse acerca de implementarlo. Si nuestra aplicación usa alguna forma de base de datos, tenemos una marca de “Borrado”. Si usa el sistema de archivos, una carpeta donde almacenamos los archivos ‘Borrados’.

Confirmar es inutil, Deshacer es divino, o como quieras ponerlo, basta de preguntas, y hacé lo que dije.

Vimpress; un buen editor en WordPress

Martes 25 de Noviembre de 2008

Interesante plugin para vim1. Con sólo un par de comandos, :BlogNew y :BlogSend, puedo editar un nuevo post en vim, y publicarlo directamente en mi blog.

Se lo pueden bajar de la página de su autor, y, como todo plugin de vim, lo único que tienen que hacer es descomprimirlo en su .vim/plugins.

No tiene muchos comandos, pero tampoco los necesita:

  • :BlogList para ver la lista de todos los posts;
  • :BlogNew para crear uno nuevo;
  • :BlogOpen id para editar uno; y
  • :BlogSend para, finalmente, publicar…

Veamos qué tal….

Edit:

Hasta ahora, me gusta; en particular porque me molestan los WYSIWYG porque lo que ves no se parece en nada a lo que sale (Y no te dan la mitad de los tags… a menos que uses el editor HTML, sacándole todo el chiste.)

Ah, y se banca categorías, tags, y varias otras cosas (aunque no me deja editar el texto del permalink).

  1. El único editor que vale la pena… Morite, emacs.

Oops…

Domingo 23 de Noviembre de 2008

Eh, no, el blog no estuvo caido; sólo que cuando lo actualicé me olvidé de copiar mi .htaccess…

Ceceo ya es un poquito más lindo; sólo estás a una bajada y un make de distancia de poder hacer, simplemente '(a b c) => (a b c).

No es la gran cosa, pero es un Lisp…

Y mi problema con bison eran los malditos strings de C; estaba guardadando el puntero al string, en vez de una copia. Ahora sí.

Bueno, sigue sin tener un recolector de basura, pero qué se le va a hacer.

Ceceo 0.1α released

Domingo 19 de Octubre de 2008

Así como lo molesté a Juanjo Conti por un par de cosas que no andaban de su Lisp, me puse a hacer uno yo.

Implementa sólo las raíces de lisp; las 7 primitivas básicas y las 6 funciones derivadas de estas —aunque, la verdad, no las uso…—, según detalla The Roots of Lisp.

En el proceso aprendí varias cosas:

  1. Bison me odia1.
  2. Las unions sirven para algo.
  3. LISP es todavía más groso que lo que imaginaba.
  4. ([a-z]|micro|pico|femto|atto)lisp ya existe.

Bien, le falta mucho para estar completo; en particular, le falta la parte interactiva; por ahora es sólo un lisp-en-c; si se quiere hacer, digamos, (quote a) (y evaluarlo, claro), hay que hacer eval(cons(symbol("quote"),cons(symbol("a"),symbol("nil"))))

Por esto, tampoco probé si lambda hace lo que debe y demás.

No tiene ningún tipo de números, porque tenía planeados ponerlos cuando haga funcionar el REPL.

Y finalmente, no hay recolector de basura…

Si alguien, por algún bizarro motivo, tiene ganas de usar el código, está en una de mis páginas secretas, liberado bajo la licencia BSD.

¿Será este el comienzo de una nueva era? ¿Una donde empiece a liberar código?… sólo el tiempo lo dirá.

  1. ¿Alguien se anima a tirarme una mano?

Lo siento…

Lunes 13 de Octubre de 2008

Amigos… Programadores… Desarrolladores…

Lo lamento… en serio… no merezco ningún tipo de respeto. Deberían revocarme la membresía del club…

Estoy en un estado de pecado: Me aburro y no tengo ningún proyecto personal para trabajar.

Me siento sucio.

Socializando

Martes 7 de Octubre de 2008

Una pregunta para todo el que lea mi blog o el feed de codear:

¿Qué listas de correo, foros, canales de chat y demás suelen visitar para discutir de programación?

Tanto general como de lenguajes y tecnologías particulares.

Una lección de vida

Domingo 5 de Octubre de 2008

El WoW te chupa la vida, pero tus feeds siguen actualizándose1.

RSS waits for no man.

  1. Me quedan 500… eran más de 2000.

Mis políticas para los comentarios

Viernes 19 de Septiembre de 2008

No son realmente políticas estrictas, y no las aplico con todo el rigor, pero son bastante claras…

  1. Modero todos los comentarios. No prohibo los que se me opongan, pero sí los que no aporten a la discusión.
  2. No edito los comentarios. Ni ortografía ni significado. No quiero quejas de «eso no es lo que dije».
  3. No borro comentarios que ya acepté.
  4. No acepto comentarios estúpidos.
  5. No acepto comentarios mal escritos. Todos cometemos errores, y la ortografía puede no ser perfecta; pero esa no es excusa para «skrivir haci». Hay límites1.

Me encanta cuando la gente comenta en mi blog; o cuando me hace simplemente un link, así pase una vez al año… aunque hay casos que preferiría no recibirlos…

En ¿Por qué usar la linea de comandos si mis ventanas son tan lindas?, alguien decidió repetir mi post entero, sin agregar nada a la conversación; acepté el comentario, pero fue un error.

Un par de personas comentaros en mis posts sobre programacion para principiantes preguntándome cómo programar. Uno no sabía lo que eran los signos de puntuación. El otro nunca vio un diccionario.

En Leé tu código, algún nonomaníaco dijo 9 quien 9 te 9 piensas 9 que 9 sos 9 para 9 decir 9 “recién ahí aprendiste a programar.” 9 no 9 tenés 9 idea. 9 quien 9 te 9 creés 9 chingado. 9

Esos son algunos comentarios que no quiero ver en mi blog… Pero quiero comentarios… los invito a la discusión.

  1. Y tienden a 0

No molestes al usuario

Lunes 1 de Septiembre de 2008

Tu programa puede hacer maravillas y ahorrar miles de horas y pesos cada vez que lo usas.

Pero esa no es razón para molestar al usuario. Además, si tu propósito es ahorrar tiempo, ¿por qué gastarlo obligándolo a hacer cosas innecesarias?

El tipo de interfaz no importa

No importa si es una línea de comandos, ventanas múltiples, juegos, si usa el teclado, el mouse, un joystick, o cualquier otra cosa; el usuario es el que importa, no tu programa.

A lo mejor a vos te tome media hora más agregar el código para auto-configurar el programa al instalarse, pero ahorrar un minuto a cien usuarios es todavía más tiempo.

Una regla importante

The Art of Unix Programming, de Eric Raymond, nos cuenta la historia de Unix, y las características de sus programas, interfaces, y qué es lo que lo hace bueno —y malo— para programar. De ésto robo una regla relacionada a la interfaz:

La Regla de Silencio: Si un programa no tiene nada sorprendente que decir, no debe decir nada.

No me avises que abriste el archivo; no me digas que todo fué bien —o, al menos, no me molestes si lo hacés. Una caja de mensajes modal1 diciendo “Archivo abierto correctamente [OK]” es una pérdida de tiempo y nada más. Si tenés que avisarme, al menos no interfieras. Por ejemplo, el diálogo de “Guardar Contraseña” de Firefox 3, que no interfiere con el flujo.

Cuando dudes, copia

A todos nos gusta ser únicos y originales, pero si diseñamos nuestro programa de manera que el usuario sienta que ya lo usó antes, no va a sentirse intimidado diciendo que es difícil de usar.

Si ya hay un programa que hace lo que vos querés, considerá robar su apariencia (Firefox, con ciertas excepciones, es igual a Internet Explorer). Claro, hay excepciones; DarkRoom, por ejemplo prácticamente elimina la interfaz, sacando del medio cualquier tipo de botón y menú, y sólo las opciones de abrir, guardar, y crear un nuevo archivo… pero DarkRoom tiene una razón para hacerlo.

  1. O sea, una que no deja hacer nada hasta que se le hace click

Leé tu código

Lunes 25 de Agosto de 2008

Programs must be written for people to read, and only incidentally for machines to execute.

Abelson & Sussman, Structure and Interpretation of Computer Programs

Todo el código que hagamos será leído, en algún momento, por otra persona. Incluso si somos los únicos en mirar nuestro código, los mismos que cuando lo escribimos. No estamos pensando lo mismo que entonces, y no lo conocemos igual.

Siempre tenemos que escribir código de la manera más legible posible, y sólo cuando se demuestra que la claridad interfiere con la velocidad Y la velocidad es importante, podríamos pensar en reescribir.

Si tenemos estructuras que podemos reconocer, y las aplicamos a nuestro código, será mucho más rápida la lectura, porque podemos reconocer de un vistazo qué partes son importantes.

80 caracteres por línea

En tiempos anteriores esta regla nació de la incapacidad de las terminales de mostrar líneas muy anchas. Muchos piensan que, dado que ya no es problema, es una regla irrelevante, pero se equivocan: El número mágico es 7 ± 2. Esto significa que se puede tener en memoria inmediata entre 5 y 9 elementos. Esto nos da una longitud promedio de nombre de 9 a 16 caracteres; descontando espacios, comas, paréntesis y demás, nos quedan cerca de 6 a 10 caracteres por nombre.

Al ingresar en un bucle, o en un condicional, indentaremos lo que pongamos adentro. Recordar que estamos en un bucle gasta uno de los espacios en memoria, así que tenemos menos espacio para la línea.

Las líneas cortas son más fáciles de entender.

Múltiples puntos de salida

Algunos lenguajes (como Pascal) nos lo prohíben, pero tener múltiples puntos de salida de una función pueden acortarlas y reducir la indentación:

def alternar(lista1, lista2):
    retorno = []
    if(len(lista1) > 0):
        if(len(lista2) > 0):
            retorno = [lista1[0], lista2[0]] + alternar(lista1[1:],lista2[1:])
        else:
            retorno = lista1
    else:
        retorno = lista2
    return retorno

puede ser reescrito, mucho más legible, como:

def alternar(lista1, lista2):
    if(len(lista1) == 0):
        return lista2
    if(len(lista2) == 0):
        return lista1
 
   return [lista1[0], lista2[0]] + alternar(lista1[1:],lista2[1:])

Primero nos deshacemos de los casos especiales, y finalmente actuamos sobre el caso recursivo.

En una función encargada del login, por ejemplo, sólo actuamos si el nombre de usuario es válido—o, si usamos múltiples puntos de salida, salimos inmediatamente al encontrar un usuario inválido.

Sintaxis significativa

Nada impide usar un for, y a veces es lo mejor. Reg Braithwaite nos dice que la sintaxis es una señal: si queremos aplicar una función sobre cada elemento de una lista, y nos interesa el valor de retorno, es mejor usar un map; si nos importan los efectos colaterales, es mejor un bucle.

Estructuras poderosas

El lambda es hermoso. Funciones anónimas, como objetos de primera clase, clausuras, y otros conceptos de la programación funcional, que podemos encontrar en Python, Ruby, Lisp, y más, son más que útiles para aprender, o como diría Eric Raymond: Lisp is worth learning for the profound enlightenment experience you will have when you finally get it; that experience will make you a better programmer for the rest of your days, even if you never actually use Lisp itself a lot..

La mejor forma de mejorar (valga la redundancia) es salir de lo que estamos acostumbrados, aprender un concepto nuevo, y resolver un problema—quizá uno que ya hayamos resuelto— con lo que acabamos de aprender.

Implementá una lista enlazada simple en un lenguaje orientado a objetos, usando sólo una llamada a un método por línea. Calculá el dígito de verificación de un CUIT con map y reduce.

Y si mientras lo hacés aprendés un lenguaje nuevo, grokkeas el concepto que acabás de aplicar, y te gusta, recién ahí aprendiste a programar.

No sé tu password. Pero podría averiguarlo.

Lunes 18 de Agosto de 2008

No, no te ‘hackearon’ el password. Y, probablemente, tampoco te lo robaron. Casi seguro, vos se los diste.

Vos no te enteraste. Probablemente estás totalmente seguro de no habérselo dicho a nadie. Aún así, si vamos por lo más probable, es tu culpa.

Primero una corta explicación. Prometo que no va a doler.

Cuando vos entrás a tu mail, sea cual sea tu proveedor (aunque, si te ‘hackearon’, todavía estás usando Hotmail1), les mandás dos datos: tu nombre de usuario, y tu contraseña.

Obviamente, en algún lugar está guardado todo eso; ahí entran las bases de datos. Puede ser algo tan simple como un archivo de texto con un usuario y una contraseña en cada uno, o servidores dedicados para almacenar tus datos protegidos y copiados mil veces, y en varios lugares del mundo, para que si uno se rompa, tus datos sigan ahí.

Pero esos detalles no nos importan.

Lo único que importa es que la máquina sabe si la contraseña que le pasaste es la tuya.

Pero, claro, ahora tenemos que confiar en que nadie va a conseguir una copia de ese archivo, y robar tu preciada contraseña (claro que, si se llevan el archivo, tienen tres millones más, pero por algún motivo, sólo les importa la tuya).

La versión corta, es que aunque tengan el archivo, no les sirve. (Bueno, si entraron en un servidor, probablemente se bajaron todo tu correo, no sólo tu contraseña.)

La versión larga involucra encriptación. Encriptación indescifrable.

En un sentido muy estricto, no existe tal cosa. Todo código se puede romper. Lo importante es que sea muy, muy, muy difícil.

Tu contraseña no está guardada. Tampoco, si vamos al caso, una versión encriptada de tu contraseña. Lo único que Hotmail guarda es un hash. No, no la droga. Un hash es un valor derivado de tu contraseña. Con la característica particular que éste sí es irreversible. Esto tiene una parte buena, y una mala: la buena es que no pueden adivinar tu contraseña. La mala es que, matemáticamente hablando, hay infinitos valores que devuelven el mismo hash.

Por dar un ejemplo trivial, supongamos un hash que consiste en asignar un valor (de 1 a 26 —sin la ñ—) a cada letra del alfabeto, reemplazar cada letra en la palabra por el valor, y sumarlos. Para “Tordek”, sería (20, 15, 18, 4, 5, 11), que da 73.

Entonces, el hash de Tordek es 73, pero a partir de 73 es imposible deducir “Tordek”. La suma es conmutativa, así que el orden de las letras es irrelevante. También puedo cambiar letras en grupos, de manera que el cambio se equilibre (ejemplo: T+1 = U, O – 1 = N, +1 – 1 = 0), que me da “Unrdek”, cuyo hash da igual.

Claro que, un hash de verdad (SHA-1, MD5) es un poco más complicado que eso. Pero el principio es el mismo.

Pero… con infinitas contraseñas para el mismo valor, ¿no se vuelve trivial encontrar una contraseña con el mismo hash?

No.

Incluso MD5, que ya se considera obsoleto, devuelve valores de 128 bits, 3,4 x 10^38 valores diferentes. Infinito dividido por eso, sigue dando infinito—pero no podés crear las infinitas contraseñas posibles. Y aunque pudieras, tarda mucho (si creamos cien millones cada segundo, tardamos 3 x 10^30 segundos, casi 10^23 años, y el universo solo tiene 1.4 x 10^10). La probabilidad de encontrar una contraseña que devuelva el mismo hash que otra que conocemos es 2,9 x 10^-39. Muy, muy, muy difícil.

Si somos paranóicos, podemos guardar tanto el MD5 como el SHA1 de una contraseña, y esperar que ambas coincidan, y ahí tenemos 128 + 160 bits. Eso es mucho. En serio. Si además agregamos una sal —un valor aleatorio, con el proposito de hacer el password todavía más largo (aunque sólo dentro de la base de datos)— bueno, digamos que lo más fácil es creerme que no se puede.

Por eso están desapareciendo los sitios que te mandan tu password al mail. Si pueden hacer eso, es porque se puede desencriptar (o, peor, ni siquiera se encripta). Y en ese caso sí te pueden ‘hackear’. No confíes en esos sitios.

Entonces, si no te pueden hackear, ¿cómo consiguen tu contraseña?

Ya te dije: se la diste. Ingeniería social es el nombre técnico. Mentir es más fácil.

Varios sitios ofrecen “exploits”; uno clásico es el mensaje de «(alguien) te mandó una tarjeta. Ingresá tu contraseña para abrirla.». Es tu culpa si caíste.

La otra es que tenés una “pregunta de seguridad” muy fácil. O que tu contraseña lo sea.

Mi contraseña más común tiene 12 caracteres. Algunos números. La saben, al menos, 3 personas. Nunca me robaron nada.

Y como última opción, sí, te pueden “hackear” (a vos, no a Hotmail). Mediante dos ataques, principalmente: uno es instalarte un keylogger, un programa que guarda cada tecla que apretás; el otro se llama “man in the middle”, que consiste en ocupar alguna máquina ubicada ‘en el medio’, entre vos, y el servidor, como, por ejemplo, el servidor de un cyber.

Hay formas de protegerse de cada uno de estos ataques, y eso queda para la próxima.

  1. Y, no, no es culpa de Hotmail

KDE 4.1

Miércoles 13 de Agosto de 2008

Uh, sé que ya es martes, casi miércoles, y debería haber posteado el lunes, pero desde que instalé KDE 4.1 me la pasé toqueteando las configuraciones como hago siempre…

Veamos…

Lo bueno

El eye-candy es bastante variado, el nuevo estilo Oxygen es bastante sutil, y bastante parecido al de los OS X, y todas las aplicaciones que vienen con KDE están bien integradas. La apariencia se vuelve aún mejor si activamos composite y los efectos de escritorio, que al fin vienen integrados, como parte propia de KDE.

Una parte donde vemos diferencias es en el panel de configuraciones, renombrado de kcontrol a systemsettings, con los distintos módulos ordenados por clase de configuración.

El panel de ejecutar comando nos muestra las opciones posibles mientras vamos escribiendo, como el hermoso menú de Baghira.

Es más de lo mismo, así que los usuarios del anterior se van a sentir como en casa, pero más lindo.

Lo malo

El 4.1 es una exageración. Todavía es un beta, aunque no lo lleve en el nombre, y le faltan muchas cosas que 3.5.9 ya tenía: no se puede ocultar los paneles, manual ni automáticamente; Kopete deja los avisos de mensaje nuevo abiertos hasta que les hagamos caso.

Algunos módulos de configuración parecen desnutridos, con sólo un par de opciones, aunque en la versión anterior teníamos muchas más. La configuración de la pantalla muere sin aviso si tenemos XRandR desactivado, como suele ser cuando tenemos dos monitores en una placa nVidia1.

La transparencia de ventanas está rota, y cualquier cosa por debajo de 100% hace que sea invisible.

¿Sí o no?

Y… es usable. Los problemas que tuve son mayormente visuales, casi nada como para descartarlo todavía; planeo quedarme —aunque espero que salga un 4.2 pronto—.

Por otro lado, si tuviera que volver a hacer lo mismo para instalarlo, me quedaría con 3.5… y eso que lo único que hice fue wget -r y upgradepkg –install-new. Todavía no vale la pena cambiarse… pero tampoco es tan feo como para reinstalar el anterior. Si querés mucho, mucho eye-candy, y no te importan perder un par de funcionalidades, quizá te guste intentarlo. Si dependés de las funcionalidades (a mi me gusta que los paneles se oculten automáticamente, para que la ventana en la que estoy trabajando ocupe la mayor parte posible del escritorio), mejor quedate en la 3, al menos hasta que esto se arregle.

Para los slackers como yo, los paquetes para Slackware 12 los pueden bajar de éste repositorio.

  1. Se puede arreglar usando TwinView, pero no hay nada para hacer si usamos dos placas independientes