domingo, 5 de octubre de 2008

Resultados de la encuesta "12 factores clave para decidir cambiar de empresa".

La consigna para las respuestas era "Evalúa tu situación laboral a través de estos 12 factores clave para decidir cambiar de empresa, que surgen de un estudio realizado por Gallup". Las calificaciones van de 1 a 6 para cada punto.

Incluyo aquí estos dos gráficos de resumen, el documento completo junto con las definiciones de cada punto está aquí. También pueden descargar una versión en PDF en este link.

Obviamente la cantidad de resultados no da para sacar conclusiones muy generales. Tiene el sentido de relevar la temperatura en el muy acotado universo de quienes leen este blog más o menos asiduamente.

Confirmo que somos mayoría de programadores, y casi todos de profesiones vinculadas al desarrollo de software (raro sería si no fuese así): analistas, consultores, líderes técnicos o de proyecto, etc.

viernes, 3 de octubre de 2008

La cadena del error.

El 30 de septiembre se publicó La cadena del error en el blog de aviación TCAS.

Es medio largón el post, para leer con tiempo. Es imposible no estar de acuerdo con las centradas opiniones del autor, que demuestra en ellas la lógica irrebatible de quien conoce de lo que expone, ubicándose lejos de las frases rápidas, baratas y efectistas de los opinadores profesionales.

Los conceptos vertidos son fácilmente extrapolables al desarrollo de software. Vale la pena una segunda leída con esta visión en mente.

Visto mientras navegaba en Dirección de Proyectos.

Jueguitos de viernes: Bloons.

Bloons: Tan simple y adictivo como parece. Para rematar la semana.

Via Microsiervos - Adiós, productividad (donde hay más todavía).

La realidad de los programadores.

Rebotando por Mi delicious me topé con esta viñeta del muy recomendable Sinergia sin control. Espectacular.

Visto en El Blog de Inwe.

Errores y excepciones (III)

Errores y excepciones (I)

Errores y excepciones (II)

Errores y excepciones (III)

El manejo de errores y excepciones fue una de las cuestiones que más me costó aprender en mi vida profesional.

Aunque parezca un sin sentido, me ayudó bastante empezar con Visual Basic, en la época en que todavía no tenía un manejo estructurado de excepciones, que recién fue incorporado en la versión 6 (creo).

En aquellos tiempos poco le importaban a mi jefe (como a todos, creo) las cuestiones metodológicas, la prolijidad del código, la arquitectura o el devaneo filosófico alrededor del desarrollo de software... y la verdad que a mí tampoco, solamente me divertía escribir código, cosa que hacía muy poco profesionalmente, era más bien un juego por el que me pagaban.

Cuestión que en mi primera aplicación de escritorio y luego de un par de pruebas, la consigna era que el sistema no se tiene que cerrar jamás a causa de un error (cosa que ni se me había cruzado por la cabeza). Sin pensarlo dos veces, metí manos a la obra.

Pasé por la etapa del On error resume next. Es fácil darse cuenta de que no sirve para nada. Al fin y al cabo, si una función o procedimiento no daba error, probablemente lo daría el que lo llamó. Además ocasionaba comportamientos extremadamente impredecibles, por decir lo menos. La aplicación se cerraba menos, pero funcionaba peor y lo más divertido de todo era depurarla...

Luego tuve mi etapa de a prueba de balas, en el que trataba, en cada procedimiento, de pensar qué haría ante un fallo o respuesta inesperada de cualquiera de los procedimientos a los que llamaba. Esto genera código imposible: contemplaba en cada llamada una cantidad de respuestas y situaciones que nunca ocurrirían, llenando todo de código que nunca se ejecutaría. Usualmente lo que daba error era el código que hacía esas comprobaciones. Es extremadamente difícil y bastante inútil. ¿Cómo podemos pensar qué haríamos ante un error del que no tenemos ninguna información?

Así que después de un par de tortazos (pruebas y errores, muchos errores) me dí cuenta de que solamente tenía que controlar los errores de programación en un sólo lugar: trabajaba con Visual 5 en una aplicación de escritorio, así que éste tipo de errores hacían "explotar" a la aplicación sólo en un punto: en el código que maneja los eventos en los formularios. Cualquier error burbujea hasta el manejador del evento que recibe el comando del usuario y ahí explota, cerrando la aplicación.

Así que me dediqué a poner On error goto MensajeError, un Exit Sub y luego la etiqueta MensajeError, que llamaba a una función que mostraba los datos del error y listo. El código era bastante feo.

Como no me gustaba tener código impredecible o código inútil, borré cualquier manejo de error que no sea el mencionado. Y todo anduvo de perillas.

