Máquinas de estado

Ayer me preguntaban cómo solucionar un problema de flujos de datos y procesos. Lo primero que se me vino a la cabeza fue: Eso es una máquina de estados!

Imaginemos por un momento un diagrama de flujos clásicos. Donde tenemos flechas que indican dirección y conectan diferentes elementos. Estos elementos representan acciones y, desde el inicio al final, los datos fluyen dejando que cada uno de esas acciones hagan algo sobre los mismos antes de pasarlos al siguiente componente.

Adicionalmente, era necesario saber que elemento estaba realizando qué y que dicho elemento conociera cualquier otro elemento que pudiese estar conectado a este para poder enviar los datos hacia ellos.

Por supuesto, hay muchas formas de implementar una máquina de estados. Un simple switch y algunas líneas de código ya son una máquina de estados pero, por supuesto, hay que hacerlo un poco más difícil 🙂

Si aún te preguntas dónde se usan estas máquinas de estado… bueno, son comunes en el desarrollo de videojuegos. Por ejemplo, cuando un personaje está realizando una acción, lo normal es que esa acción sea un estado del personaje. Saltar, correr, caminar, son estados del objeto y solo uno puede ejecutarse en un momento particular. Luego, solo se puede ir de caminar a correr como posible flujo y no de correr a agacharse sin primero caminar (Por dar un ejemplo).

El código

El código necesitaba hacerse en JavaScript (Lenguaje que amo) y debía contemplarse la posibilidad de no tener clases base. Esto quiere decir que, por ejemplo, para un nodo de la máquina de estado pueda conocer un nodo anterior o un nodo siguiente, lo lógico sería tener una clase base que implementase estos métodos y así reusarlos en cada nueva instancia de un nodo.

La máquina

    var stateMachine = {
        currentState: null,
        next: function() {
            if (this.currentState._next !== null) {
                this.currentState = this.currentState._next;
                this.currentState.process.call(this);    
            }
        },
        prev: function() {
            if (this.currentState._prev !== null) {
                this.currentState = this.currentState._prev;
                this.currentState.process.call(this);    
            }
        }
    };

La maquina de estados solo conoce el nodo o acción actual y provee dos funciones para poder moverse hacia adelante o hacia atrás (Más movimientos dependerán de nuestras necesidades).

El nodo

    var step = (function() {

        var s = function (configuration) {
            this._configuration = configuration;
            this._next = null;
            this._prev = null;
        };

        s.prototype.process = function () { };

        return s;
    }());

Una definición de “clase” clásica. Teniendo un constructor y una función que se usará para ejecutar las acciones del nodo.

Las acciones

    var firstStepFunction = function() {
        console.log(this.currentState._configuration.text);
        this.next();
    }

    var secondStepFunction = function() {
        console.log(this.currentState._configuration.text);
        this.next();
    }

    var lastStepFunction = function() {
        console.log(this.currentState._configuration.text);
        this.next();
    }

Cada función representa una acción particular para un nodo particular.

Uniendo todo

    var step1 = new step({text: "step 1"});
    step1.process = firstStepFunction;

    var step2 = new step({text: "step 2"});
    step2.process = secondStepFunction;

    var step3 = new step({text: "step 3"});
    step3.process = lastStepFunction;

    step1._next = step2;
    step2._prev = step1;
    step2._next = step3;
    step3._prev = step2;

    stateMachine.currentState = step1;
    step1.process.call(stateMachine);

En este caso, se puede crear un nuevo nodo, asociarle una acción en particular y sus siguientes o previos nodos en la cadena de ejecución.

La línea final dispara la ejecución del primer nodo, el cual se encargará de llamar a sus siguiente nodo y ejecutar todo el flujo.

En resumen. Este tipo de máquinas nos pueden ser de mucha utilidad ahorrándonos condificiones anidades y código poco mantenible. También, poder conocer el estado de un proceso. Aislar los mismos en diferentes unidades especializadas, entre otros beneficios varios.

Anuncios

Interceptores y JavaScript

Primero que nada decir que estoy armando este post desde el celular. Lo que puede llevar a horrendos errores gramaticales y ortográficos. Y se debe a que aún no cuento con acceso a internet (Larga historia).

Segundo, el tema de este post. Básicamente hace bastante tiempo venía pensado cómo poder simular algo cercano a AOP pero en Javascript. Claro, no todo el compendio de AOP, o no rigurosamente, pero algo.

Ese algo, para este caso se limitaba a interceptores en las diferentes llamadas a funciones. Como en el caso de lenguajes como C# o Java, dónde es posible decorar una función para obtener un comportamiento previo a la ejecución de la misma.

Un ejemplo es el clásico caso de los controllers de un proyecto MVC. Algo como:

[HttpPost]
public void HacerAlgo() ...

En este caso el decorador hace que dicha función sea ejecutada solo si se produce una llamada de tipo POST.

Por supuesto, esto no es necesariamente AOP. Pero por lo menos nos permite encapsular comportamiento por fuera de la función y esperar el mismo cada vez que decoramos una función.

