27/10/2020 | Consejos tecnológicos,Desarrollo de aplicaciones,Desarrollo de software,Tecnologías

¿Cuáles son los principios S.O.L.I.D. ? "Single Responsability"

S.O.L.I.D. es el acrónimo de los cinco principios básicos de la programación orientada a objetos. Los principios S.O.L.I.D. fueron definidos por Robert C. Martin en su publicación “Design Principles and Design Patterns”.

Lo veremos todos en detalle a continuaciónpero antes es fundamental una breve introducción.

Aunque no lo parezca, los primeros ordenadores digitales llevan con nosotros menos de un siglo, y de hecho el término como tal de «Ingeniería del Software» aparece por primera vez a mediados del siglo XX. En contraste, términos como «arquitectura» datan desde el siglo I a.C., por lo que podemos decir que la Ingeniería de Software sigue siendo un campo muy joven. Seguimos aprendiendo día a día de los errores propios (y de los demás), tratando de evolucionar y de evitar repetirlos para ser más productivos y eficientes. Así poco a poco vamos definiendo los principios y buenas prácticas para el desarrollo de software.

Dentro de esos principios, unos de los más conocidos fueron justamente los cinco princicpios S.O.L.I.D. definidos por Robert C. Martin. El conocer y aplicar estos principios ofrecen una serie de ventajas al desarrollador a la hora de programar, independientemente del lenguaje utilizado. El código resultante estará menos acoplado por lo que será más fácil de extender, de mantener, más legible, reutilizable y más sencillo realizar test unitarios. En conclusión tendremos un mejor diseño en la arquitectura de la aplicación y un código de mayor calidad.

¿Qué significa el acrónimo S.O.L.I.D.?

Single responsibility principle – Principio de responsabilidad única

Open-closed principle – Principio de abierto-cerrado

Liskov substitution principle – Principio de sustitución de Liskov

Interface segregation principle – Principio de segregación de interfaces

Dependency inversion principle – Principio de inversión de dependencias

Single responsibility principle – Principio de responsabilidad única

Hoy nos centraremos en el primer principio SOLID, el principio de responsabilidad única.

Este principio establece que cada clase debe tener una única responsabilidad dentro de nuestro software, y esta responsabilidad debe estar definida y ser concreta. Todos los métodos deben estar alineados con la finalidad de la clase.

“Una clase debe tener solo una razón para cambiar” – Uncle Bob

Si nos encontramos con una clase que dispone de métodos que realiza tareas con distintas finalidades se debería refactorizar el código y crear clases nuevas que se corresponda con los objetivos del método.

Definir la responsabilidad única de una clase no es una tarea fácil, será necesario un análisis previo de las funcionalidades y cómo estructuramos la aplicación. Gracias a este principio nuestras clases tendrán un bajo acoplamiento y a la hora de realizar cambios menos clases se verán afectadas.
Algunos síntomas que nos pueden hacer sospechar (bad smells) que no se está cumpliendo este principio serían:

  • Una clase es demasiado larga, demasiadas líneas de código.
  • Cada vez que hay que introducir una modificación o una nueva funcionalidad, es necesario tocar en muchos sitios.
  • Hay demasiadas relaciones entre clases.
  • Mezcla funcionalidades de distintas capas de la arquitectura.

Un ejemplo real en Java de como aplicar el principio de responsabilidad única

Tenemos una aplicación cuya función es calcular la suma del área de dos polígonos y mostrar el resultado al usuario. En un principio podríamos tener clases para definir los objetos Square y Circle que extienden de la clase padre Polygon.

public class Square extends Polygon {

    int side;

    public Square(int side){
        this.side = side;
    }

    public int getSide(){
        return this.side;
    }

    public void setSide(int side){
        this.side = side;
    }

    public double getArea(){
        return Math.pow(side,2);
    }

}

public class Circle extends Polygon {

    int radius;

    public Circle(int radius){
        this.radius = radius;
    }

    public int getRadius(){
        return this.radius;
    }

    public void setRadius(int radius){
        this.radius = radius;
    }

    public double getArea(){
        return Math.PI * Math.pow(radius,2);
    }

}


También crearemos una clase que realice los cálculos que necesitamos.

public class CalculationService {

    public void sumAreas(Polygon poligon1, Polygon poligon2){
        System.out.print(poligon1.getArea() + poligon2.getArea());
    }

    public void diffAreas(Polygon poligon1, Polygon poligon2){
        System.out.print(poligon1.getArea() - poligon2.getArea());
    }
}

En la aplicación principal creamos los objetos y llamamos al método de sumar las áreas:

  Circle circle = new Circle(5);
  Square square = new Square(6);

  CalculationService calculationService = new CalculationService();
  calculationService.sumAreas(circle, square);

Podríamos pensar que está bien crear el método de mostrar el resultado por pantalla dentro de la misma clase que realiza los cálculos, pero estaremos violando el principio de responsabilidad única, ya que no deberíamos mezclar la capa de presentación con la lógica de negocio, y posiblemente en un futuro si queremos actualizar la forma en que se muestra al usuario el resultado o queremos realizar nuevos cálculos vamos a tener que modificar todos nuestros métodos de la clase CalculationService.
Aplicando el principio de responsabilidad única para refactorizar el código crearíamos una nueva clase PrintService en la que implementaremos las funciones encargadas de la presentación de nuestra aplicación:

public class PrintService {

    public void printResult(double result){
        System.out.print("-- Result = " + result);
    }

}

La clase CalculationService solo quedaría como responsable de realizar los cálculos:

public class CalculationService {

    public double sumAreas(Polygon poligon1, Polygon poligon2){
        return poligon1.getArea() + poligon2.getArea();
    }

    public double diffAreas(Polygon poligon1, Polygon poligon2){
        return poligon1.getArea() - poligon2.getArea();
    }

}

En la aplicación principal estaríamos utilizando los dos servicios, con la posibilidad de reutilizar el resultado para otros cálculos o de crear nuevos métodos en el PrintService para mostrar el resultado en distintos formatos.

   CalculationService calculationService = new CalculationService();
   PrintService printService = new PrintService();

   Circle circle = new Circle(5);
   Square square = new Square(6);

   double result = calculationService.sumAreas(circle, square);
   printService.printResult(result);

Esperamos que estos ejemplos os hayan ayudado a entender el primer principio de SOLID y ver su gran importancia en el proceso de desarrollo de software.

Esto ha sido todo con lo que respecta a la «S» de S.O.L.I.D. pero, si quieres saber más sobre el resto de principios, consulta nuestros artículos:


Compartir en:

Relacionados