Crónicas del Buen Programador: Software Ortogonal

La ortogonalidad es un concepto crítico a la hora de crear sistemas fáciles de diseñar, probar, compilar y extender. Sin embargo no es una característica que se enseñe de forma explícita y termina siendo una consecuencia de otras escuelas de diseño de software. Esto es un error, una vez que aprendes a aplicar el principio de ortogonalidad en tus sistemas de forma directa notarás una mejora inmediata en la calidad de los sistemas que produces.

¿Qué es Ortogonalidad?

El término “Ortogonalidad” es prestado de la geometría, cuando dos líneas se encuentran en un ángulo recto, ortogonalidad = perpendicularidad, ambas líneas son independientes. Muévete en cualquiera de los ejes y tu proyección en el otro eje no cambia.

En computación el término ha venido significando un tipo de independencia o disociación. Dos o más cosas son ortogonales si cambios en una no afectan a ninguna de las otras. En un sistema bien diseñado, el código de la base de datos será ortogonal a la interfaz de usuario, puedes cambiar la interfaz sin afectar la base de datos, y cambiar bases de datos sin cambiar la interfaz.

Beneficios de la Ortogonalidad

Los sistemas no ortogonales son inherentemente difíciles de cambiar y de controlar. Cuando los componentes de cualquier sistema son altamente interdependientes, no hay tal cosa como un pequeño cambio local.

Elimina Efectos entre cosas no relacionadas

Queremos diseñar componentes que son auto-contenidos, independientes y con un propósito bien definido (lo que se conoce en otras escuelas como cohesión). Cuando estos componentes son aislados unos del resto, sabes que puedes cambiar uno sin tener que preocuparte de los otros. Siempre y cuando no cambies las interfaces externas para utilizar estos componentes, puedes estar cómodo de que no causarás problemas que dañen el resto del sistema.

Los dos beneficios más importantes que obtienes de escribir sistemas ortogonales son: Mayor Productividad y Disminución de Riesgo.

Mayor Productividad

Los cambios son localizados, el tiempo de desarrollo y pruebas se reducen. Es más fácil escribir código relativamente corto, componentes auto-contenidos, que un bloque grande de código. Componentes simples pueden ser diseñados, codificados, probados y olvidados una vez que funcionan. No hay necesidad de mantener código existente a medida que vas agregando código nuevo.

Esto promueve el reuso (recuerda el principio DRY). Si los componentes tienen propósitos específicos con responsabilidades bien definidas, estos componentes pueden ser combinados con nuevos componentes en formas que en principio no fueron imaginados por el programador original. Mientras más disasociado tu sistema, más fácil de reconfigurar, extender o rediseñar será.

Si un componente hace M cosas, y otro hace N cosas, cuando los combinas puedes producir M x N cosas. Si estos componentes tienen funcionalidades que se solapan, su combinación va a resultar en un número menor de cosas. La combinación de componentes ortogonales resulta en más funcionalidad por unidad de esfuerzo.

Disminución de Riesgo

Si hay porciones de código que ya no nos sirven, si un módulo está enfermo, es más fácil de aislarlo y de evitar causar daños al resto del sistema. También es más fácil hacer un transplante de ese componente por un nuevo componente similar, pero nuevo y saludable.

Los sistemas se hacen menos frágiles, si haces cambios en una parte de un sistema ortogonal cualquier posible problema que puedas introducir se verá restringido a sólo esa área.

No atas tu sistema a un “vendor” particular, a un producto o plataforma dado que las interfaces que interactían con estos sistemas o componentes de terceros pueden ser aisladas y remplazadas por otras opciones.

Lógicamente es más fácil de probar cuando las piezas no dependen del todo, un sistema probado es mucho más robusto y confiable.

Mejor para desarrollo en Equipos

Algunos equipos de desarrollo son eficientes, cada quien trabaja y contribuye al máximo, mientras que otros equipos están constantemente pisándose los pies, o uno de los miembros tiene demasiado poder sobre el proyecto, lo adivinaste, ortogonalidad vs falta de ortogonalidad.

Es más fácil organizar equipos de desarrollo en grupos con responsabilidades bien definidas y con mínimo solapamiento si los componentes del sistema han sido pensados con ortogonalidad en mente.

Código Ortogonal

Cada vez que escribes código corres el riesgo de reducir la ortogonalidad de la aplicación. A menos que constantemente monitorees no sólo lo que estás haciendo sino el contexto más ámplio de toda la aplicación, es posible que de forma no intencional dupliques funcionalidad que exista en otro módulo, o expreses conocimiento del sistema más de una vez.

Algunas técnicas se recomientan para mantener ortogonalidad:

Escribe código Tímido: Módulos que no revelen nada innecesario a otros módulos y que no dependan de las implementaciones de otros módulos. Si necesitas cambiar el estado de un objeto, deja que ese objeto cambie su estado por ti. De este modo tu código se mantiene aislado de la implementación del otro código y tus chances de permanecer ortogonal aumentan.

Evita Datos Globales: Cada vez que tu código hace referencia a data global, se ata inmediatamente a otros componentes que comparten esa data. Inclusive data global que sólo piensas leer puede llevarte a problemas (algunas veces cambiar tu código para que sea multihilos puede causar problemas si utilizas variables globales). En General, tu código es más fácil de entender y de mantener si se le pasa de forma explícita cualquier contexto requerido para que el módulo funcione. En aplicaciones orientadas a objetos el contexto se pasa generalmente como parámetros del constructor del objeto.

Evita funciones similares: A veces te encuentras con un grupo de funciones que lucen muy similares, quizás estas comparten código común al inicio y al final y algo fundamental cambia en el medio. Código duplicado en este estilo es un síntoma de problemas estructurales. En estos casos hay varios patrones de diseño que pueden ayudarte para tener una sola implementación cuyo medio puede ser dinámico. Puedes utilizar herencia, clases abstractas, o pasar como parámetro un objeto que implemente una interfaz la cual invocas en ese “medio” que cambia.

La próxima vez que veas un equipo sufriendo para hacer cambios, puedes con toda certeza afirmar que el problema es falta de ortogonalidad.

[ad#Google Adsense-468x15ContentLinkunit]

Sobre el Autor

Angel León (aka Gubatron) es un Ingeniero de Software Venezolano (UCAB) que ha desarrollado desde sencillos sistemas con bases de datos relacionales, servicios webs distribuidos para millones de visitantes mensuales, software p2p de uso masivo, hasta aplicaciones para dispositivos mobiles, todo esto empleando gran variedad tecnologías abiertas (Linux, Android, Java, Python, PHP, C++, Javascript).

Estas crónicas son inspiradas en el libro “The Pragmatic Programmer” (un libro que debería ser un texto obligatorio en todo curso de Ingeniería de Software) junto con las experiencias de Angel León durante los últimos 8 años desarrollando software en Venezuela y los Estados Unidos.

[ad#Gubatron-AmazonAd-PPBook-120×240]
  • Ricardo

    muchas gracias por las crónicas del buen programador… no lo pude encontrar en la web, así que me estoy leyendo los conceptos fundamentales desde acá