Patrones de diseño – Parte I

¿Qué son los patrones de diseño?

Los patrones de diseño o design patterns son soluciones a problemas recurrentes que nos encontramos durante el desarrollo de software. Nos sirven para solucionar problemas que se repiten en la etapa del desarrollo de software.

Al final son una forma estándar de solucionar problemas de diseño que ya han sido probados y que funcionan

Tipos de patrones de diseño

Existen tres tipos de patrones, que son:

  • Creacionales: Aquellos que nos ayudan durante la creación de objetos.
  • Estructurales: Los que nos ayudaran en como estructurar o de que forma se componen los objetos.
  • Comportamiento: Son aquellos que nos ayudan en como los objetos se comunican o comportan entre ellos.

Patrones creacionales

Factory o Factory Method

Imagina que quieres desarrollar una aplicación de logística para gestionar la entrega de paquetes y que por ahora solo realizas entregas por carretera. Por lo tanto tu aplicación solo instancia clases de tipo Camión.

¿Pero que ocurre si mañana entregas paquetes a otros continentes? Tendrías que revisar toda tu aplicación para añadir esta nueva clase Barco.

El patrón Abstract Factory propone que en lugar de crear estos objetos directamente los crees a través de objeto llamado «fabrica«.

De esta forma si en el futuro entregas paquetes a través de la clase Avión solo modificarías la «fabrica» sin necesidad de realizar modificaciones en el resto del código.

Tenemos una explicación muy bien detallada en https://refactoring.guru/es/design-patterns/factory-method

Builder

Para este caso vamos pensar que desarrollamos un portal de venta de un coche con muchos modelos distintos para un mismo coche. Por ejemplo podemos seleccionar el modelo clásico, deportivo, exhibición, futurista, etc.

¿Crearíamos una clase coche con todas las posibilidades existentes? ¿No seria una clase demasiado grande y compleja?

Aquí es donde el patrón builder nos ayuda, el patrón builder nos dice que en lugar de tener una sola clase tengamos varias clases llamadas constructoras con cada uno de los modelos y una clase directora que sera la que utilizaremos para crear el coche.

De esta forma si queremos añadir un nuevo modelo a nuestro coche nos sera mucho mas sencillo añadiendo un nuevo constructor en lugar de modificar una clase única que seguramente quedaría llena de sentencias if.

Una explicación mas detallada en https://refactoring.guru/es/design-patterns/builder

Abstract Factory

Vamos a pensar en nuestro primer ejemplo de empresa de logística pero en este caso vamos a gestionar a la vez varias empresas de logística donde cada una tiene su propia imagen. Por ejemplo seur, ups y dhl.

Dependiendo de la empresa contratada vamos a necesitar un camión, barco o avión con la imagen de seur, ups o dhl. Con el método Factory tenemos solucionado como crear el transporte pero ahora tenemos la complejidad de la marca o imagen.

Podríamos usar tres veces el patrón Factory pero tendríamos que comprobar en cada caso la imagen que queremos obtener para saber cual de las tres «fabricas» debemos utilizar.

El patrón Abstract Factory nos ayuda con este problema, nos dice que tengamos una «fabrica» común y que por debajo derive a la fabrica correspondiente la responsabilidad.

De esta forma al añadir una nueva empresa o marca solo debemos crear una nueva «fabrica» y modificar la «fabrica» común.

Más información en https://refactoring.guru/es/design-patterns/abstract-factory

Prototype

Imagina que estamos desarrollando una aplicación tipo Paint de windows y tenemos que implementar el famoso copia y pega.

Para este caso nos seria muy útil poder copiar el objeto que se ha seleccionado para luego insertarlo, ¿Pero como sabemos que tipo de objeto ha seleccionado?

En este caso el patrón Prototype es la solución, nos dice que debemos tener una interfaz común con el método clonar y que deben utilizar todos aquellos objetos que puedan ser clonados.

De esta forma evitamos acoplar el código de nuestro programa a tener que conocer las clases que trabajamos. Si mañana queremos clonar un nuevo objeto no tenemos que modificar todo el código anterior.

Tenemos mucha mas información en https://refactoring.guru/es/design-patterns/prototype

Singleton

Imagina que estamos desarrollando un editor de texto y vamos a implementar la funcionalidad de imprimir el documento.

Si cada vez que imprimimos un documento creamos el objeto es posible que al intentar imprimir dos documentos en un periodo muy corto de tiempo el segundo documento no se pueda imprimir porque la impresora esta ocupada.

¿Entonces que hacemos? ¿Implementamos toda la lógica para tratar estos errores? Imagina que queremos imprimir 100 documentos. ¿Tiene sentido tener 100 objetos creados todos preguntando a la impresora si esta libre o no? ¿No sería más sencillo tener una sola cola de impresión?

El patrón Singleton nos da una forma de tener un objeto único en toda nuestra aplicación por lo que en lugar de tener 100 objetos intentando imprimir 100 documentos tendríamos un único objeto con 100 documentos a imprimir.

Con el patrón Singleton cada vez que intentamos crear el objeto nos devuelve el objeto en su estado actual en caso de exisitir y si nunca fue creado

Mas detalles en https://refactoring.guru/es/design-patterns/singleton

Cliente Web SSH con Laravel

A raíz del cliente web ssh que hice con PHP he decidido crearlo usando el framework de Laravel.

Ahora se pueden guardar los servidores con su usuario y contraseña pero las contraseñas son encriptadas con el password que se indica. De esta forma aunque una persona acceda a la base de datos no podra obtener acceso a los servidores.

Para poder conectarte es necesario desencriptar la contraseña introduciendo la contraseña con la que se encripto.

Teneis mas información en https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/encrypt

Y tenéis acceso al repositorio de la app en https://github.com/roke22/Laravel-ssh-client

Cliente Web SSH con PHP

Hace algunos días estuve buscando un cliente web para conectar por SSH a servidores linux y encontré una solución muy buena que utilizaba node.js y que podéis encontrar aqui https://github.com/billchurch/WebSSH2

Viendo como WebSSH2 utilizaba los websockets decidí hacer lo mismo pero esta vez usando PHP en lugar de node.js. Para ello he utilizado la librería libssh2 de php la cual debéis tener activa si queréis utilizar el cliente que he creado.

Podéis encontrar el cliente y ayudarme a mejorarlo en github https://github.com/roke22/PHP-SSH2-Web-Client

A continuación os dejo un pequeño vídeo que muestra como funciona.