views:

145

answers:

2

Hello, I'm getting in to a situation where I have several interacting widgets (on a web UI), all of whom can be in multiple different states, and whose behavior depends on others the others. I'm running in to situations where, for example, a set of data gets sorted twice, or the data gets displayed before it's sorted, rather than the other way around. It's a little bit of a wack-a-mole problem, where I think I've simplified things and gotten it working, only to find out I've broken things somewhere else.

I have functions that do things like:

widgetAFunction
  load data into widget B
  tell widget B to sort the data
  tell widget B to display the data

My love of code reuse makes me want to do something like write a loadData function in widget A that goes something like this:

widgetBLoadDataFunction
  update data
  sort the data
  refresh the view

So that all widgetA has to do is call one function on widgetB. But then there are cases where I just want to sort the data, without updating the data, so I write:

widgetBSortFunction
  sort the data
  refresh the view

And then maybe I want a filter function

widgetBFilterFunction filter the data refresh the view

And maybe I want to be update the data but not sort it, so I have

widgetBNoSortLoadDataFunction
  update data
  refresh the view

It doesn't seem that complex, but I wind up with these really long, very brittle chains of function calls, or a bunch of very similar calls. As Martin Fowler would say, the code is getting a little smelly.

So, what other alternatives do I have? I did something on a recent project where I did a state machine kind of thing, where I registered a bunch of functions with a set of conditions, or states which would trigger their execution. That worked somewhat well, and I'm thinking that approach might be good to use again.

Does anyone know what I'm talking about here, and even better, can anyone point me toward some patterns that will help me get my head around this better?

+3  A: 

What you need is a finite state machine implementation. Basically every finite state machine needs:

  • Events that the program responds to
  • States where the program waits between events
  • Transitions between states in response to events
  • Actions taken during transitions
  • Variables that hold values needed by actions between events

A good article from IBM teachs you a way of implementing it by means of Javascript.

Edit: Here is a FSM builder, so you don't have to build your own.

Fernando Miguélez
Thanks Fernando. Your response confirms the way I've been leaning.
morgancodes
Thanks for the FSM builder. I wish I'd realized how complicated this project was going to get when I started! I thought I could just slap it all together, but now, to do it right, I'm going to have to untangle a lot of spaghetti!
morgancodes
Many times we feel too optimistic about a project and don't realize how big and complex it has become until oneself is too far in the timeline because we usually tend to develop oversized and overgeneralized applications. That is a sin the perfectionist people like me tend to commit
Fernando Miguélez
That's not my particular sin. I don't have any fantasies about my code for this project being particularly reuasable. But I sure want it to be maintanable!
morgancodes
+1 for FMSs, Fernando :)
dwc
A: 

Fernando already mentioned FSMs, and gave good info and links. :)

In addition, I'll add that your classes should already incorporate enough state so that you're not worried about sorting twice, etc. I.e., widgetB.sort() should check if it's been sorted since last update and just return if so. There's practically no downside to doing this, and it can improve performance (and also guard consistency).

dwc