DEV Community

Marcelo Andrade R.
Marcelo Andrade R.

Posted on • Originally published at marceloandrader.github.io

Máquinas de estados finitos

Una cosa que aprendí luego de cometer el mismo error varias veces en proyectos pasados es dejar de usar booleans en los diseños de las tablas de la base de datos. Estos te dan cierta facilidad al inicio pero son muy difícil de usarlos a futuro. Por ejemplo una tabla usuarios con el campo estado con valores true es activo y false es inactivo parece muy inofensiva; el problema viene cuando queremos agregar un tercer estado como por ejemplo reseteando para identificar que usuarios están reseteando el password y la solución más fácil en ese momento es agregar un nuevo campo llamado reseteando como boolean. Pero cuando quieres hacer una consulta a esa tabla de los usuarios activos, ahora tienes que verificar que reseteando también sea false. Y esto pasa en muchos otros procesos, como facturas, documentación, etc.

Muchos de los procesos del negocio casi siempre tienen un flujo de trabajo asociado, y los estados no son blanco o negro, la solución que ha funcionado para mí en ya algunos proyectos, es usar máquinas de estados finitos o FSM por sus siglas en inglés.

Existen muchas librerías que permiten usar una FSM en diferentes lenguajes de programación. En el caso de PHP la que uso personalmente es: yohang/finite tiene un respetable número de descargas en packagist y es agnóstica al framework, la he usado con laravel, phalcon y symfony sin ningún problema.

En una FSM se define una configuración para una entidad, esta debe tener estados, transiciones y opcionalmente llamadas.

Estados (states) como su nombre lo indica son los posibles estados en los que un objeto de la entidad puede estar. En nuestro ejemplo de usuarios, este puede tener los siguiente estados: activo, inactivo, reseteando.

Transiciones (transitions) son las posibles acciones que pueden hacer que un objeto cambie de un estado a otro. En nuestro ejemplo las transiciones pueden ser activar que va de inactivo a activo, desactivar que va de activo a inactivo y resetear que va de inactivo o activo a reseteando y reestablecer que va de reseteando a activo.

Llamadas (callbacks) son funciones del objeto que se llaman cuando una transición se ejecuta, esto me ha sido útil por ejemplo para llevar un control de cambios en el objeto, cuándo se hizo la transición y quién la ejecutó.

Una vez realizada la configuración, el API para verificar que transiciones puede realizar el objeto son:

$user->getCurrentState(); // por ejemplo ‘activo’

$user->can(activar); // false porque está en estado activo solo puede ir a reseteando
$user->can(desactivar); // true si se puede realizar esta transición de acuerdo a la configuración

$user->apply(desactivar); // se realiza el cambio
$user->getCurrentState(); // ahora es ‘inactivo’

$user>getCurrentState()->getTransitions(); // muestra que posibles transiciones tiene disponible, en el caso de inactivo puede ir solo a ‘activar’
Enter fullscreen mode Exit fullscreen mode

Para mayor información la documentación de yohang/finite es muy completa.

Latest comments (0)