Como desarrollador seguramente utilizas o has oído hablar de los principios SOLID. Este acrónimo, introducido por Robert C. Martin (Uncle Bob), en su libro Agile Software Development: Principles, Patterns, and Practices, hace referencia a cinco principios básicos de la programación orientada a objetos, que están relacionados con los Patrones de diseño.

Si aplicamos estos cinco principios:

  • Tendremos un código flexible, que podremos cambiar fácilmente y que sera tanto reusable como mantenible.
  • El software desarrollado será robusto, estable y escalable (podremos añadir nuevas funcionalidades fácilmente).
  • Junto con el uso de los Patrones de diseño, nos permitirá crear un software que sea altamente cohesionado (es decir, los elementos del sistema están muy relacionados) y poco acoplado (el grado de dependencia entre elementos es bajo).

Origen del acrónimo SOLID

El acrónimo SOLID proviene de:

  • S (SRP): Single responsibility principle o Principio de responsabilidad única
  • O (OCP): Open/closed principle o Principio de abierto/cerrado
  • L (LSP): Liskov substitution principle o Principio de sustitución de Liskov
  • I (ISP): Interface segregation principle o Principio de segregación de la interfaz
  • D (DIP): Dependency inversion principle o Principio de inversión de la dependencia

Vamos a ver qué nos indican estos principios y cómo aplicarlos en el desarrollo con Swift.

Single responsibility principle o Principio de responsabilidad única

Según este principio, una clase debería tener una razón, y solo una, para cambiar. Es decir, una clase solo debe tener una responsabilidad. Veamos un ejemplo:

Tal como se observa, esta clase presenta tres responsabilidades: Authentification, Decode info and Save info. Para cumplir el principio de responsabilidad única extraemos cada una de estas responsabilidades en otras clases más pequeñas.

Open/closed principle o Principio de abierto/cerrado

Según este principio, debemos poder extender una clase sin que cambie su comportamiento. Esto se consigue mediante abstracción.

Para cada tipo nuevo de vehículo hay que implementar de nuevo la función getScrapingAddress(), lo que rompe el principio de abierto/cerrado. Para resolver este punto, introducimos el protocolo Scrappable que contiene el método getScrappingAddress():

Liskov substitution principle o Principio de sustitución de Liskov

Este principio, introducido por Barbara Liskov en 1987, establece que en un programa cualquier clase debería poder ser reemplazado por una de sus subclases sin que se vea afectado su funcionamiento.

Por ejemplo, supongamos que tenemos una clase, UserService, que tiene la responsabilidad de contactar con los usuarios (por ejemplo, enviar un mail). Si cambia la lógica de negocio y, por ejemplo, solo se pueden enviar mails a usuarios de más de 17 años, podemos crear una subclase que añada la nueva lógica de negocio:

En este caso no se cumple el Principio de sustitución de Liskov, ya que la subclase añade una condición (que la edad del usuario sea mayor de 17 años), que no esperaría un cliente de la clase UserService. Podemos solucionar este problema no creando la subclase, y añadiendo a UserService la precondición (incluyendo un valor por defecto):

Interface segregation principle o Principio de segregación de la interfaz

El Principio de segregación de la interfaz indica que es mejor tener diferentes interfaces (protocolos) que sean específicos para cada cliente, que tener un interfaz general. Además, indica que un cliente no tendría que implementar métodos que no utilice.

Por ejemplo, podemos crear una interfaz para animales que incluya métodos de desplazamiento:

Sin embargo, aunque Wale adopta el protocolo, hay dos métodos que no implementa. La solución es establecer tres interfaces (protocolos), una por método:

Dependency inversion principle o Principio de inversión de la dependencia

Según el Principio de inversión de la dependencia:

  • Las clases de alto nivel no deberían depender de la clases de bajo nivel. Ambas deberían depender de abstracciones.
  • Las abstracciones no deberían depender de los detalles. Los detalles deberían depender de las abstracciones.

Lo que se busca es reducir las dependencias entre módulos, y así alcanzar un menor acoplamiento entre clases.

Observemos el siguiente ejemplo:

¿Qué ocurre si en vez de utilizar CoreData para guardar los datos, queremos utilizar la base de datos Realm? El hecho de instanciar la clase como hemos hecho en el ejemplo genera un fuerte acoplamiento, por lo que si queremos utilizar otra base de datos, habría que rehacer el código.

Para solucionar esto, podemos hacer lo que se explicó en un artículo anterior, cuando se estableció una capa de base de datos.

Ahora hacemos que User adopte el protocolo Storable y que la clase UserService adopte el protocolo StorageManager, de forma que aunque cambiemos la base de datos, no necesitaremos cambiar todo el código de implementación:

Conclusion

Estos principios nos permitirán reducir la rigidez y fragilidad del código, al permitir crear componentes reusables, de fácil mantenimiento y con una mayor calidad en su código.


3 comentarios

Raúl Ferrer · 16 febrero 2020 a las 17:25

Thanks.

Mejora tu código Swift con funciones de orden superior - Thinking In Swift · 9 junio 2020 a las 10:12

[…] visto cóm omejorar la arquiectura de nuestro código mediante patrones de diseño y el uso de los principios SOLID. Ahora veremos cómo mejorar el código Swift con funciones de orden superior. Seguramente más de […]

Inyección de dependecias en Swift - Thinking In Swift · 1 noviembre 2020 a las 16:06

[…] un artículo anterior ya hablé sobre los principios SOLID y cómo aplicarlos con Swift. En este artículo voy a tratar sobre un patrón que nos permitirá […]

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Sígueme en Feedly