¿Qué son los principios SOLID en programación?
Los Principios Solid son una serie de normas o recomendaciones que guían la forma de programar y que tienen como objetivo intentar que el código desarrollado sea más mantenible, sea un código en el que se puedan aplicar cambios y arreglar errores de una forma sencilla, facilitando la incorporación de nuevas funcionalidades, en definitiva, hacer el código más legible y fácil de entender.
Aprender a programar es fácil: variables, tipos de datos, condicionales, ciclos, operadores, son los conceptos y las bases mínimas de un programador. Sin embargo, ya os hemos mencionado en varios artículos lo importante que es escribir código limpio con buenas prácticas, mantenible y escalable.
Es por esta razón que las buenas prácticas son una de las principales diferencias entre una persona con algo de experiencia programando (lo que conocemos como un junior) y una persona que ya tiene amplia experiencia (senior) en el desarrollo de software. Podríamos decir que el junior busca que el código funcione y el senior busca que también sea mantenible en el futuro.
Entre los recursos más importantes que existen para escribir código limpio están los Principios Solid. Para entender estos principios, necesitamos de una buena base referente a los conceptos de la Programación Orientada a Objetos (POO). Este es el paradigma más utilizado y empezó en los años 70 y se extendió a casi todos los lenguajes.
La POO utiliza objetos que se comunican entre ellos para representar las entidades del programa. Los objetos tienen atributos que también son llamados propiedades que son sus características y métodos que son sus funciones. Por ejemplo, un usuario de TechGenius tiene como atributo su nombre y su correo y como método, Iniciar Sesión en nuestra plataforma formativa e inscribirse en uno de nuestros cursos.
Otro concepto muy importante en la POO son las clases. Los objetos se crean a partir de plantillas llamadas clases, que vendrían a ser como el “plano de una casa” a partir del cual se pueden construir muchas casas. La creación de un objeto a partir de una clase se llama Instanciación, donde cada objeto es una instancia de la clase.
Los Pilares de la POO, que son los fundamentos, nos hablan de la Abstracción, que consiste en extraer las propiedades más importantes de un objeto del mundo real para llevarlo a una clase. El Encapsulamiento, es el fundamento que protege la información de un objeto para que no sea manipulada sin autorización. La Herencia, es cuando una clase hija hereda atributos y métodos de una clase padre. El Polimorfismo, significa que objetos de clases diferentes pueden tener el mismo comportamiento, o sea los mismos métodos, pero implementarlos de diferentes maneras.
Otro concepto que debemos entender antes de adentrarnos en solid, son las Interfaces y Clientes. Las interfaces están muy relacionadas con el polimorfismo, varias formas de hacer los mismo, pero el polimorfismo trae el riesgo de tener código inconsistente. Para evitarlo utilizamos las Interfaces que son contratos que definen el nombre de los métodos y los argumentos que reciben, pero no especifican como implementar el método. Por último, tenemos el concepto de Clientes, que son parte del programa que interactúan o utilizan clases o interfaces.
Los 5 Principios Solid
La palabra solid, no significa que tu código sea solido o robusto, como se podría pensar. Solid es un acrónimo de los principios en inglés para que estos principios puedan ser más fáciles de recordar:
Cuatro (4) de estos principios fueron creados por Robert C. Martín, quien dedico varias décadas a estudiar cómo crear reglas para hacer código limpio y es el autor del libro Clean Code y el tercero desarrollado por Bárbara Liskov, reconocida científica de la computación.
La S, del Principio de Responsabilidad Única (SRP)
El Principio de Responsabilidad Única (Single Responsibility Principle – SRP) dice que una clase debe tener una única responsabilidad, es decir una única función y por ende una clase debe tener una sola razón para ser modificada. Una clase, debería encargarse de una sola parte del sistema. Una clase no puede ser demasiadas cosas o tener demasiadas razones para cambiar, porque esto genera problemas cuando el código crece. La manera de resolver este problema es que las clases tenga una sola función, esta es la única forma de asegurarnos de que esa única cosa que hace, la hace muy bien.
Se deben crear tantas clases como funciones, es decir que una clase delega a otra (s) las funciones – responsabilidades que esta no puede asumir.
La O, de Principio Abierto / Cerrado (OCP)
El Principio Abierto / Cerrado, está muy relacionado con el anterior porque dice que una clase debe estar cerrada para su modificación, pero abierta para su extensión. Lo que se busca con este principio es que la funcionalidad básica de nuestro sistema este protegida y que no se pueda romper.
Para conseguir esto, nos dice que para añadir nuevas funcionalidades tenemos que escribir código nuevo, y no modificar código ya existente que seguramente ya funciona. El objetivo es intentar escribir código que no se tenga q cambiar cada vez que se tengan que cambiar los requerimientos.
Es decir, que si queremos agregar nuevas funcionalidades a la clase no se debería cambiar el código porque se podrían “romper cosas”, por el contrario, se debería extender las funcionalidades del código desde afuera. Es aquí donde entran en juego la Herencia (crear clases que hereden de la clase base) y el polimorfismo.
La L, del Principio de Sustitución de Liskov (Liskov Substitution Principle - LSP)
Este principio dice que si tenemos clases padre y clases hijas (es decir herencia) las instancias de las clases hijas y las instancias de las clases padre deben poderse intercambiar sin producir resultados inesperados. Es decir, que los objetos instanciados a partir de esas dos clases deberían ser iguales o cumplir con las mismas características.
Algo muy importante es que debemos evitar crear restricciones o cambiar el comportamiento de los métodos heredados en una clase, para luego no tener comportamientos inesperados en la aplicación.
La I, del Principio de Segregación de Interfaces (Interface Segregation Principle - ISP)
El Principio de Segregación de Interfaces, nos dice que los clientes no deben verse obligados a depender de interfases que no utilicen, es decir, que un cliente solo debe conocer los métodos que va a utilizar. Esto supone que se deben crear métodos con clases comunes y luego con herencia crear clases hijas para cada tipo. Como cada tipo tendrá habilidades o características diferentes, se crean interfases específicas para cada habilidad. Entonces segregar interfases permite instancias y elementos específicos
La D, del Principio de Inversión de Dependencias (Dependency Inversion Principle - DIP)
En el Principio de Inversión de Dependencias, las clases de alto nivel no deben depender de las de bajo nivel, ambas deberían depender de interfases, ambas deben depender de abstracciones (depender de capas abstractas). En este caso, las clases en lugar de traer a las dependencias, recibe esas dependencias desde afuera a través a través de la interfaz, sin afectar a ninguna parte del sistema.
Los principios solid son un requisito obligatorio en tu camino si quieres convertirte en un programador de primer nivel. Solid, son un conjunto de principios con el propósito de escribir un mejor código.
Nuestra recomendación es evitar caer en la aplicación de estos principios de forma excesiva, sobre todo en donde no exista una necesidad real, si solid te ayuda a hacer tu código mejor, adelante.
Pero, si utilizar estos principios te lleva a complicar en exceso tu sistema, quizás sea conveniente aplicar parte de solid o ser un poco más flexible a la hora de implementar estos principios. Las herramientas han de ser funcionales y tenemos que utilizarlas con algún propósito.
Si quieres saber más de cómo funcionan o simplemente quieres crear tu código con estos principios te invitamos a consultar nuestra formación Solid y Arquitectura Hexagonal. Con nuestras formaciones ayudamos a tus equipos a avanzar en su desarrollo técnico, adquiriendo nuevos conocimientos y aportar soluciones a las empresas, recibiendo un problema y definiendo la solución.