Variables en Javascript y constantes

Javascript variables and constants

Variables

One of the most used elements are variables in Javascript. We can describe variables in Javascript as boxes to hold information, which we label so that we can find that information easily. This label is the name of the variable and the box is the space used in RAM.

Variables y constantes, cajas que guardan información
Variables and constants, boxes that store information

This is what variables are like in Javascript, and in fact in any programming language. You can also store any datatype, whether they are numbers, text strings, functions or any type of object.

There are two ways to declare a variable. One is using let and the other using var.

//Variables de tipo String
var name = 'Jaime';
let last name = "Cervantes"

The shape var It is the one that has always existed since the origin of language, then in 2015 it appeared let in order to mitigate certain deficiencies of var. For this reason, the recommendation is to use letIn any case, it is important to know well var because you will come across a lot of code that still uses var.

How are variables used in Javascript?

The name or identifier of a variable, it cannot start with a number, it must start with some letter (including _ and $), and Javascript is also case-sensitive. Is not the same name and Name, these are two different variables.

Variables are defined in two ways:

With a single let:

let name = 'Jaime',
    last name = 'Cervantes',
    mother's last name = 'Velasco';

a single var:

var name = 'Jaime',
    last name = 'Cervantes',
    mother's last name = 'Velasco';

Now with a let for each variable:

let name = 'Jaime';
let last name = 'Cervantes';
let mother's last name = 'Velasco';

With a var for each variable.

var name = 'Jaime';
var last name = 'Cervantes';
var mother's last name = 'Velasco';

In the previous example we define variables of type string (text strings), but remember that you can store any type of data.

It is advisable to put each variable on its own line because it is faster to understand for the “you” of the future and your colleagues who have not touched your code. For example, DO NOT define the variables like this:

let name = 'Jaime', last name = 'Cervantes', mother's last name = 'Velasco'; edad = 32, sexo = 'H'

Let's try numbers.

let edad = 32.9;
let hijos = 1;
var edad = 32.9
var hijos = 1;

Boolean data only stores false or true.

let esHombre = true;
let esAlto = false;
var esHombre = true;
var esAlto = false;

As its name says, its value can be variable, therefore you can reassign a new value to your variable:

var name = 'Jaime';
name = 'Pepito';
name = 'Menganito';
console.log(nombre); // 'Menganito'

Variable scopes in Javascript, let vs var

The main difference between variables defined with let and var is the scope they reach when they are declared:

  • With let you have block scope {}.
  • With var you have scope of function function() but not block.

Example of block scope.

if (true) {
  let name = 'James';
}
console.log(nombre); // Uncaught ReferenceError: nombre is not defined

Because let has block scope, when wanting to access the variable name Javascript shows:

Uncaught ReferenceError: name is not defined

Try to use block scope with var.

if (true) {
  var name = 'Jaime';
}
console.log(nombre); // 'Jaime';

In this example the variable name If it can be accessed from outside the blocks, this is because it is not inside any function.

Now we are going to declare the variable with var inside a function.

functions setearNombre() {
  var name = 'Jaime';
}
setearNombre();
console.log(nombre); // Uncaught ReferenceError: nombre is not defined

Let's see what happens with let when we try to use function scope.

functions setearNombre() {
  let name = 'Jaime';
}
setearNombre();
console.log(nombre); // Uncaught ReferenceError: nombre is not defined

If we define a variable with let inside a function, we can't access it from outside either, because the function definition itself uses blocks {}.

Constants in Javascript

Constants are in the same way as variables, labeled boxes to store information, with the only difference that they cannot be reassigned to any other value.

const name = "Jaime";
name = "Pepito"; // Uncaught TypeError: Assignment to constant variable 

Let's not forget to declare each constant on its own line to improve the readability of our code.

const name = "Jaime";
const last name = "Cervantes";
const mother's last name = 'Velasco';
const name = 'Jaime',
    last name = 'Cervantes',
    mother's last name = 'Velasco';

Same rules as variables with let

Constants follow the same block scope rules as variables in Javascript with let.

As well as let, const has block scope, so if you define a variable with var and has the same name as a constant, the following error will be thrown:

{
  const name = "Jaime";
  var name = "Pepito"; // Uncaught SyntaxError: Identifier 'nombre' has already been declared
}

Constants in javascript read-only and mutable

Constants are read-only, which is why they cannot be reassigned a value. Even so, these saved values continue to preserve the behavior of their data type.

For example, if you create a constant for an object, you can change the properties of that object.

An object literal in JavaScript is nothing more than a set of values identified with a name or key, like the following:

const James = {
  name: "Jaime",
  last name: "Cervantes",
  mother's last name: "Velasco"
};
James.name = "Pepito"; // todo bien, se puede cambiar una propiedad
James = {}; // Uncaught Type Error: Assigment to constant variable

The reference to the object is read-only, but it does not mean that the value is immutable. As seen in the example, you can change the property, but not reassign a new value to the constant James as we can see in the last line of the example.

How to name variables and constants in Javascript?

Any fool can write code that a computer can understand. Good programmers write code that humans can understand.

Martin Fowler

