The state machine

After adding a lot of features and conditionals to the OTempo service, and after almost going mad to keep a legible and safe code, I decided to use the state pattern.
The fact is that OTempo needs to handle a lot of cases when updating station predictions:

  • The activity may be starting and needing just one station, but with really high priority.
  • The widget may be updating and needing its own station, not so fast.
  • The service may be updating all the stations to have them cached.
  • Internet may be enabled, or disabled.
  • The user may have background app updates enabled, or disabled
  • An update cycle may have ended, or not. And meanwhile the user may terminate the service.
  • Internet may return from an off state.
All of these situations and needs make it really difficult to keep a clean and safe service loop. This is why I modelled the service following the state pattern.
The fundamental idea is actually very simple, just follow these steps (if you already know the state pattern, skip this):
  • Make a list of all the situations in which your service has a very different behaviour.
  • Now make a list of all the events that may provoke a change from one situation to another.
  • Now, for each state, think what should happen if any of these events are fired. Some events will transition to another state, some other should not change state.
  • Write this diagram into paper and paste it in a visible place.
Now you are ready to code:
  • Create a State interface, with one method for each possible event. These methods should receive the context (the service) and any other data that describing the event itself.
  • Add a State attribute to the service (current state)
  • Create a concrete State class for each of the mentioned situations.
  • Implement the interface methods on these classes. If some event should trigger a state change, then ask the service to transition.
  • Add logging code to the service method that handles transitions, to be able to debug.
  • Reimplement the service loop as a call to the current state (ie, update())
  • Delegate any event that you detect in the service to the current state.
Of course, this way of doing things, as usual with design patterns, is slightly slower, as it adds some extra method calls, but it will simplify a lot the code, as you will be able to isolate different behaviours into different classes. Debugging now becomes just checking in what state the machine is, and then how is it responding to the events.
Anuncios

Acerca de Rubén L.

Software Engineer
Esta entrada fue publicada en android, English y etiquetada , , , . Guarda el enlace permanente.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s