SOLID Design Principles

En este post me gustaría guardar información sobre los principios de diseño SOLID.

Pero a fin de cuentas, ¿Qué es SOLID?
Bueno, básicamente es un set de principios de diseños presentados por Robert C. Martin

Robert Cecil Martin.png
By Tim-bezhashvyly - Own work, CC BY-SA 4.0, Link

El, ademas de tener una serie de libros y su blog, hay una selección de 5 principios que usualmente se incluyen. Quiero hacer un breve resumen y una simple implementación en javascript.

Single Responsibility Principle

El primer principio se llama principio de una sola responsabilidad, dicho principio aunque es bastante simple, usualmente tendemos a caer en ese error. Básicamente dice que una clase debería tener una sola responsabilidad y que es una mala idea incluir otras funcionalidades (Y por consiguiente librerías) a esa clase.

Supongamos que tenemos una clase donde guardamos nuestras Tareas

class Tasks {

    constructor() {
        this.tasks = {};
    }

    addEvent(text) {
        let c = ++Tasks.count;
        let task = `${c}: ${text}`;
        this.tasks[c] = task;

        return c;
    }

    removeEvent(index) {
        delete this.tasks[index]
    }

    toString() {
        return Object.values(this.tasks).join('\n');
    }
}

Y para crear nuestras tareas, lo usamos de la siguiente forma

Tasks.count = 0;

let taskManager = new Tasks();
taskManager.addEvent('Study design patterns');
taskManager.addEvent('Clean the house');

console.log(taskManager.toString())

// Resultado: 
// $ node  index.js 
// 1: Study design patterns
// 2: Clean the house

Todo va bien, porque la clase Tasks solamente tiene una responsabilidad. Pero imaginemos que queremos guardar todas las tareas en una base de datos. Esto se puede hacer fácilmente agregando una nueva función de la siguiente forma:

const fs = require('fs');

class Tasks {

    constructor() {
        this.tasks = {};
    }

    // Another Methods

    save(filename) {
        fs.writeFileSync(filename, this.toString())
    }
}

Todo luce bien, pero más adelante se tendrá que agregar la función que cargue el archivo, y de pronto en el futuro se quiera traer desde un WebService. Y pues allí ya estamos cayendo en que ya no tenemos una sola responsabilidad, y el tema es ¿porque esto es un problema?

Ya agregamos una segunda responsabilidad a nuestra clase, con ello nuevas librerías, etc pero, imaginemos que esa funcionalidad de guardar quiere ser utilizada en otra clase? Ya vamos viendo por donde va el asunto … no mezclar peras con manzanas

Entonces tiene más sentido sacar todas esas operaciones y hacer una clase separada como la siguiente:

class PersistenceManager {

    saveToFile(tasks, filename) {
        fs.writeFileSync(filename, tasks.toString())
    }
}

Y podemos conectar nuestra clase Tasks con la nueva de la siguiente forma:

let taskManager = new Tasks();
// Adding some tasks

console.log(taskManager.toString())

let persist = new PersistenceManager();
persist.saveToFile(taskManager, 'tasks.txt')

Finalmente, podemos darnos cuenta que es mejor agrupar funcionalidades por clases en vez de tener todas las funcionalidades en una misma clase.

Proximamente publicaré el resto de los principios! Gracias por llegar hasta aquí.