Principios de diseño de Software (SOLID)

Los principios de diseño de software representan un conjunto de pautas que nos ayudan a evitar un mal diseño

Traducción del contenido publicado en

Los principios de diseño están asociados a Robert Martin que los reunió en

«Desarrollo de software ágil: principios, patrones y prácticas».

Robert Martin

Según Robert Martin hay 3 características importantes de un mal diseño que debe evitarse:

  1. Rigidez – Es difícil de cambiar porque cada cambio afecta a demasiadas otras partes del sistema.
  2. Fragilidad: cuando se realiza un cambio, se rompen partes inesperadas del sistema.
  3. Inmovilidad – Es difícil de reutilizar en otra aplicación porque no se puede desenredar de la aplicación actual.

Principios de diseño

  • Responsabilidad única
  • Abierto cerrado
  • Sustitución de Liskov
  • Segregación de la interfaz
  • Inversión de dependencia

Principio de Responsabilidad única

Una clase debe tener una sola razón para cambiar.

En este contexto, se considera que una responsabilidad es una razón para cambiar. Este principio establece que si tenemos 2 razones para cambiar para una clase, tenemos que dividir la funcionalidad en dos clases. Cada clase manejará sólo una responsabilidad y en el futuro si necesitamos hacer un cambio lo haremos en la clase que lo maneje. Cuando necesitamos hacer un cambio en una clase que tiene más responsabilidades, el cambio podría afectar a la otra funcionalidad de las clases.

El Principio de Responsabilidad única fue introducido por Tom DeMarco en su libro Structured Analysis and Systems Specification, 1979. Robert Martin reinterpretó el concepto y definió la responsabilidad como una razón para cambiar.

Principio Abierto Cerrado

Las entidades de software como clases, módulos y funciones deben estar abiertas para la extensión, pero cerradas para modificaciones.


Este es un principio genérico. Se debe tener en cuenta al escribir sus clases para asegurarse de que cuando necesite ampliar su comportamiento no tenga que cambiar la clase, sino extenderla. El mismo principio se puede aplicar para módulos, paquetes, bibliotecas. Si tiene una biblioteca que contiene un conjunto de clases, hay muchas razones por las que preferirá ampliarla sin cambiar el código que ya se escribió (compatibilidad con versiones anteriores, pruebas de regresión, ). Es por eso que tenemos que asegurarnos de que nuestros módulos sigan el Principio Abierto Cerrado.

Cuando se hace referencia a clases, mediante el uso de clases abstractas y clases concretas se puede seguir el Principio Abierto Cerrado para implementar su comportamiento. Esto exigirá tener clases concretas que extienden las clases abstractas en lugar de cambiarlas. Algunos casos particulares de esto son el Patrón plantilla y el Patrón de estrategia.

Principio de Sustitución de Liskov

Los tipos derivados deben ser completamente sustituibles por sus tipos base.

Este principio es sólo una extensión del Principio Abierto Cerrado en términos de comportamiento, lo que significa que debemos asegurarnos de que las nuevas clases derivadas están extendiendo las clases base sin cambiar su comportamiento. Las nuevas clases derivadas deben poder reemplazar las clases base sin ningún cambio en el código.

El Principio de Sustitución de Liskov fue introducido por Barbara Liskov en una Conferencia de 1987 sobre Lenguajes y Aplicaciones de Sistemas de Programación Orientados a Objetos, en abstracción y jerarquía de datos, en abstracción y jerarquía de datos

Principio de Segregación de la interfaz

Los clientes no deben verse obligados a depender de interfaces que no utilizan.

Este principio nos enseña a cuidar cómo escribimos nuestras interfaces. Cuando escribimos nuestras interfaces debemos tener cuidado de agregar sólo los métodos que deben estar allí. Si agregamos métodos que no deberían estar allí, las clases que implementan la interfaz también tendrán que implementar esos métodos. Por ejemplo, si creamos una interfaz llamada Trabajador y agregamos un método de descanso para el almuerzo, todos los trabajadores tendrán que implementarlo. ¿Qué pasa si el trabajador es un robot?

Como conclusión Las interfaces que contienen métodos que no son específicos de ella se denominan interfaces contaminadas o grasas. Deberíamos evitarlos.

Principío de Inversión de dependencia

Los módulos de alto nivel no deben depender de módulos de bajo nivel. Ambos deben depender de abstracciones.
Las abstracciones no deben depender de los detalles. Los detalles deben depender de abstracciones.

El Principio de Inversión de Dependencia establece que debemos desacoplar módulos de alto nivel de módulos de bajo nivel, introduciendo una capa de abstracción entre las clases de alto nivel y las clases de bajo nivel. Más aún invierte la dependencia: en lugar de escribir nuestras abstracciones basadas en detalles, debemos escribir los detalles basados en abstracciones.

La inversión de dependencia o la inversión de control son términos más conocidos que se refieren a la forma en que se realizan las dependencias. De la manera clásica cuando un módulo de software (clase, framework) necesita algún otro módulo, inicializa y contiene una referencia directa a él. Esto hará que los 2 módulos estén altamente acoplados. Para desacoplarlos, el primer módulo proporcionará un hook (una propiedad, un parámetro) y un módulo externo que controla las dependencias inyectará la referencia al segundo.

Mediante la aplicación del Principio de Inversión de Dependencias, los módulos se pueden cambiar fácilmente por otros módulos simplemente cambiando el módulo de dependencia. Las fábricas y las fábricas abstractas se pueden usar como marcos de dependencia, pero hay marcos especializados para eso, conocidos como contenedor de Inversión de control.