2007/06/20

Programación de orientación abyecta

Esto es una traducción sin autorizar del artículo "Abject-Oriented Programming".

La programación de orientación abyecta es un conjunto de prácticas para promover la reutilización de código y asegurarse que los programadores producen código que se pueda usar en producción durante mucho tiempo. El número de líneas de código en la aplicación es una medida común de la importancia de la aplicación, y el número de lineas que un programador puede producir al día, a la semana o en un mes, es una métrica útil para la planificación de proyectos y la reserva de recursos. La programación de orientación abyecta es una de las mejores formas de conseguir el mayor número de lineas de código en el menor tiempo posible.

abyecto: desesperanzado, miserable, humillante o penoso: pobreza abyecta

Herencia

La herencia es una forma de mantener características del código antiguo en código más nuevo. El programador deriva de una función que ya existe o de un bloque de código haciendo una copia del código, y modificándola posteriormente.

La copia derivada a menudo se especializa añadiendo características no implementadas en el original. De esta forma el código antiguo se mantiene, pero el nuevo código hereda de él.
Los programas que usan herencia se caracterizan por bloques similares de código de los que surgen pequeñas diferencias a lo largo de los fuentes. Otra señal de herencia son los miembros estáticos: código y variables que no se usan ni referencian directamente, pero que sirven para mantener un enlace al código progenitor o base.

Un ejemplo de herencia en pseudo-código:

function getNombreClnt(IDclnt)
{
    regClnt = readFromDB("cliente", IDclnt);
    nombrecompleto = regClnt[1] + ' ' + regClnt[2];
    return nombrecompleto;
}

function getEmailClnt(IDclnt)
{
    regClnt = readFromDB("cliente", IDclnt);
    nombrecompleto = regClnt[1] + ' ' + regClnt[2];
    /***************
    * 4/15/96 git : dirección email está en
    * el segundo campo del fax
    ***************/
    return regClnt[17];
}

La función getEmailClnt fue heredada de getNombreClnt cuando se introdujeron direcciones de correo a la aplicación. Heredar código de esta forma potencia código que funciona con menor riesgo de introducir errores.

El subtyping es una forma de herencia donde los tipos de las variables se cambian al heredar del código original.

Modularidad

Un programa modular es aquel que está dividido en archivos separados que comparten un bloque de comentarios común en la cabecera. Un módulo normalmente está compuesto por:

  • Nota de copyright
  • Descargos legales
  • De tres a cinco líneas de asteriscos
  • Un historial de cambios
  • Una descripción de lo que se supone que hacía el código originalmente
  • Otras tres o cinco líneas de asteriscos
  • Un gran bloque de espacio en blanco delimitado por asteriscos, u otro carácter, donde aparece el nombre de cada función o subrutina, el nombre o iniciales del autor, y la fecha de escritura original
  • El código

Los módulos normalmente se mantienen de un tamaño razonable para reducir dependencias y mejorar la resistencia del módulo. Si un módulo alcanza un tamaño excesivo se divide en partes más pequeñas, copiando la nota de copyright, descargos legales, etc... del original. Es seguro heredar comentarios de un módulo a otro, así que lo más seguro es copiar todos los comentarios del original.

Componentes y bibliotecas

La programación de orientación abyecta se presta a usar componentes conectables (plug-in) (fragmentos de código encontrados en libros o en la red). Usando un buscador, un programador inteligente puede ahorrar tiempo al encontrar componentes prefabricados capaces de hacer casi cualquier cosa. Los mejores componentes son las cajas negras: el programador ni sabe ni le importa como funciona el componente. Muchas aplicaciones grandes están construidas con una combinación de herencia de otros componentes y aplicaciones encontrados en la red.

Encapsulación

La idea tras la encapsulación es mantener los datos separados del código. Esto se llama ocultación de datos en algunas ocasiones, pero los datos no están realmente ocultos, sólo protegidos dentro de otra capa de código. Por ejemplo, no es una práctica recomendable esparcir consultas a la base de datos por todas partes. Una práctica abyecta sería envolver u ocultar todas las funciones relativas a la base de datos en funciones o subrutinas, encapsulando así la base de datos. En la función getNombreClnt de antes, no se consulta la base de datos directamente -- se llama a una función para leer el registro de la base de datos. Lo único que getNombreClnt y getEmailClnt (y otras muchas funciones parecidas) "saben" es donde encontrar los pocos datos que necesitan en el registro del cliente. La forma de leer el registro del cliente está encapsulado en algún otro módulo.

Algunos lenguajes de programación hacen que el programador declare las variables como protegidas, públicas o privadas. Pero esta no es una práctica abyecta. No hay forma de que el autor de un módulo sepa que variables internas del módulo van a hacer falta para implementar nuevas características en el futuro. Los programadores deben hacer todas las variables públicas (o globales), y deben dejar que el resto del código decida qué debe y qué no debe ser privado.

Polimorfismo

Al aprender técnicas de orientación abyecta, los programadores frecuentemente se atascan en el polimorfismo. Suena complicado pero la idea es sencilla y fácil de implementar. El código es polimórfico cuando produce distintos resultados para distintos tipos de datos de entrada.

