La reutilización es la panacea inalcanzable del desarrollo de software. Hace mucho tiempo que componer sistemas a partir de elementos reutilizables es nuestro talón de Aquiles. Realmente queremos la reutilización, y sin embargo nuestros fracasos son espectaculares. Casi todas las tendencias tecnológicas de los últimos 20 años mostraron a la reutilización como la solución salvadora. Los proveedores vendieron millones de dólares en software con la promesa nunca cumplida de mayor reutilización.
¿Qué pasó? Se suponía que la reutilización ahorraría desarrollo de software. A principios de los 90, la orientación a objetos prometió salvarnos. No lo hizo, seguimos avanzando. A fines de los 90, el desarrollo orientado a componentes prometió salvarnos. No lo hizo, seguimos avanzando. Poco después en el nuevo milenio SOA prometió salvarnos. No lo hizo, y seguimos avanzando... ¿Por qué es tan dificil la reutilización?
El problema proviene del siguiente hecho, que también podemos visualizar en un diagrama:
Maximizar la reutilización complica la utilización
(la frase es un derivado de la oración original de Clemens Szyperski en su libro Component Software: Beyond Object-Oriented Programming - “Maximiar la reutilización minimiza la utilización")
En general, mientras más reutilizable es un componente de software, más dificil es de utilizar. En el extremo, un componente infinitamente reutilizable es infinitamente dificil de usar. Es dificil manejar este balance entre reutilización y utilización, y a menudo fallamos. En gran medida, el problema tiene que ver con las dependencias.
Los detalles de la reutilización
Reconozco que hicimos un bastante buen trabajo para lograr la reutilización en ciertos niveles, y estamos mucho más lejos de la curva que hace 20 años. Hoy, tenemos mucha variedad de frameworks para elegir que nos ayudan a desarrollar. Frameworks Web, frameworks de ORM, y frameworks de seguridad, por mencionar unos pocos. Pero la mayoría de estos frameworks son horizontales, no verticales. Solucionan los problemas relacionados a la infraestructura y coordinación del código, y no a problemas de negocio. Quiero enfocarme principalmente en la reutilización vertical, porque aquí es donde está la panaca inalcanzable por la que estamos luchando desde hace tanto tiempo. Aquí está la promesa incumplida. ¿Por qué luchamos para crear componente de negocio reutilizables?
Granularidad
La granularidad es el grado que un sistema se descompone en partes. Los componentes de grano grueso tienden a tener comportamiento más rico que los componentes de grano fino. Porque los componentes de grano grueso hacen más cosas, tienden a ser más grandes que los componentes de grano fino. Para maximizar la reutilización, intentamos componer componentes de grano grueso a partir de componentes de grano fino. Por supuesto, esto resulta en muchas dependencias entre los componentes, lo que hace que sean más dificil de usar. En general, podemos decir:
Los componentes de grano grueso son más fáciles de usar, y los componentes de grano fino son más reutilizables
Vamos a un ejemplo. Supongamos que estamos creando un componente que procesa reclamos de un seguro de vida. Vamos a usar un proceso de negocio relativamente simple. Hay 4 pasos en el proceso. Primero, se ingresa al sistema la información del pedido. Segundo, el sistema comprueba que no sea un envio duplicado. Tercero, el sistema verifica los precios en base a los acuerdos correspondientes. Cuarto, el sistema emite el pago. Un componente de grano grueso se encargaría de hacer estos cuatro pasos.
Al hacerlo así, el componente es facil de utilizar ya que sólo hay que invocar a una única operación para completar todo el proceso. Pero también es más dificil de reutilizar sólo una porción del proceso, como ser la emisión del pago. La solución lógica es crear cuatro componentes de grano fino (uno para cada paso del proceso) y un componente de grano grueso compuesto por los otros cuatro componentes. Los componentes de grano fino hacen que sea más reutilizable, pero también más dificil de usar ya que debemos utilizarlos y coordinarlos para lograr una unidad de trabajo.
Peso
El peso es el grado que un componente depende de su entorno. Un componente pesado depende de su entorno operativo, mientras que un componente liviano evita las dependencias. Cuando creamos un componente que se ejecuta en múltiples entornos, nos vemos forzados a mover dependencias específicas del entorno (por ejemplos, dependencias del contexto) del código a la configuración. Esto hace que el componente sea más reutilizable, pero también más dificil de usar ya que el componente tiene que configurarse para cada entorno.
Es más dificil diseñar y configurar un componente liviano que simplemente crear un componente programador para operar específicamente en un entorno. En general, podemos decir:
Los componentes livianos son más reutilizables, y los componentes pesados son más fáciles de usar
Sigamos con el ejemplo anterior, en donde la solución era crear un componente de grano grueso compuesto de cuatro componentes de grano fino. Si cada uno de estos componentes sólo necesita ejecutarse dentro de una única aplicación en un único entorno operativo, podemos encapsular todo este código del entorno en cada componente, haciendolos más pesados. Pero si queremos reutilizar estos componentes en múltiples aplicaciones y múltiples entornos operativos, vamos a tener que mover este código afuera del componente y asegurarnos que podamos configurarlo para cada entorno en donde funcionará.
Reutilizar o Utilizar
El desafio que enfrentamos al crear un componente altamente reutilizable es encontrar el balance entre reutilización y usabilidad. Los componentes de grano fino tienen más dependencias con componentes, y los componentes livianos tiene más dependencias con el contexto. Cada aspecto hace que un componente sea más reutilizable, pero también más dificil de usar. La clave es hallar el balance... y eso no es para nada facil.
Traducido de Reuse: Is the dream dead? por Kirk Knoernschild.