Pero con más pruebas surgieron problemas: algunos errores se daban en momentos poco oportunos, dejando archivos abiertos, operaciones por la mitad y un sinfín de basura y cosas a medio hacer. Y aparte se mostraban errores catastróficos por algunas tonterías: falta de validaciones de los datos ingresados por el usuario, sobre todo.

Así que de vuelta empecé a poner manejo de errores más allá de los manejadores de eventos, para "limpiar" eventuales desastres.

Pero me di cuenta de que los mensajes son importantes: como usuarios, imaginen que después de ingresar 20 datos en una pantalla el sistema les dice Duplicated primary key o algo por el estilo. Un programador puede decir "ya ingresaste ese código de producto", pero para el usuario el sistema no funciona, y no entiende por qué. Mi única solución para el caso era corregir la falta de validación, arreglando la omisión de programación que se veía tan fea.

Cuando comencé a utilizar lenguajes orientados a objetos y manejo estructurado de errores (Exception en el código), sobre todo en C# reproduje la misma estructura de control de errores.

Y luego, recién después de un tiempo más, aprendí a usar excepciones en una forma más genérica y no pura y exclusivamente para el manejo de errores de codificación.

Todo ese recorrido me hizo llegar al manejo de bloques try...catch...finally sabiendo (por lo menos en una mínima parte) para qué servían. Y eso fue fundamental. Porque (esto lo veo en programadores junior y también en alumnos) que entender conceptualmente qué es un error, qué es una excepción y qué hacer con ello, es muy duro. Aún con mejores herramientas, creo que todos transitarán un camino parecido al mío (salvo que utilicen intensivamente una que yo no tuve al principio: internet).

Creo que éstos tres artículos fueron un pasable resumen, que tal vez con un poco más de tiempo pueda emprolijar y complementar con más ejemplos. Sugerencias, como siempre, más que bienvenidas.

jueves, 2 de octubre de 2008

Errores y excepciones (II).

Errores y excepciones (I)

Errores y excepciones (II)

Errores y excepciones (III)

Ya definimos error y excepción. Todo para llegar a La Teoría (con mayúscula) que es bastante simple. Voy a tratar de enunciarla como yo la pienso:

Un procedimiento es un pequeño sistema: tiene entradas definidas, salidas definidas, y un objetivo, al que usualmente le decimos responsabilidad. Preferentemente una y sólo una responsabilidad (que puede delegar en otros procedimientos, pero que debe poder enunciarse fácilmente y de la que de todas maneras sigue siendo responsable, eso ya lo sabemos).

Vamos a la responsabilidad: una función, un procedimiento, un método o una propiedad o todo el sistema, debe tener sólo dos respuestas posibles: o hace lo que tiene que hacer y devuelve lo que tiene que devolver, o no hace absolutamente nada y de alguna manera avisa.

Ésa es la ley primera, y es inapelable. Ahora las sutilezas.

Avisar no es necesariamente explotar, y el motivo no es necesariamente un error de programación. No estamos hablando necesariamente de errores, sino de cualquier situación o estado que le impide a una porción de código cumplir con su responsabilidad.

Simplemente tiene que explicitar que algo le impidió hacer su tarea, diferenciando ésa respuesta de los otros resultados válidos. Puede explotar de mala manera con un mensaje incomprensible (algo es algo), puede ser un mensaje amable al usuario (más bonito), puede ser una entrada en un log de errores (más escondido y sutil), o puede ser un código especial de retorno, lo que sea, pero algo tiene que decir.