Entonces el siguiente paso a pensar es: Qué pasaría si quiero escribir un log antes de que la función sea llamada. O mejor aún: Qué pasa si quiero que un set de reglas se ejecute antes de entrar a la función, como por ejemplo, validar que los campos no estén vacios.

[Validar(variable="nombre", empty=false, throwException=true)]
public void MiFuncion(string nombre) ...

En este caso si al llamarse la función la variable nombre se encuentra vacía, entoces se produce una excepción.

Nuevamente, esto no es AOP real, pero para el ejemplo pensemos que es una aproximación.

El punto a evaluar es que podemos obtener conportamiento repetible adicional a nuestra función sin tener que repetir el mismo código dentro del cuerpo de la misma. Y si bien no nos liberamos del acoplamiento, si podemos tener algunos beneficios próximos al mismo.

Tal vez en el caso de AOP, al momento de compilar deberíamos obtener nuevas funciones con dicho código incorporado en ellas. En el ejemplo de C#, por el contrario, necesitamos de un observador que controle el comportamiento de los objetos, clases y funciones, use algún modelo de reflection e inyecte comportamiento mientras las funciones son llamadas.

Esto quiere decir que la estructura de la función no muta en base a nuestras decoraciones.

¿Pero qué pasa con Javascript?

Bueno, resulta un poco más difícil ya que los métodos reflectivos que tenemos disponibles (Hasta donde yo se) no nos permiten decorar y leer esas decoraciones. (Usuarios de React y Redux y demases abstenerse, eso tiene una capita adicional)

Pero sí podemos recrear una función de forma dinámica. Esto es: Tomar la función existente y sobre escribirla a nuestro gusto en tiempo de ejecución.

Toda esta cantaleta para llegar a esto.

En la imagen se puede ver un objeto en el que tenemos una función que recibe dos parámetros. El primero llamado p y el segundo __interceptor. Y es el segundo el que me interesa.

¿Que pasaría si este dictaminará que dicha función, al ser llamada, debiera primero ejecutar alguna acción definida en ese interceptor y luego, si todo sale bien, seguir el camino esperado?

En la imagen lo que terminé armando.

Básicamente la posibilidad de definir dicho interceptor (o varios en cadena). Que modifican el comportamiento original de la función. La sobre escriben y la dejan lista para ser usada con el nuevo código inyectado.

Como vemos en la consola. Al llamar a las diferentes funciones, antes, los interceptores son ejecutados para luego dar paso al código de las funciones originales.

Algunas aclaraciones.

El código es algo largo como para pegarlo en este mismo post por lo que trataré de colocarlo en GitHub en breve.

No lo hice en ES6 o TypeScript por falta de compiladores.

Seguro hay mejores implementaciones. Angular tiene cosas así. PrototypeJs creo que también. Pero ya saben… Es divertido hacerlas uno mismo.

Por último, una vez suba el código aprovecharé para armar otro post explicando algunas partes.

Espero que les resulte interesante 😛


A repartir para que tengan

Por culpa de un compañero de trabajo he caído en la adicción de hacer katas de código en CodeWars. Por supuesto, en uno de mis lenguajes favoritos: JavaScript.

Lo bueno: He arrancado humildemente por los katas de nivel más bajo, con el tino de crear soluciones que están dentro de las que se consideran las más adecuadas (?), o por lo menos, las que se parecen más a las mejor valoradas (Puntito para el ego).

Lo malo: … en realidad no hay nada malo. Se aprende, se ejercita la mente y se aprende (Eso creo que ya lo dije).

Lo que sí resulta importante es que la mayoría de las soluciones, aquellas más valoradas, están siendo hechas en ECMA6. De a poco nuestro viejo y querido JavaScript ha crecido y se hizo adulto. Y por supuesto, nosotros necesitamos crecer con este.

Con lo que me encontré en uno de los katas (Y que claramente ni sabía que estaba por ahí) fue con los (Sí, tres puntos). Un nuevo operador, el operador de dispersión (Calculo que podemos llamarlo de esa forma).

Este operador permite tomar una colección de valores y asignarlos o “traspasarlo” a una lista independiente de valores o variables. De esta forma, si tenemos una función con muchos parámetros, es posible tomar un array y enviarlo como parámetro para que cada uno de los índices del mismo sean asignados a cada una de las variables de la firma (A alguien le suena apply?).

En TypeScript:

let f = (v: any, r: any) => {
  console.log(v, r);
};

var args = ['hola','mundo'];
f(...args);

En el código, cada índice del array irá a parar a cada una de las variables (v y r). Existen otras aplicaciones, pero para eso es cuestión de dejar volar la mente.


Dibujando X en la pantalla

Estoy escribiendo unos artículos que saldrán publicados en fascículos, dentro de muy poco, para aprender a programar desde la óptica de un desarrollador Full Stack (Aquel que puede programar tanto en el cliente como en el servidor). Mientras escribía, me distraje y se me ocurrió hacer un graficador de algunas funciones simples. Si a alguien le interesa, lo dejo por acá.