The main objective of naming variables and constants is to immediately understand what we are storing in them. It is important to correctly describe the content of the variables, because this makes life easier for the next person who needs to read and modify our code.

This next person is very often “you” from the future, and unless you are a robot, you won't be able to remember every detail of your code.

Most of the time spent by a programmer is reading and understanding code, we don't want to spend a lot of time deciphering the content of them, as programmers we are happier creating new things.

For this reason we should not be surprised by the importance in naming our variables and constants, it is one of the best ways to not waste our time and the time of our colleagues.

Recommendations:

  • Take enough time to name a variable. It's like organizing your room, the tidier it is, the faster it will be to find the other sock (it happens to me a lot when I don't organize mine) xd.
  • The name must be very semantic and explain its context. Avoid names like data either info because they don't say much about the context, it is obvious that they are data and information, but for what? or what?.
  • Agree with your colleagues on how to name variables, especially those that are closely related to the business. For example, for a user's registration data, it can be “UserRegistration”, “CustomerRegistration”, “VisitorRegistration”, all three forms can be valid (it depends a lot on the context), but it is better to follow a convention through an agreement.
  • Avoid very short names like “u1”, “a2”, “_”, “_c”
  • Avoid abbreviations, prefixes, suffixes and infixes. These are difficult to understand. For example pmContentWhat is “pm”?
  • If the variable or constant has a very small scope, that is, it is used in nearby lines, then the name can be short.
  • If the variable or constant is used in a large scope, that is, it is referenced over a distance of many lines, then the name must be very descriptive, and therefore it is normal that it can be long.

Related posts

https://www.pensemosweb.com/introduccion-javascript/
https://www.pensemosweb.com/javascript-scheme-self-java/
Javascript Event Loop, concurrencia y asíncrono

Javascript Event Loop, concurrencia y asíncrono

Javascript es secuencial

“Event loop”, tal vez lo has escuchado. Esto es porque javascript tiene modelo de ejecución de código donde utiliza un ciclo de eventos (event loop), que una vez entendiendo su funcionamiento, se puede crear código mucho más eficiente, y resolver problemas rápidamente, que a simple vista no son tan obvios. Es la base de la concurrencia y el asincronismo.

Para comenzar:

  • Javascript se ejecuta en un solo hilo de ejecución, como se ejecuta un solo hilo, su ejecución es secuencial, no es como JAVA donde se pueden lanzar otros hilos.
  • Existen ambientes huéspedes donde se ejecuta javascript que tienen su propia API, ejemplo:
    • Navegador web
    • Node.js
  • Este funcionamiento secuencial es el mismo, no cambia por estar relacionado con un ambiente huésped.
  • La concurrencia se logra a través de invocaciones asíncronas a la API del ambiente huésped, esto evita que el funcionamiento se bloquee y provoque lentitud de las aplicaciones.

Elementos para la concurrencia

Veamos con más detalle los elementos que hacen funcionar Javascript en los ambientes huéspedes.

  1. Call Stack – Pila de ejecuciones
  2. Callback Queue – Cola de retrollamadas, tambien llamado Task Queue
  3. Event Loop – Ciclo de eventos
  4. Host Environment – Funcionalidad del ambiente huésped
Event loop, ciclo de eventos javascript
Event loop, ciclo de eventos javascript

Calls Stack, heap y motor de javascript

Del lado izquierdo tenemos al motor de javascript, este motor se encarga de ejecutar nuestro código. A veces es llamado máquina virtual, porque se encarga de interpretar nuestro código a lenguaje máquina y ejecutarlo. Solo puede ejecutar una línea de código a la vez. Tiene un Heap para guardar objetos y demás datos en memoria que el código pueda generar.

Pero también tenemos una Pila de llamadas (Call Stack). Los elementos de la pila son objetos y datos de memoria, pero tienen una estructura especifica. Tienen un orden y el último elemento en entrar es el primero en salir, se le llama LIFO (Last-in, First-out).

Cada elemento de la pila es un trozo de código Javascript y guarda las referencias del contexto y variables utilizadas. La pila ejecuta el trozo de código en turno hasta quedar vacía.

Callbacks Queue

Abajo tenemos Callbacks Queue, es una estructura de datos y guarda pedazos de código que el motor de javascript puede ejecutar. Es una cola, y como la cola de las tortillas el primero en formarse, es el primero en salir (FIFO, First-in, First-out).

Un callback, es una función que se pasa por parámetro a otra, de tal manera que esta última ejecuta el callback en un punto determinado, cuando las condiciones y/o los datos cumplen una cierta regla de invocación.

Event loop

Event Loop, este elemento nos permite mover la siguiente callback del Callbacks Queue al Call Stack. Como es un ciclo, en cada iteración toma un solo callback.

Ambiente huésped

Del lado derecho tenemos El ambiente huésped, el ambiente huésped es el lugar donde corremos Javascript, los más comunes son el Navegador web and Node.js. Las tareas que ejecuta el ambiente huésped son independientes de los demás componentes. En el navegador web tiene sus propias API como fetch, setTimeout, alert. Node.js también cuenta con su propia API como net, path, crypto.

¿Cómo es posible?, ¿Y la concurrencia? ¿Puedo hacer muchas cosas a la vez en un sitio web?

