Cómo crear código reutilizable en JavaScript usando patrones de diseño

Si alguna vez desea crear código JavaScript reutilizable o colaborar con un equipo de desarrolladores, entonces necesita saber cómo usar e identificar los diferentes patrones de diseño en el lenguaje.

En JavaScript, el término patrón de diseño se refiere a una forma específica de escribir código y, a menudo, se lo considera una plantilla de programación. Lo interesante es que la etiqueta "patrón de diseño" se puede aplicar a cualquier cosa, desde una aplicación completa hasta un simple bloque de código.

El patrón de diseño es un tema amplio, pero al comprender el patrón del módulo y el método de fábrica, debe familiarizarse con él.

El patrón del módulo

Los módulos de JavaScript se introdujeron en 2009, con la versión ES5 del lenguaje de programación. Mediante el uso de módulos, los desarrolladores ahora podían crear piezas de código personalizadas y exportarlas para usarlas en otras secciones de una aplicación JavaScript.

La estructura básica del patrón del módulo

 
(function(){
//Declare private variables and functions
//Declare and return public variables and functions
})();

En el ejemplo anterior, los patrones de módulo siempre se incluyen en una expresión de función invocada inmediatamente (IIFE). Esto significa que un patrón de módulo se ejecuta tan pronto como se define. Lo importante a tener en cuenta es que el patrón del módulo consta de dos secciones distintas.

La primera sección se usa para declarar variables y funciones privadas, a las que solo se puede acceder dentro del alcance del patrón del módulo.

La segunda sección consta de un valor de retorno que incluye variables públicas y funciones a las que se puede acceder fuera del alcance del patrón del módulo.

Uso del patrón de módulo para crear una aplicación

Considere una aplicación simple como un administrador de tareas. Usando el patrón de módulo, necesitará crear módulos personalizados para cada sección. Estos pueden incluir:

  • Un controlador de tareas
  • Un controlador de interfaz de usuario
  • Un controlador de almacenamiento
  • Un controlador de aplicaciones

Relacionado: Proyectos de programación para principiantes

El controlador de tareas se utilizará para crear cada nueva tarea. El controlador de la interfaz de usuario se utilizará para controlar las funciones relacionadas con la interfaz de usuario, como escuchar el clic de un botón o cambiar lo que se muestra. El controlador de almacenamiento se utilizará para guardar cada nueva tarea en una base de datos. El módulo de la aplicación se utilizará para ejecutar la aplicación.

Uso del patrón de módulo para crear un ejemplo de controlador de interfaz de usuario

 
const UIController = ( function() {
//the private section of the module
let component = 'Replacement Text';
const changeComponent = function() {
//change all the h1 text to what is in the component variable above
const element = document.querySelector('h1');
element.textContent = component;
}
//the public section of the module
return{
callChangeComponent: function() {
changeComponent();
}
}
})();

El ejemplo anterior muestra claramente las dos secciones que se encuentran dentro de un patrón de módulo: privado y público.

En la sección privada de la función, la variable de componente y la función changeComponent son ambas privadas. Por lo tanto, si quisiera cambiar todo el texto h1 en una página web, obtendría un error si escribiera el siguiente código.

Manera incorrecta de invocar el ejemplo de componente de cambio

 
UIController.changeComponent();

El mensaje de error indicará explícitamente que changeComponent () no es una función de la función UIController. Ésta es la belleza del patrón del módulo; las variables y funciones que se crean en la sección privada nunca serán accedidas directamente fuera del alcance de esa función.

Aunque no se puede acceder directamente a las variables privadas, se puede acceder a ellas indirectamente (desde la sección pública). Una conclusión del ejemplo anterior del controlador de IU es que la sección pública en el patrón del módulo siempre está marcada por la propiedad return.

Dentro de los parámetros de la propiedad return, ahora podemos obtener acceso indirecto a la función changeComponent. Ahora podemos usar la siguiente línea de código (con el patrón de módulo anterior) para cambiar efectivamente todo el texto h1 en una página web de destino a "Texto de reemplazo".

Manera correcta de invocar el ejemplo de componente de cambio

 
UIController.callChangeComponent();

El patrón de fábrica

El patrón de fábrica (también conocido como método de fábrica) es otro patrón de diseño de JavaScript popular. El patrón del módulo brilla cuando se requiere la encapsulación de datos, y el patrón de fábrica es más útil en los casos en que se trata de una colección de diferentes objetos que son similares en algunos aspectos.

