5 de marzo de 2006

Me gustan los errores devueltos en cadenas de error

Aparentemente a alguien no le ha parecido buena queja mi queja sobre que Unix debería volver códigos de error en forma de cadenas en forma de enteros. Creo que debería haber explicado exactamente que quiero decir por devolver cadenas de error en vez de números (lo cual no quiere decir que me vaya a arrepentir de algo de lo que dije, más bien lo contrario)

Básicamente, mi queja era que yo quisiera que se pudiera hacer "si 'cvs update' = 'No updates found"" en vez "si 'cvs update' = 0". ¿Por qué? Porque "No updates found" significa algo, y "3", no. Si me gustaría probar cadenas de error en vez de códigos es porque tienen significado, y eso es bueno.

Pero vayamos por partes. Algo que no admito es que la gente se ponga a hablar de "filosofía Unix", de potencia, de scripts y de extendibilidad en un post que supuestamente va a críticar a las cadenas de error. Las cadenas de error no restan extendibilidad ni potencia ni nada por al simple razón de que son prácticamente lo mismo. El programador quiere saber lo que ha devuelto el comando y en vez de utilizar un código, utiliza una cadena de error, punto. Las posibilidades son exactamente las mismas.

La persona a la que le gustan los códigos de error tambien dice que se evitan problemas como que en una actualización/modificación del software un cambio en una simple letra tire al traste todo lo que se haya construido encima. Me gustan ese tipo de afirmaciones en las cual se dice que tal cosa tendrá tal efecto y ese efecto es efecto secundario (indirecto), porque en muchas ocasiones la asociación que se hace a ese efecto secundario no tiene porque tener ni pies ni cabeza, como en este caso: Si las cadenas de error son malas porque al cambiar una letra todo se va a la mierda, los códigos de error son malos porque cambiando un "2" a un "3" tambien mandarás todo a la mierda, y puestos a ser cínicos tal vez sea solo yo, pero mientras que cambiar un número apenas se notaría a primera vista - porque en realidad no significan nada por si solos sin una asociación a un código de error - una falta en una cadena de error se notaría mucho más. Si nos ponemos a buscarle siete patas al gato, porque no afinar un poco y sacar ocho. Lo de traducir ni lo comento: en ningún lado he propuesto que dichas cadenas de error deberían ser traducidas. Eso es como proponer que el "if" debería traducirse a "si" cuando compila un español. Los programas deben funcionar correctamente al margen del idioma del usuario, punto.

Pero voy a explicarme más: No me he sacado esto de la manga, repito, y no son solo sistemas operativos como Plan 9 los que me hacen pensar que las cadenas de error son mejores (llamarlas "cadenas de error" es un poco inadecuado, porque para empezar no tienen porque indicar un error, pero bueno). Aquí va un ejemplo de por qué lo que pido no es ninguna fantasía absurda

if (malloc(...) == NULL)

¿Se ve, o no se ve? NULL no es más que un define a "(void *) 0". No solo es NULL: Hay millares de defines de C en el mundo desde hace décadas, algunos de ellos se utilizan para comprobar el retorno de las funciones (no tan a menudo como se podría por desgracia). Tengo un preload.c aquí que hace un switch y luego tiene un "case PROC_EVENT_FORK", "case PROC_EVENT_EXIT", y un "case PROC_EVENT_EXEC".

¿Por qué en C se hace esto desde hace décadas y esta bien, y cuando propongo que bash haga lo mismo a la gente no le gusta, tan metida tiene la gente los "estándares" en la cabeza como para no tener un poco de imaginación e imaginarse cosas distintas a las que utilizamos? ¿Tan mala es la idea de poder hacer un "if cvs update = 'no update found'"? ¿O por qué no puedo hacer un case "$(cvs update)" in en bash, y a continuación poder poner "no update found"), "no repository found") igual que hago en C con los switch, en vez de poner 5), 2) y -1)?.

Si fuera yo, diseñaría el sistema para que los programadores proporcionaran esas cadenas de error y que estas cadenas se pudieran utilizar en bash, en C y en cualquier lenguaje de manera uniforme. La manera simple de implementar esto es utilizar códigos números que se correspondan con las cadenas de error y dejar que el lenguaje de turno se las arregle de la manera que le plazca. Si uno quiere utilizar el preprocesador en C, pues bien. Si bash quiere comprobar cadenas de texto, pues cadenas de texto. Eso es el método "conserva la compatibilidad". Pero la idea de que unix devuelviera cadenas enteras tal como hace 9P en Plan 9 (que tiene por cierto más "espiritu Unix" que Unix y que es el sistema operativo que utiliza desde hace años uno de los dos creadores de Unix) no me parece absurda (incluso considerando los inconvenientes) en absoluto, porque aunque parezca inútil el facilitar la gestión de errores ayudaría a hacer más fácil la gestión de errores que es uno de los problemas que tienen muchos programadores para construir software más robusto, y por eso estoy dispuesto a pagar un precio, al igual que los creadores de Unix se arriesgaron cuando decidieron utilizar un lenguaje interpretado para programar el kernel, un sistema de archivos jerárquico y un shell fuera del kernel (en aquel tiempo la norma era implementar el kernel en ensamblador, meter dentro el shell y los sistemas de archivos no jerárquicos). Para tener lo que tenemos hoy se tomaron en su día decisiones arriesgadas que en aquel tiempo eran medio herejías para algunos. Si tuviera oportunidad (que no la tendré nunca pero pongamos que si por el bien de este post) no me importaría tomar una decisión arriesgada como el que los procesos devuelvan cadenas de texto en las llamadas al sistema, por muy herejía que parezca.

2 comentarios:

  1. Yo iria mas lejos de lo que propones y obtaria por un modelo parecido a la nueva shell de MS (Monad), que para mi gusto es lo más innovador que ha hecho esa empresa en toda su historia. Y en el caso de las famosas cadenas de error, nada de cadenas o numeros, OBJETOS, como en cualquier lenguaje de programación moderno.

    ResponderEliminar
  2. rrey me saco las palabras de la boca, o del teclado.

    Que bueno seria que los errores devueltos fueran objetos, eso facilitaria mucho la depuración.

    ResponderEliminar