Todo el trabajo de poner un temporizador, renderizar contenido como texto, imágenes, animaciones, o ver videos, están a cargo del ambiente huesped. Lo que pasa es que las APIs del navegador web generan callbacks cuando su tarea ya está completada y los agrega al Callbacks Queue para que el event loop las tome y las mueva al Call stack.

Javascript se comunica con el ambiente huésped a través de su API, mas adelante vamos a utilizar un ejemplo basado en el diagrama de arriba, donde se utiliza window.setTimeout, la cual es una función del navegador web.

Concurrencia

Home es la función principal, con la que se inicia el proceso de ejecución en el call stack. Dentro de inicio tenemos cuatro setTimeout de dos segundos. La función setTimeout es propia del ambiente huésped, y a los cuatro setTimeouts le pasamos un callback, estos son, cb1, cb2, cb3 y cb4.  

Los temporizadores setTimeout se ejecutan en la parte de la funcionalidad del ambiente huésped dejando tiempo de ejecución para el call stack. He aquí la concurrencia, mientras el ambiente huésped ejecuta un temporizador, el call stack puede continuar ejecutando código.

Después de los primeros dos segundos, el ambiente huésped, a través del primer setTimeout pasa cb1 al callback queue, pero durante estos dos segundos se pueden realizar otras operaciones en el ambiente huésped, en el caso del navegador, un ejemplo seria que el usuario puede seguir escribiendo dentro de un textarea. De nuevo, he aquí la concurrencia.

Tras el primer setTimeout, el segundo setTimeout pasa cb2 al callback queue y así sucesivamente hasta el cb4. Mientras los callbacks se pasan al callback queue. He event loop nunca deja de funcionar, por lo que en alguna iteración el event Loop pasa cb1 al call stack y se empieza a ejecutar el código de cb1 y esto mismo sucede con cb2, cb3 and cb4.

Event loop en acción

Aquí abajo esta el ejemplo del que hablamos, el temporizador genera los callbacks en el orden que aparecen los setTimeouts más dos segundos. El Event Loop toma un callback en cada iteración, por lo que cada cb de setTimeout se invocan uno después del otro, y no exactamente después de dos segundos, pues entre que se posicionan los callbacks en la cola y se mueven al call stack de ejecución transcurre más tiempo. Esto sin contar el tiempo que trascurre entre cada invocación de setTimeout.

Si en los cuatro callbacks se indica el mismo tiempo en milisegundos. Presiona el botón RERUN, Te darás cuenta de que los tiempos no son iguales y que pueden pasar más de dos segundos.

Conclusion

  1. Las APIs huéspedes reciben callbacks que deben insertar en la callback queue cuando el trabajo que se les encomienda esta hecho, por ejemplo un callback de una petición ajax se pasa a la callback queue solo cuando la petición ya obtuvo la respuesta. En el ejemplo que describimos arriba con setTimeout, cuando pasan dos segundos, se inserta el callback al callback queue.
  2. Mientras el ambiente huésped realiza sus tareas, en este caso, los demás temporizadores, el call stack de ejecución de javascript puede ejecutar el código que el event loop le puede pasar desde el callback queue.
  3. He Event loop es un ciclo infinito que mientras existan callbacks en el callback queue, pasara cada callback, uno por uno, al call stack.
  4. He call stack no puede ejecutar más de un código a la vez, va ejecutando desde el último elemento hasta el primero, en nuestro caso hasta la terminación de la función inicio que dio origen a todo el proceso. Es una estructura de datos tipo Pila.

Gracias a que los callbacks se ejecutan hasta que un trabajo específico esté terminado, proporciona una manera asíncrona de ejecutar tareas. Las tareas pueden realizarse en el ambiente huésped sin afectar la ejecución del call stack. En la pila solo se ejecuta código que recibe el resultado de las tareas realizadas por el ambiente huésped.

¿Cómo empezar con Redux en 7 minutos?

¿Cómo empezar con Redux en 7 minutos?

¿Qué es Redux?

Redux es un contenedor predecible del estado de aplicaciones JavaScript.

Te ayuda a escribir aplicaciones que se comportan de manera consistente, corren en distintos ambientes (cliente, servidor y nativo), y son fáciles de probar. Además de eso, provee una gran experiencia de desarrollo, gracias a edición en vivo combinado con un depurador sobre una línea de tiempo.

redux.org

Te permite controlar el flujo de datos de una aplicación Javascript, este flujo de los datos funciona en una sola dirección. Por esta única dirección es mucho más fácil controlar las mutaciones and operaciones asíncronas.

Redux es parecido a flux, de hecho está basado en flux

En el estado de una aplicación, principalmente en aplicaciones SPA, esto es muy importante, porque las aplicaciones web modernas tienen gran complejidad de operaciones asíncronas. Además de controlar el estado entre los componentes.

¿Qué problemas puedo mitigar con Redux?

En el ejemplo de aplicaciones web, estas necesitan controlar peticiones a servidores, obtener datos y controlar el estado en el cliente. Aun cuando estos datos no han sido guardados en el servidor.

