Monday, September 7, 2015

Máquinas de estado para JAVA

Manejar los estados de los objetos en un entorno multi-thread, orientado a eventos, es duro. Especialmente si este evento puede provocar diferentes acciones dependiendo del estado sobre el que se aplique.

Quizás sea más fácil entenderlo con un problema concreto. Empecé a pensar sobre este problema cuando desarrollaba protocolos en tiempo real para voz. En concreto, si miramos la RFC sobre SIP https://www.ietf.org/rfc/rfc3261.txt, una A SIP INVITE server transaction tendría una pinta como sigue:


                               |INVITE
                               |pass INV to TU
            INVITE             V send 100 if TU won't in 200ms
            send response+-----------+
                +--------|           |--------+101-199 from TU
                |        | Proceeding|        |send response
                +------->|           |<-------+
                         |           |          Transport Err.
                         |           |          Inform TU
                         |           |--------------->+
                         +-----------+                |
            300-699 from TU |     |2xx from TU        |
            send response   |     |send response      |
                            |     +------------------>+
                            |                         |
            INVITE          V          Timer G fires  |
            send response+-----------+ send response  |
                +--------|           |--------+       |
                |        | Completed |        |       |
                +------->|           |<-------+       |
                         +-----------+                |
                            |     |                   |
                        ACK |     |                   |
                        -   |     +------------------>+
                            |        Timer H fires    |
                            V        or Transport Err.|
                         +-----------+  Inform TU     |
                         |           |                |
                         | Confirmed |                |
                         |           |                |
                         +-----------+                |
                               |                      |
                               |Timer I fires         |
                               |-                     |
                               |                      |
                               V                      |
                         +-----------+                |
                         |           |                |
                         | Terminated|<---------------+
                         |           |
                         +-----------+

Si no das con una solución fácil para implementar esta máquina de estados, acabarás teniendo un código: difícil de escribir, difícil de mantener, error-prone, difícil de probar y imposible de tracear. El signo que estás en una situación similar es que tienes un montón de if/elsesynchronized y y te has pasado 2 días intentando encontrar cómo has podido entrar en un estado que no tenías previsto.

Por tanto, si te has encontrado con este problema, deberías mirar mi solución. Acabo de finalizar una nueva iteración sobre el código y estoy muy satisfecho del resultado: https://bitbucket.org/xferro/sicoris-statemachine . Hay un SNAPSHOT disponible si quieres empezar a probar.

Cualquier comentario es bienvenido! Espero que lo disfrutéis!

No comments:

Post a Comment

State machines in JS

You can read in previous blog posts the reasoning behind state machines: they simplify and unify the way we define states and transitions i...