En un lenguaje orientado a objetos la herramienta natural que cualquier porción de código tiene a mano para decir que no pudo hacer lo que tenía que hacer (y que no hizo nada) es arrojar una excepción (throw en C#). Pero no es la única forma de implementación, lo importante es seguir el principio teórico, la forma variará según la ocasión.

Ahora, ya que una porción de código tiene que decir que no hizo lo que tenía que hacer, puede que sea relevante el por qué. Ojo, digo puede y no debe... la información que devolvamos tiene que ser acorde a la situación.

En la primera parte vimos que la excepción de negocio sólo lleva como información el mensaje que hay que mostrar al usuario. Aparte, el hecho de ser una excepción de negocio la diferencia, por ejemplo, de una excepción por un error de código.

El resto del sistema no hace nada especial con la excepción generada. Simplemente muestra el mensaje, y entiende que para el usuario es relevante (por lo que lo colocará en algún lugar donde pueda verlo, pero eso es responsabilidad del front-end).

En C#, si el resto del código tiene que tomar alguna decisión basada en detalles de la excepción pueden agregarse propiedades. En el ejemplo, si el código tiene la posibilidad de generar un aviso de necesidad de compra por la cantidad faltante, el dato puede viajar como valor de la propiedad "FaltanteDeStock" de la excepción junto con el mensaje. Si no es necesario, no. Lo más simple es lo mejor.

La responsabilidad de avisar también puede delegarse, como cualquier otra. En el caso del error por referencia nula es el framework el que avisa al procedimiento de negocio que no puede consultar el valor de una propiedad. El método de negocio, al dejar pasar la excepción, avisa al que lo llamó que esa excepción le impidió completar la operación.

Y llegamos a que un error de programación es una excepción del componente que hayamos invocado, de alguno interno de éste, o del framework, o del sistema operativo. En algún lugar hubo una validación y el equivalente a un throw. Algún algoritmo no pudo completar su tarea, y está avisando. Y debemos pensarlo como cualquier otra excepción. Un error de programación es un tipo especial de excepción.

La decisión de interceptar o no determinado tipo de excepción tendrá que ver con:

  1. No impide realizar correctamente la operación, por ejemplo codificando algún curso de acción alternativo. En este caso decimos que la estamos resolviendo o manejando. El código que la resuelve no arrojará una excepción, sino otro de sus retornos esperados.
  2. Hay que ejecutar algún tipo de código para cancelar la operación en forma prolija (por ejemplo haciendo un Rollback). En este caso se la intercepta, se codifican las instrucciones para la cancelación y se la deja seguir (throw a secas en C#) o lanzamos una nueva excepción (creando una nueva y especificando la excepción original en el InnerException, en C#), si es que tenemos información propia que agregar.

Llegamos ahora a la segunda parte importante de la teoría: una excepción indica que el algoritmo que la arroja no hace absolutamente nada. Esto implica que si inicié una operación de base de datos tengo que poder deshacerla ante cualquier excepción, si abrí un archivo tengo que cerrarlo, si modifiqué alguna variable o propiedad compartida tengo que dejarla como estaba, y así con todo. Donde haya un uso de un recurso compartido (léase base de datos, archivo o variable) tendrá que haber un control de excepciones.

El ejemplo más sencillo es el de la transacción de base de datos:

        Datos.BeginTransaction();
        try
        {
            //...(operaciones)...
            Datos.Commit();
        }
        catch
        {
            Datos.RollBack();
            throw;
        }

Aquí, desde que el código comienza a utilizar el recurso persistente (la base de datos) tiene que asegurarse de que cualquier excepción (error de programación o no, no importa) cancele todas las modificaciones. Una vez que se cancela pasa la información sobre los motivos (la excepción) a los procedimientos superiores.

El único objetivo del bloque try...catch es cancelar la transacción. Si la excepción se produce antes del inicio de la operación (por ejemplo en la llamada a BeginTransaction) no hay motivo para atraparla.

Si ningún algoritmo puede manejar una excepción (por ejemplo en el caso de un error de programación en algún lado) llegará al front-end. Y la decisión de mostrarla o no al usuario y de qué manera dependerá del caso. Si es un error de negocio se mostrará un mensaje, si es de conexión tal vez se muestre un mensaje genérico y se guarden los detalles en un log, si es un error interno de un componente de terceros, tal vez se muestre información específica... las posibilidades son infinitas.

Pero lo importante es que el front-end, más allá de lo que muestre o no, preserve la información relevante. Esto es especialmente importante en el caso de los errores, donde toda la información contenida en la excepción ayuda (en C# es importante utilizar el método ToString de la excepción, que devuelve todo su contenido).

miércoles, 1 de octubre de 2008

Entorno de desarrollo para programadores de verdad.

By ChuckNorris (foto)

No me vengan con Visual Studio, Eclipse, JBuilder, NetBeams, Lazarus, y yo qué sé qué más.

Los programadores de verdad no necesitamos IntelliSense, ni colores ni refactory, ni nada de eso.

Los programadores de verdad utilizamos un entorno de desarrollo liviano y rápido que nos permite trabajar en Binario, Assembler, o C (para los novatos). También sirve para cualquier otro lenguaje (aunque los programadores de verdad no necesitemos de otros lenguajes).

Para aquellos que no lo conocen, se los presento en versión Windows: se llama Notepad. Aquí les dejo un screenshot:

Para mí es perfecto. La única contra que se le puede apuntar es que para programar en binario hay que traducir los octetos a ASCII mentalmente, pero los programadores de verdad nos acostumbramos en los primeros minutos de uso.

Hay más información en Wikipedia, y novedades sobre la versión para web en http://www.notepad.org/.

Con el uso de este tipo de herramientas podrás iniciar el largo camino que te llevará a ser un verdadero programador.