Estas aplicaciones modernas requieren de un control complejo y por eso nuevos patrones de arquitectura como Redux y flux  nacen para hacer el desarrollo más productivo.

Las mutaciones de objetos son difíciles de manejar y más a escalas medianas y grandes. Se comienza a perder el control de los datos, este flujo de datos generan comportamiento no deseados. Mala información desplegada al usuario y código que es muy difícil de mantener.

Sin contar cosas más elevadas como tu salud y causa de estrés por el esfuerzo en arreglar estas inconsistencias, te hace perder tiempo para mantener la aplicación funcionando correctamente. Por si fuera poco afectas a tus usuarios porque ellos obtienen información incorrecta y pierden su tiempo al utilizar esa información.

¿Qué decir de las operaciones asíncronas? Bueno, prácticamente pasa lo mismo o aún peor. Porque en una operación asíncrona no sabes cuando obtendrás el resultado y además normalmente vienen acompañadas con el deseo de hacer modificaciones al estado de la aplicación.

Un ejemplo común es el control de los datos de tu aplicación con cualquier frawework front-end de componentes visuales.

¿De qué está hecho Redux? Tres elementos

Store. El store es un objeto donde guardas toda la información del estado, es como el modelo de una aplicación, con la excepción que no lo puedes modificar directamente, es necesario disparar una acción para modificar el estado.

Actions. Son el medio por el cual indicas que quieres realizar una modificación en el estado, es un mensaje o notificación liviana. Solo enviando la información necesaria para realizar el cambio.

Reducers. Son las funciones que realizan el cambio en el estado o store, lo que hacen internamente es crear un nuevo estado con la información actualizada, de tal manera que los cambios se reflejan inmediatamente en la aplicación. Los reducers son funciones puras, es decir, sin efectos colaterales, no mutan el estado, sino que crean uno con información nueva.

¿Qué principios debo seguir? Tres principios

Un único Store para representar el estado de toda la aplicación. Tener una sola fuente de datos para toda tu aplicación permite tener centralizada la información, evita problemas de comunicación entre componentes para desplegar los datos, fácil de depurar y menos tiempo agregando funcionalidad o detectando errores.

Estado de solo lectura. Esto permite tener el control de cambios y evitar un relajo entre los diferentes componentes de tu aplicación, ni los componentes, ni peticiones ajax pueden modificar directamente el Estado (state) de tu aplicación, esto quiere decir que si quieres actualizar tu estado, debes  hacerlo a través de actions, de esta manera redux se encarga de realizar las actualizaciones de manera estricta y en el orden que le corresponden.

Los cambios solo se hacen con funciones puras. Al realizar los cambios con funciones puras, lo que realmente se hace es crear un nuevo objeto con la información actualizada, estas funciones puras son los reducers y no mutan el estado, al no mutar el estado, se evitan problemas de control, datos incorrectos, mal comportamiento y errores, también permite que la depuración sea más fácil. Puedes dividir los reducer en varios archivos diferentes y las pruebas unitarias son fáciles de implementar. Los reducers son funciones puras que toman el estado anterior y una acción, y devuelven un nuevo estado.

Otras arquitecturas como MVC (Modelo, Vista, Controlador), los cambios pueden existir en ambas direcciones, es decir, la vista puede cambiar el estado, el modelo lo podría modificar y también el controlador. Todos estos cambios necesitan estar sincronizados en varias partes de una aplicación para evitar inconsistencias, lamentablemente este problema de inconsistencia se vuelve muy difícil y tedioso de resolver.

Lo anterior no sucede con Redux.

¿Cómo funciona? Mi primer estado predecible con Redux

Primero veamos el flujo de una sola dirección de redux:

Redux: flujo de control una sola dirección
Redux: flujo de control una sola dirección

Ahora un ejemplo concreto para saber de que estamos hablando, el control de un contador:

See the Pen Redux: Contador State, es5 by Jaime Cervantes Velasco (@jaime_cervantes_ve) on CodePen.

Si quieres probar este ejemplo en tu máquina recuerda insertar o importar la librería Redux. En este ejemplo podemos ver el funcionamiento de Redux, cada vez que se da clic sobre los botones de incrementar y decrementar, el contador se incrementa y decrementa.

Si ahora nos vamos al código JS, podremos ver que solo tenemos una función llamada counter, esta función es un reducer y es una función pura, sin efectos colaterales.

Luego vemos que como parámetros recibe un state y un action, cuando creamos nuestro Store con Redux, estas funciones reducer son utilizadas para modificar el State.

Normalmente, el state, reducer and action son definidos en puntos diferentes, y pueden ser organizados en varios archivos y carpetas dependiendo de la necesidad de la aplicación, toda esta organización tiene la finalidad de tener un código limpio y separar funcionalidades. En este caso sencillo no es necesario, en un solo archivo tenemos todo.

State

Nuestro state es solo un valor numérico, el cual se va a incrementar o decrementar con los botones que están en la página, normalmente el state es un objeto literal o un array literal, pero en nuestro caso solo necesitamos un número. Su definición podría estar en otro archivo, sin embargo, para este ejemplo no es necesario, lo agregamos como valor por defecto del parámetro state.

