Principio de responsabilidad única (I)

Comenzamos con el Principio de Responsabilidad Única, una de las bases fundamentales sobre la programación oriendada a objetos.
Fue en los preparativos del Code Camp de Tarragona ‘2009 cuando surgió la idea de escribir esta serie de artículos para describir cinco principios fundamentales de la POO cuyas iniciales conforman las siglas SOLID. La comprensión de dichos principios nos permitirá mejorar la percepción del no siempre fácil campo de la POO, evitando así malas prácticas que la gran flexibilidad que ofrece esta metodología otorga, fundamentalmente a través de los lenguajes y herramientas que la soportan.

Las herramientas de desarrollo rápido (Rapid Application Development, RAD), como Visual Studio 2010, ofrecen al desarrollador un conjunto de funcionalidades que aumentan, ya sea a través de asistentes o mediante "arrastrar y soltar", la productividad en el desarrollo de aplicaciones, y le permiten focalizarse únicamente en la utilización de propiedades o eventos específicos, sin tener que preocuparse en muchas ocasiones del código generado "por debajo". Sin embargo, en ocasiones acabamos pagando un precio muy elevado, ya que estas herramientas dejan tras de sí "cajas negras lógicas" de código difíciles de modificar o reutilizar, en las que los conceptos clave de la orientación a objetos son sacrificados en aras de la productividad; pero hablar de productividad es hablar de facilidad de mantenimiento y calidad del software, con lo que dicho sacrificio, sencillamente, no tiene o debería tener cabida.

Cohesión

Para tratar de comprender el término "nivel de cohesión", vamos a utilizar como ejemplo el teléfono móvil. Como todos sabéis, un dispositivo móvil está compuesto por una serie de componentes, tales como la pantalla, el teclado, la radio GPRS/3G, el módulo Bluetooth, etc. Todos estos componentes tienen una responsabilidad específica, ya sean los módulos de entrada y salida de datos o los módulos de conectividad y comunicación, etcétera, y por tanto existe una cohesión entre todos los componentes, ya que no hay ningún componente que haga funciones que se solapen con las de otros componentes, ni ninguna función básica que no quede descubierta por un determinado componente. A la hora de buscar un nuevo móvil, miraremos las características y especificaciones técnicas del dispositivo, y además de contemplar las especificaciones que deseamos, también esperaremos que los componentes sean de alta calidad; no es viable que un móvil esté compuesto por los últimos componentes electrónicos del mercado y se venda con una pantalla no táctil en "blanco y negro" de 3 pulgadas, o que, por ejemplo, no tenga algo tan básico como un micrófono.

En un sistema informático también tenemos componentes (además de módulos, clases, etc.), y todos estos componentes lógicos tienen su responsabilidad dentro del sistema. Pensemos pues en el nivel de cohesión de una aplicación no como en una suma de los componentes, sino como el conjunto de los mismos.

Acoplamiento

Siguiendo con el ejemplo del teléfono móvil, un ejemplo de acoplamiento lo encontramos en los cargadores de nuestros móviles. Son cada vez más los fabricantes que optan por adaptadores de corriente estándar en lugar de crear adaptadores propietarios que casi siempre acaban tirados en el contenedor de reciclaje cuando sustituimos el móvil. Se entiende que se opta por la universalidad de los dispositivos de corriente para su reaprovechamiento en otros dispositivos, incluso de diferentes fabricantes. En la ingeniería del software, el acoplamiento entre módulos, clases o cualquier otro tipo de entidad lógica es el grado de dependencia entre ellos. Cuanto más estándar sea la relación de una entidad lógica con otras, mayor reaprovechamiento podremos hacer de ella.

Encapsulación

Seguramente se habrá dado cuenta de que la parte interna de un móvil no es fácilmente accesible; es decir, no tenemos acceso a la electrónica interna. La idea de la encapsulación es la de abstraer determinadas funciones para que, además de ser reutilizables, no requieran que los usuarios tengan los conocimientos del diseñador. La complejidad de un dispositivo móvil o de cualquier otro dispositivo electrónico es muy elevada, y la gran mayoría de usuarios son capaces de sacarle el máximo provecho sin tener nociones específicas sobre su arquitectura interna. La radio Bluetooth o el módem GPRS/3G son los mismos para varios modelos, incluso de diferentes fabricantes. Esta es precisamente la idea de la encapsulación de funciones o características, que lo único que requiere es que el usuario sepa qué se puede hacer con esa función y no cómo está diseñada.

Aplicaciones SOLIDas

Siguiendo el modelo del teléfono móvil y la idea subyacente de estos tres aspectos, podríamos afirmar que el teléfono ideal sería aquel que estuviera compuesto por los mejores componentes del mercado, cuyas interfaces de conexión para la sincronización de datos y recarga de la batería fueran estándares, y cuyas funcionalidades pudiéramos conocer en profundidad sin necesidad de tener que consultar detalles en la documentación técnica para saber cómo han sido diseñadas y así poder sacarles el máximo provecho.

Extrapolando este ejemplo a nuestro mundo, el mundo del software, tenemos que tener siempre presentes estos tres aspectos fundamentales desde el momento mismo en que empezamos el diseño de una nueva aplicación. Es ahí donde entran en escena los cinco principios descritos por el acrónimo mnemotécnico SOLID y presentados a principio de esta década por Robert C. Martin (figura 1).

Los principios SOLID pretenden ser una guía a seguir durante la fase de desarrollo para facilitar el mantenimiento de las aplicaciones y tratar de eliminar el impacto de las inevitables modificaciones que éstas sufren durante su ciclo de vida, además de facilitar el uso de las unidades de testeo, entre otras ventajas.

Nota: Los principios SOLID pretenden ser una guía a seguir durante la fase de desarrollo para facilitar el mantenimiento de las aplicaciones

Principio de responsabilidad única

El Principio de responsabilidad única (Single Responsability Principle - SRP) fue acuñado por Robert C. Martin en un artículo del mismo título y popularizado a través de su conocido libro [1]. SRP tiene que ver con el nivel de acoplamiento entre módulos dentro de la ingeniería del software. En términos prácticos, este principio establece que:
Una clase debe tener una y solo una única causa por la cual puede ser modificada.

Si una clase tiene dos responsabilidades, entonces asume dos motivos por los cuales puede ser modificada. Por ejemplo, supongamos una clase llamada Factura, la cual dentro de un contexto determinado ofrece un método para calcular el importe total, tal y como muestra la figura 2.