Volviendo a nuestro administrador de tareas anterior; si permitiéramos que el usuario asigne un tipo a cada tarea que se crea, entonces podríamos crear ese aspecto de la aplicación (de manera bastante eficiente) usando el patrón de fábrica

Ejemplo de uso del patrón de fábrica para asignar un tipo de tarea

 
//Factory pattern function
const TaskFactory = function(){
this.createTask = function(name, type){
let task;
//check the type the user selected
if(type === 'urgent'){
task = new UrgentTask(name);
}else if(type === 'trivial'){
task = new TrivialTask(name);
}
//set the type selected in the if statement to the one received as a property
task.type = type;
//used to print the task and its type to the console
task.define = function(){
console.log(`${this.name} (${this.type}): ${this.priority}`)
}
return task
}
}

El código anterior usa el método de fábrica para crear nuevas tareas, verificar el tipo (urgente o trivial) y asignar la propiedad apropiada antes de imprimir la nueva tarea en la consola.

La función interna createTask, prepara el escenario para que se creen múltiples tareas simultáneamente, pero antes de que intentemos crear nuevas tareas, hay un código adicional que debemos incluir en esta sección del proyecto.

En el código anterior, estamos creando una nueva UrgentTask o una nueva Trivialtask si se cumple una condición específica. Sin embargo, no hay ninguna función o clase con estos nombres en nuestro proyecto; este problema se puede resolver fácilmente introduciendo el siguiente código en nuestro proyecto.

Cree tipos de tareas urgentes y triviales

 
//Create the urgent task type
const UrgentTask = function(name){
this.name = name;
this.priority = "as soon as possible"
}
//create the trivial task type
const TrivialTask = function(name){
this.name = name;
this.priority = "when you can"
}

Debido al código anterior, ahora podemos asignar la propiedad UrgentTask o TrivialTask ​​a cada nueva tarea que se crea. El siguiente paso es crear ahora una nueva tarea, pero antes de eso, necesitamos crear una base de datos para almacenar cada nueva tarea a medida que se crea.

Dado que la creación de una base de datos es un artículo completo en sí mismo, sustituiremos una base de datos con una estructura de datos (una matriz).

Creación de un ejemplo de matriz

 
//create an array to host the different task
const task = [];

Ahora finalmente podemos crear una nueva tarea.

Ejemplo de creación de nuevas tareas

 
//create two new tasks
const factory = new TaskFactory();
task.push(factory.createTask('Clean the house', 'urgent'));
task.push(factory.createTask('Reach level 30 in Candy Crush', 'trivial'));

Con el código anterior, ahora puede crear dos nuevas tareas utilizando la función TaskFactory que creamos inicialmente. Cuando creamos cada nueva tarea, las propiedades (nombre y tipo) se pasan a la función createTask, que se encuentra en la función TaskFactory que creamos usando el patrón de fábrica.

Una vez que cada tarea ha pasado por TaskFactory y se le asigna la propiedad de tipo correspondiente. Luego se inserta en la matriz de tareas que creamos anteriormente.

Nuestro único dilema ahora es ¿cómo sabemos que esas dos tareas fueron creadas o que nuestro patrón de fábrica funcionó? Si hubiéramos utilizado una base de datos, simplemente podríamos verificar la base de datos para ver si se crearon dos nuevas tareas.

Vuelva al "Ejemplo de uso del patrón de fábrica para asignar un tipo de tarea" anterior, directamente debajo del comentario "utilizado para imprimir la tarea y su tipo en la consola", hay una pequeña función "task.define" que se creó para imprima cada tarea de la matriz en la consola utilizando el siguiente método de matriz .

 
//print each task to the console
task.forEach(function(task){
task.define();
});

Debería ver la siguiente salida que se muestra en su consola.

 
Clean the house (urgent): as soon as possible
Reach level 30 in Candy Crush (trivial): when you can

Ahora puede usar patrones de diseño en sus proyectos de JavaScript

En esta etapa, debe comprender los patrones de diseño en JavaScript y comprender cómo se pueden usar los patrones de diseño para crear código reutilizable y hacer la vida más fácil para todos los desarrolladores involucrados en un proyecto.

Ahora que sabe cómo funcionan dos patrones de diseño de JavaScript populares, debería poder aplicarlos de manera eficiente para desarrollar una aplicación.

Crédito de la imagen: Alltechbuzz / Pixabay