functions counter(state = 0, action) { ...

Actions

Si seguimos revisando nuestro código, veremos unos cuantas condiciones que revisa el valor del parámetro action y dependiendo de la acción, se ejecuta alguna operación, en nuestro caso son las operaciones INCREMENTAR either DECREMENTAR.

The actions no son más que objetos literales como los siguientes:

const incrementar = { type: 'INCREMENTAR' }
const decrementar = { type: 'DECREMENTAR' }

Reducers

The reducer revisan esos actions, en nuestro ejemplo:

if (action.type === 'INCREMENTAR') {
  return state +  1;
}

if (action.type === 'DECREMENTAR') {
  return state - 1;
}

Con todo esto ya tenemos nuestro State y su estado inicial en caso de no estar definido, también nuestra primer reducer, counter, y nuestros primeros actions INCREMENTAR and DECREMENTAR.

Store

Es el momento de crear nuestro Store, utilizando la librería redux esto es muy fácil:

const store = Redux.createStore(counter);

Con la anterior línea, Redux crea un Store para controlar el estado de nuestra aplicación. Internamente, un Store es un Patrón observador que utiliza un Singleton para el State y expone los siguientes métodos principales:

  • store.getState()
  • store.subscribe(listener)
  • store.dispatch(action)

store.getState() te permite obtener el estado actual de tu aplicación.

store.subscribe(listener) ejecuta la función listener (u observador), cada vez que el store es actualizado.

store.dispatch(action) pide actualizar el estado, esta modificación no es directa, siempre se realiza a través de un action y se ejecuta con un reducer.

Reaccionar a cambios del state

Luego creamos una función render, para que se ejecute cada vez que el State de tu aplicación cambie.

Aquí nuestro contenido html:

<button id="incrementar">Incrementar</button>
<button id="decrementar">Decrementar</button>
<div id="state"></div>

Nuestra función render

functions render () {
  document.querySelector('#state').innerText = store.getState();
}

Invocamos render para pintar el valor 0

render()

Aquí te preguntarás, ¿Cómo es posible que esa línea imprima 0 en la pantalla?, pues internamente el store invoca un dispatch con un action vacío store.dispatch({}), esto invoca nuestra función reducer y al no encontrar ninguna acción, entonces regresa el estado inicial 0.

Luego nos subscribimos a store para escuchar u observar el State cada vez que se actualice y poder ejecutar la función render().

store.subscribe(render);

Esta línea permite que cuando demos clic en los botones de incrementar y decrementar, se imprima el nuevo valor en la página volviendo a renderizar su contenido.

Ejecutar dispatch a través de eventos del DOM

Y por último agregamos dos listeners correspondientes a los botones de incrementar y decrementar, cada botón realiza una invocación dispatch para modificar el estado.

<button id="incrementar">Incrementar</button>
<button id="decrementar">Decrementar</button>
<div id="state"></div>
document.querySelector('#incrementar').addEventListener('click', () => {
  store.dispatch(incrementar);
});

document.querySelector('#decrementar').addEventListener('click', () => {
  store.dispatch(decrementar);
});

Al fin tenemos el flujo de datos de nuestro sencillo ejemplo usando Redux, en general los componentes que forman a una aplicación que utiliza Redux son los siguientes:

Redux: flujo de control completo
Redux: flujo de control completo

Conclusions

Podemos notar el flujo en una sola dirección desde la vista con los actions dispatch(action), luego  los reducers counter(prevState, action) para modificar el store y este último manda la información a través de subscribe(render) and getState().

Redux como ya se mencionó en párrafos anteriores, nos proporciona:

  • El conocimiento en todo momento del estado de nuestra aplicación y en cualquier parte de la aplicación con mucha facilidad.
  • Fácil organización, con actions, reducer y store, haciendo cambios en una sola dirección, además puedes separar tus actions, reducer y el store en varios archivos.
  • Fácil de mantener, debido a su organización y su único store, mantener su funcionamiento y agregar nuevas funcionalidades es muy sencillo.
  • Tiene muy buena documentación, su comunidad es grande y tiene su propia herramienta para debuguear
  • Todos  los puntos anteriores hacen que sea fácil de hacer pruebas unitarias.
  • Y lo más importante, te ahorra tiempo, dinero y esfuerzo xD.
Introducción a programación funcional

Introduction to functional programming

Origin

El origen de la programación funcional data del año 1936, cuando un matemático llamado Alonzo Church necesitaba resolver un problema complejo, del cual no hablaremos aquí, pero Alonzo creó una solución, el lambda calculus. De esta forma nació la programación funcional, incluso mucho antes de la primera computadora digital programable y de los primeros programas escritos en ensamblador.

La programación funcional es mucho más antigua que la programación estructurada y la programación orientada a objetos. Te recomiendo también revisar esta información sobre el paradigma de programación funcional.

Sin efectos colaterales

Todo lo que necesitas saber sobre functional programming es que “No tiene efectos colaterales“, es decir, que sus elementos (funciones) son inmutables.

Lo anterior significa que una función no se mete en lo absoluto con datos que existen fuera de ella, si puede utilizar los datos enviados como parámetros, pero no debe modificarlos, todos los datos deben ser inmutables, ¿Por qué?, pues porque así hacemos las cosas más simples y con menos errores, más adelante tenemos un ejemplo. A este comportamiento se le llama puro.

No side effects nos permite entender todas las demás características de la programación funcional, por mencionar algunas principales:

  • Funciones puras
  • Inmutabilidad
  • Funciones de alto nivel
  • Funciones currificadas
  • Recursividad
  • Menos errores de programación porque no realiza efectos colaterales.

Toda función teniendo ciertos parámetros, cuando se ejecuta, obtendremos un resultado basado en esos parámetros, y si volvemos a utilizar los mismos parametros, entonces la función regresara el mismo valor. Esto es debido a que una función no depende de más datos externos que puedan ser modificados, así tendremos más seguridad y nuestro código se vuelve más entendible.

Javascript es un lenguaje de programación muy potente y multiparadigma, soporta el paradigma funcional y lo utilizaremos para nuestros ejemplos.

Funciones puras e inmutabilidad

Bueno, realmente ya explicamos de manera indirecta que es una función pura en los párrafos anteriores, pero veamos una definición formal. Una función pura es la que cumple con estas dos características:

  1. Siempre obtendremos el mismo resultado dado los mismos parámetros de entrada.
  2. No tiene ningún efecto colateral observable, no modifica el estado de los datos externos, por lo que todos los datos deben ser inmutables.

Un ejemplo de como cambiar el nombre de una objeto persona usando primero una función con efector colaterales:

functions cambiarNombre(name) {
  person.name = name;
}
const James = { name: 'Jaime', edad: 30 };
cambiarNombre('Juan')
console.log(jaime); // { nombre: 'Juan', edad: 30 }

En la anterior función notamos que se cambia objeto James, el cual supongamos que es parte del estado de nuestra aplicación, pero puede haber otras funciones que utilicen este objeto, por lo que se puede generar problemas si alguien más espera que la propiedad name del objeto siga siendo 'jaime'.

Ahora veamos la versión funcional de la función:

functions cambiarNombre(name, person) {
  return {
    name: name,
    edad: person.edad
  }
}
const James = { name: 'Jaime', edad: 30 };
const juan = cambiarNombre('Juan', jaime);
console.log(jaime); // { nombre: 'Jaime', edad: 30 }
console.log(juan); // { nombre: 'Juan', edad: 30 }

En la versión funcional, cambiarNombre no modifica el objeto James, más bien crea un nuevo objeto con la misma edad que James y con la propiedad name equal to 'Juan', con esto evitamos efectos colaterales por si el objeto James es utilizado por otra función u otro programador.

Con esta función sin efecto colateral, nos damos cuenta de que los datos se manejan sin ser modificados, es decir, inmutables, los parámetros person and name nunca fueron cambiados.

Funciones de alto nivel y currificadas

Una función de alto nivel es una función que implementa al menos una de las opciones siguientes:

  • Recibir como parámetro una o más funciones
  • Regresar como resultado una función

Un ejemplo muy común usado en nuestro navegador web es agregar escuchadores de eventos:

<button id="boton">Soy un botón</button>
const boton = document.querySelector('#boton');
boton.addEventListener('click', functions () {
  alert('Click sobre el boton');
});

En el código pasamos como segundo parámetro del método addEventListener una función anónima (sin nombre) que mostrará un alerta al dar click sobre un botón con id igual a ‘botón’. Dado que pasamos por parámetro una función, entonces se dice que es una función de alto nivel.

Otro ejemplo de función de alto nivel lo podemos observar en los métodos de arreglos en Javascript, el código de abajo toma un arreglo de números y crea otro arreglo con los valores aumentados al doble.

See the Pen Funciones de alto nivel by Jaime Cervantes Velasco (@jaime_cervantes_ve) on CodePen.

The function map retorna un nuevo arreglo, no cambia el arreglo original, por lo que decimos que no existe un efecto colateral.

Las funciones currificadas son funciones de alto nivel que como resultado regresan otra función, de tal manera que el acto de currificar es convertir una función de más de un parámetro en dos o más funciones que reciben parcialmente esos parámetros en dos o más invocaciones currificadas.

See the Pen Funciones de alto nivel y funciones currificadas by Jaime Cervantes Velasco (@jaime_cervantes_ve) on CodePen.

Las funciones flecha o arrow functions nos permiten acceder al contexto de los parámetros, es por eso que seguimos teniendo acceso al parámetro to de la primera invocación de summaryCurry. De esta manera cuando se les define un valor, una arrow function puede ver ese valor. Para lograr lo mismo sin funciones flecha se debe utilizar la variable arguments que existe como variable local dentro de todas las funciones en JavaScript. Para mantener las cosas simples, de momento no veremos como hacerlo con arguments.

Función recursiva

Para crear una función recursiva, primero se define un caso base, luego a través de la división del problema en pedazos más pequeños se encuentra un patrón, este patrón llamado caso recursivo se repite muchas veces, es aquí donde la función se llama así misma y acumula los resultados, la ejecución se detiene hasta llegar a su caso base.

  1. El caso base, el cual permite detener la ejecución de subsecuentes invocaciones de la función recursiva.
  2. El caso recursivo, el cual permite que una función se llame a sí misma hasta llegar al caso base.

El factorial de un número positivo es la multiplicación de ese número por el número inmediato menor y así sucesivamente hasta llegar al número 1, su notación es n!, donde n es un número positivo. Por ejemplo el factorial de 5 is 120, 5! = 5 x 4 x 3 x 2 x 1 = 120.

// caso base:
1! = 1 = 1
// caso recursivo, ejemplos:
2! = 2 x 1 = 2 x 1!
3! = 3 x 2 x 1 = 3 x 2!
4! = 4 x 3 x 2 x 1 = 4 x 3!
5! = 5 x 4 x 3 x 2 x 1 = 5 x 4!

Con estos datos, podemos crear nuestra formula factorial(n) = n * factorial(n-1), lo cual seria nuestro caso recursivo, pero debemos de añadir nuestro caso base para que se detenga, cuando n=1 debemos obtener como resultado 1.

Veamos como quedaría nuestra función recursiva en javascript:

See the Pen Funciones recursivas by Jaime Cervantes Velasco (@jaime_cervantes_ve) on CodePen.

Con esto cubrimos las cualidades principales de la programación funcional, pero recuerda, lo más importante es que NO existen efectos colaterales.

Patrón de diseño observador en Javascript

Patrón de diseño observador en Javascript

¿Qué es el patrón de diseño observador?

El patrón de diseño observador, define una dependencia de uno a muchos objetos de tal manera que cuando un objeto cambio de estado, todos sus dependientes son notificados y actualizados automáticamente

Del libro “Design patterns: elements of reusable object-oriented software”

Si aún no sabes que es un patrón de diseño, revisa primero esta publicación sobre patrones de diseño.

Si has utilizado eventos del navegador, como escuchar el evento click sobre un botón, ahí estás utilizando el patrón observador, tu función callback es tu objeto observador y el botón es el sujeto, tu función callback esta interesada en la actividad de dar click sobre el botón.

Se compone de un Sujeto y uno o más Observadores. Veamos el diagrama tomado del libro Design Patterns: Elements of reusable Object-Oriented software:

Patrón de diseño observador
Patrón de diseño observador

He Sujeto está compuesto por las siguientes métodos importantes que usaremos en nuestro código javascript:

  • Una colección de observers
  • Método attach()
  • Método detach()
  • Método notify()

Normalmente un Observador contiene un método update() que el Sujeto utiliza.

Para tener más claro esto, vamos a ver dos ejemplos del patrón observador, el primero será el Observador puro y el segundo en su modo Publicador/Suscriptor.

Simplificando el observador

Simplificando el diagrama anterior, el patrón observador funciona así:

Patrón de diseño observador simplificado
Patrón de diseño observador simplificado

Juega con el ejemplo de abajo, y agrega nuevos checkbox, si has agregado más de un nuevo checkbox, podemos notar que cuando damos click en el checkbox ‘Seleccionar‘ todos los demás checkbox nuevos se enteran de esa actividad y se actualizan automáticamente.

Todo esto sin necesidad de estar al pendiente de que el checkbox ‘seleccionar‘ ha cambiado su estado, el encargado de notificar del cambio es el Sujeto y solo si existe algún cambio. Esto es muy eficiente si tienes cientos o miles de checkbox observando ese cambio.

Si das click sobre uno de los checkbox, se ejecuta el método subject.detach(), entonces ese checkbox ya no es un observador, por lo que si ahora activas y desactivas el checkbox seleccionar nunca es notificado sobre el cambio.

Publicador/suscriptor simple

El patrón de diseño publicador/suscriptor es una variación del observador, en este modo el suscriptor u observador se suscribe a una actividad o evento del publicador o sujeto.

He publicador notifica a todos los objetos suscritos cuando el evento al que están interesados se dispara o publica.

He publicador está compuesto por las siguientes métodos importantes que usaremos en nuestro código javascript:

  • Una colección de observers either subscribers
  • Método subscribe() either attach()
  • Método unsubscribe() either detach()
  • Método publish() either notify()

Aquí dejo el diagrama simple de como funciona esta versión:

Patrón de diseño publicador/suscriptor simplificado
Patrón de diseño publicador/suscriptor simplificado

He publicador/suscriptor se parece más a los eventos del DOM y a eventos personalizados, pero no deja de ser el patrón de diseño Observador. Ademas, como observadores, podemos suscribirnos a más de una actividad o evento.

En el ejemplo, el método suscribe agrega la función observadora, esta última se ejecuta cuando la actividad click es publicada.

publisherSeleccionar.subscribe('check', subscriberCheckbox.update, subscriberCheckbox);

En conclusión, el patrón de diseño observador es muy útil, se puede modificar o adecuarlo a ciertas necesidades, un ejemplo es la variacion publicador/suscriptor. Se usa en:

  • ReactveX.
  • Librerias y frameworks de componentes web tales como angular, react, lit, vue, svelte utilizan este patrón para su bindeo de datos.
  • Navegadores web cuando usamos eventos
  • Node.js cuando utilizamos EventEmitter al recibir una petición a nuestro servidor o al leer un archivo del disco duro.
  • Flux y redux para manejar cambios en el estado de nuestra aplicación.
¿Cómo crear un servidor web en 5 minutos con Node.js?

¿Cómo crear un servidor web en 5 minutos con Node.js?

Para crear un servidor web en node.js, primero, ¿Qué es node.js?, tomando la definición del sitio oficial, Node.js® es un entorno de ejecución para JavaScript construido con el motor de JavaScript V8 de Chrome. Node.js usa un modelo de operaciones E/S sin bloqueo y orientado a eventos, que lo hace liviano y eficiente. El ecosistema de paquetes de Node.js, npm, es el ecosistema más grande de librerías de código abierto en el mundo.

Vamos a describir la parte que nos interesa, Node.js es un programa, V8 es un motor de javascript de código abierto creado por Google, por lo que también lo hace un programa, V8 está escrito en C++, y la tarea de V8 es tomar código Javascript y convertirlo a código máquina (compilar código), pero lo que lo hace especial para nuestros fines es que puede ser embebido dentro de otros programas, lo que permite que V8 esté embebido en Node.js, V8 por así decirlo es el punto de partida para toda la funcionalidad de Node.js.

Node.js también está escrito en C++ y utiliza la API de V8 para agregarle características y funcionalidades nuevas a Javascript. Estas nuevas funcionalidades permiten tener acceso al sistema de archivos y carpetas, nos permite crear un servidor TCP y http, además de acceso a POSIX, o sea, a toda la funcionalidad del sistema operativo donde se encuentre instalado.

Node.js proporciona la sintaxis Javascript para crear programas que tengan acceso a las características del sistema operativo donde sé está ejecutando.

Con esto podemos razonar que con Node.js podemos crear un servidor web, para crearlo, vamos a utilizar NPM (Node Package Manager) y express.js un frawework web.

Vamos a crear una nueva carpeta llamada mi-servidor-web, luego accede a esta carpeta con:

$ cd mi-servidor-web

Ahora vamos a iniciar el proyecto utilizando el siguiente comando:

$ npm init

La línea de comandos nos pedirá algunos datos, puedes dar “enter” a todos si quieres, te muestro un ejemplo:

Press ^C at any time to quit.
package name: (mi-servidor-web)
version: (1.0.0)
description: Mi primer servidor web
entry point: (index.js)
test command:
git repository:
keywords:
author: Jaime Cervantes<James.cervantes.ve@gmail.com>
license: (ISC)
About to write to /home/James/develop/node.js/mi-servidor-web/package.json:
{
  "name": "mi-servidor-web",
  "version": "1.0.0",
  "description": "Mi primer servidor web",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Jaime Cervantes <jaime.cervantes.ve@gmail.com>",
  "license": "ISC"
}
Is this ok? (yes)

npm init nos genera un archivo package.json:

{
  "name": "mi-servidor-web",
  "version": "1.0.0",
  "description": "Mi primer servidor web",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Jaime Cervantes <jaime.cervantes.ve@gmail.com>",
  "license": "ISC"
}

Este archivo contiene la información anteriormente proporcionada y además se encarga de controlar los paquetes que instalamos para nuestro proyecto. Por ejemplo, para poder crear nuestro servidor rápidamente, vamos a instalar un paquete llamado express.js de la siguiente manera:

$ npm install express --save

Este comando instala express.js y además actualiza nuestro archivo package.json gracias al parámetro --save en la propiedad dependencies:

{
  "name": "mi-servidor-web",
  "version": "1.0.0",
  "description": "Mi primer servidor web",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Jaime Cervantes <jaime.cervantes.ve@gmail.com>",
  "license": "ISC",
  "dependencies": {
    "express": "^4.16.2"
  }
}

Ya teniendo express instalado, vamos a crear nuestro servidor web creando el archivo  ./mi-servidor-web/index.js:

const express = require('express');
const app = express();
app.use(express.static(__dirname + '/public/'));
app.listen('3000', functions() {
  console.log('Servidor web escuchando en el puerto 3000');
});

Hay una parte importante que nos permitirá ver el funcionamiento de nuestro servidor web:

app.use(express.static(__dirname + '/public/'));

Esta línea le indica a nuestro servidor que cuando un usuario haga una petición de archivos estáticos, por ejemplo, http://localhost:300/index.html enviará como respuesta el contenido de ./public/index.html.

Vamos a crear la carpeta public y el archivo index.html con el editor de nuestro preferencia o en línea de comandos si lo deseas. Agregamos el siguiente contenido a nuestro archivo index.html:

<!DOCTYPE html>
<html lang="is">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Mi primer servidor web</title>
</head>
<body>
  <h1>HOLA, mi primer servidor web</h1>
</body>
</html>

Para ejecutar nuestro servidor nos posicionamos dentro de nuestra carpeta mi-servidor-web y ejecutamos el siguiente comando:

$ node index.js;

Veremos este mensaje en nuestra consola:

Servidor web escuchando en el puerto 3000

Por último abrimos nuestro navegador web y obtendremos nuestro index.html como la imagen de abajo, utilizando http://localhost:3000 either http://localhost:3000/index.html:

en_USEN