Para poner un ejemplo, las funciones de arriba se pueden reescribir como una única función polimórfica heredando el código que ya funciona y encapsulándolo en una nueva función:

function getDatosClnt(Idclnt, que)
{
    if (que == 'nombre') {
        regClnt = readFromDB("cliente", Idclnt);
        nombrecompleto = regClnt[1] + ' ' + regClnt[2];
        return nombrecompleto;

    } else if (que == 'email') {
        regClnt = readFromDB("cliente", Idclnt);
        nombrecompleto = regClnt[1] + ' ' + regClnt[2];
        /***************
        * 4/15/96 git : dirección email está en
        * el segundo campo del fax
        ***************/
        return regClnt[17];
    }

    /* ... etc. */
}

El polimorfismo está relacionado con la idea de no-determinismo y las máquinas de estados finitos de Turing, que deberías recordar de tus clases de Informática.

Ser frente a Tener

Esta es una sutileza de buen diseño de orientación abyecta. Al principio de aprender los principios abyectos, los programadores tienden a hacerlo todo con herencia (modelo ser). Con más experiencia los programadores se dan cuenta que la relación tener es a menudo más apropiada. En el código de ejemplo de arriba, cada cliente tiene un mombre, pero regClnt es un registro de la base de datos.

Clases virtuales y funciones

Una función o clase virtual es código que la aplicación necesitará tarde o temprano, pero que no está escrito todavía. Esto se consigue normalmente mediante una clase base en la que se basará el código final:

function calcImpuestoVentas(precio, esDevengable, provincia)
{
    /****************************************
    *
    * TO DO:
    *
    * obtener porcentaje de impuestos de la
    * provincia del cliente
    * en algun momento de alguna tabla
    *
    ****************************************/

    /** 02/07/99 git -- usamos impuestos de M de momento **/
    return precio * (7.25 / 100.0);
}

Una clase base frágil es un módulo o clase que lleva en la aplicación mucho tiempo y hace que la aplicación falle cada vez que se modifica de cualquier manera.

Sobrecarga

La sobrecarga es cuando un módulo o pedazo de código hace más de una cosa. Un ejemplo sería una subrutina que devuelve el nombre del cliente, la dirección postal, la dirección electrónica y la tasas de impuesto estatal. Usar funciones sobrecargadas reduce el method dispatching (reparto de métodos), que es una de las razones por las que otros estilos de programación pueden resultar en código lento.

Documentación

Se dice que el código debe escribirse para que sea leído por gente, por lo tanto se deduce que la documentación se escribe para que nadie la lea. La documentación debe escribirse en cada módulo nuevo y mantenerse conforme los cambios se entreguen a producción o, al menos, la próxima vez que haya un hueco en el trabajo.

Un buen momento para escribir documentación es cuando alguien del departamento entrega el pre-aviso de dos semanas: aprovecha ese tiempo para asegurarte que el miembro del equipo que se marcha documenta todo su código.

Ensuciar el código con montones de comentarios explicando qué es lo que intenta hacer el código distrae y ralentiza al compilador. Por eso cualquier empresa que siga las "practicas recomendadas" mantiene la documentación en un sistema de gestión de documentación donde los programadores no pueden borrar nada accidentalmente.

Control de versiones

No es realmente una práctica de programación per se, pero las empresas abyectas suelen seguir prácticas similares de control de versiones. Mantener cerca versiones previas del código, y llevar un seguimiento de los cambios en el código es importante incluso si sólo hay un programador trabajando en la aplicación. Los programadores abyectos experimentados siguen un sistema como el siguiente:

  • Añade siempre tus iniciales y la fecha de la última revisión en la cabecera del fichero de código.
  • Cuando edites un fichero y te des cuenta que tus cambios son lo bastante grandes como para que revertirlos sea complicado, guarda una copia con extensión .bak.
  • Mantén múltiples copias de respaldo cerca añadiendo tu nombre o iniciales y la fecha en el nombre de archivo de copia de seguridad: datoclnt_git20040321.bak.
  • Guarda siempre copias de respaldo en el mismo directorio o carpeta que el código original, así se facilita ver la historia del archivo.

Conclusión

Probablemente encuentres que en las empresas con más solera ya se siguen algunas o todas estas prácticas abyectas. Modas como métodos ágiles o programación "extrema" vienen y van, pero el estilo abyecto ha existido desde el principio de los tiempos. Los encargados están familiarizados con las prácticas abyectas y esperan que seas capaz de trabajar con su código base de orientación abyecta.

3 comentarios:

  1. Si sólo fuera esto todo lo bajo, miserable y despreciable que tienes que tragar en según qué sitios...

    ResponderEliminar
  2. jejejejejeje xDDD

    Definitivamente esta es la forma de trabajar más extendida en España (y supongo q en todo el muunddo)

    La programación Abyecta!!! Yeah! me encanta :) por fín sé como se llama la metodología q usan

    ResponderEliminar
  3. Me ha sonado todo a "chino" pero,no por tú culpa, simplemente por mi "incultura".
    Besitos
    P.D. El último dibujito es el de la grapadora a ver si renovamos la "pinacoteca" ;)

    ResponderEliminar

Nota: solo los miembros de este blog pueden publicar comentarios.