var canvas = document.createElement('canvas');
canvas.width = 800;
canvas.height = 600;
document.getElementsByTagName('body')[0].appendChild(canvas);
var ctx = canvas.getContext('2d');

function dibujar(f) {
  ctx.clearRect(0, 0, 800, 600);
  var p = 0;

  for (var i = 0; i < 800; i+=0.1) {
    var r = f(i);
    ctx.fillText('x', r[0], r[1]);
  }
}

Y estas son algunas funciones:

var periodo = 0;
var amplitud = 100;
var sobre_eje_y = 200;
var sobre_eje_x = 400;

function seno(tiempo) {
    periodo += 0.01;
    return [tiempo, (Math.sin(periodo) * amplitud) + sobre_eje_y];
}

capture

function coseno(x) {
    periodo += 0.01;
    return [(Math.cos(periodo) * amplitud) + sobre_eje_x, x];
}

capture

function circulo() {
    periodo += 0.1;
    return [(Math.cos(periodo) * amplitud) + sobre_eje_x, (Math.sin(periodo) * amplitud) + sobre_eje_y];
}

capture


Coding Dojo

highres_457780477El lunes hicimos un Coding Dojo de JavaScript. Algunos ejercicios para romper cabezas y pensar mejores formas de hacer código.

Un interesante ida y vuelta, con rotación frente al teclado de los asistentes.

El código quedó en el repositorio: https://github.com/MatiasIac/JsDojo


SINO y la Global Game Jam

capturePasó otra GGJ y con esta, según me han dicho, son 7 años seguidos participando. En esas furiosas 48 horas de código, ninguna hora de descanso y de ideas alocadas, siempre termina saliendo algún juego que nos divierte, a nosotros como programadores, y colateralmente, a los usuarios del mismo.

Después de 7 años, la evolución en los juegos que hacemos se nota. De tomarnos las 48 horas para hacer un runner, a tomarme 2 horas en hacer otro en la actualidad. De intentar agregar gráficos para suplir la falencia técnica, a enfocarnos en la mecánica del juego como elemento principal, incluso si este análisis nos consume la mayoría del tiempo.

Llegué tarde, no pude escuchar la consigna ni ver los videos introductorios, pero la cosa decía algo como: Ondas u olas (Waves).

Como siempre, corrieron muchas ideas, intercambiando con todos las diferentes posibilidades. Y como siempre, muy entrada la noche del primer día, no teníamos mucho. Aparecieron arduinos, gamepads, frameworks, motores de física. Probamos algunas ideas con Phaser, pero como en otras oportunidades, el framework y las diferentes implementaciones de los motores de física nos defraudaron. Era hora de arremangarse y codear todo (O casi todo).

wp_20170123_001 wp_20170123_002 wp_20170123_003

Muchas horas de ecuaciones más tarde… llegamos a lo que necesitábamos y por fin teníamos el núcleo del juego andando.

Sino parece simple, pero es un juego sustentado por la matemática. No solo para dibujar una onda en la pantalla sino por poder modificar esa onda y desplazarse por la misma. Entender como el tiempo, frecuencias, amplitudes y fases impactan en el cálculo y el estado de la onda. Un juego que, de alguna forma, nos recordó a RouteLoop, otro resultado de una GameJam donde las matemáticas eran la columna que lo sostenía todo.

Y como ya estábamos con el cerebro en funcionamiento, este juego también se llevó de premio un creador de mapas mediante imágenes.

map1 map2 map3 map4

 

 

Cada mapa, en vez de ser escrito en el código, es tomado desde una pequeña imagen y reconstruido en el juego. Si bien es una técnica bastante conocida, se suele pasar por alto. En mi caso fue un momento de nirvana cuando mi compañero de equipo me dijo: Leamos el mapa desde una imagen!

Simplemente mi cabeza explotó y se puso a trabajar en el código para que eso fuera realidad.

El resultado de todo esto se encuentra en GitHub: https://github.com/MatiasIac/Sino

Una Jam extraña, o diferente a otras, tal vez reflejo de esos 6 años de participación.


Evento en Córdoba – Coding Dojo de JavaScript

karate-computerComo muchos de estos eventos, aparecen, se discuten, y en menos de una hora ya tenemos fecha, lugar y temática.

El lunes que viene, a las 6:30 de la tarde haremos un Coding Dojo de JavaScript.

La idea surgió de Juan Gabardini (Un tipo de esos que transpiran conocimientos).

La idea de un dojo de código es plantear un problema o una serie de ejercicios para que los desarrolladores resuelvan. Mientras se meten las manos en el código, se comparten las posibles soluciones. Un moderador o posible guía (En esta oportunidad seré yo) intentará darle solución o contexto a las diferentes dudas.

En definitiva, un evento más que interesante. Pueden anotarse aquí: https://www.meetup.com/agiles-arg/events/237045139/