Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I really don't like state machines because if you need to add a new event, each of the states need to be updated to handle that event. If you add a new state, you have to figure out how to handle each of the transitions from other states. So as your states grow, the maintenance on the developer's side grows faster than linear.

Additionally, I find that I cannot understand how the program works without actually drawing out the state machine diagram if I come across it the first time, so there is a bit of a learning curve. It's also a nightmare to test because of all of the states that need to be tested.

So in summary, not a fan. Like recursion... if it feels natural then use it, but I don't go and try and turn stuff that isn't a SM into one or turn something that can be done as loops into recursive function for fun.



>I really don't like state machines because if you need to add a new event, each of the states need to be updated to handle that event. If you add a new state, you have to figure out how to handle each of the transitions from other states. So as your states grow, the maintenance on the developer's side grows faster than linear.

State machines have been designed to neatly capture and componentize exactly that.

Anything else is less explicit, and even more error prone.

That new even and those new transitions you've mentioned? You still need to handle them anyway -- only you do it in an informal manner without a SM.


For the life of me, I can't read your complaints as actual complaints, but endorsements of the idea.

I haven't done it, yet, but I am tempted to make everyone I work with draft out the state machine of everything we are working with in our systems. I'm half convinced the worst bugs we have, are when folks didn't realize that the change they were doing required modifications because of how far reaching they were in the state of the system.

I take a simple vending machine as a good thought exercise. If you are just changing the system that recognizes coins, you can easily localize your changes. If you are changing the system that accepts coins...


This.

How much of the anti-formalism attitude is about real difficulties of the method, and how much is about "I don't know this method, so it must be bad".

Code, regardless of what it does, is a state machine. That does not change whether you do it intentionally or not. And if you don't use state machine design tools to design them ... then your state machine becomes a huge mess with transitions going from everywhere to everywhere and very surprising connections in many places (and most/all of those will be bugs, bugs that no unit test ever is going to find).

Which seems to be acceptable for a lot of people.


Both of your concerns seem to be nicely addressed by statecharts (nesting to constrain relations + visualization): https://medium.freecodecamp.org/how-to-model-the-behavior-of...

(haven't used this yet)


> if you need to add a new event, each of the states need to be updated to handle that event

Depends on your formalism. I never use state machines of that form for exactly the reason you say. Rather, each state defines the conditions which cause a transition from it. Receiving an event in a state in which it is not expected (say, an I/O completion in a state which should not have outstanding I/O) is a straight-up hard error.


This idea of defining a hard error for a transition which makes no sense is a nice way to deal with the OPs problem. You must still explicitly handle the situation, but it minimizes the "unwind/undo" code.


I don't understand the issue very well... If you have a new event, you either have to handle it in the state machine or some other way. Any place where the event doesn't apply should cause an appropriate failure. Same with new states - you have to write those transitions in some way. You can use macros/abstractions/whatever for simplifying many cases. But none of that code really disappears when you don't use SM.


I think the concern is that the update is across the code -dispersed in the code base. But this only applies to legal events in all states else the default behavior should be invoked. If a new event that is legal in many states is created then you have to handle it everywhere anyway, and my experience that if then structures fill with bugs fast in this case


That faster than linear maintenance growth is exactly why you need SMs.

You don't need to test every scenario - only the critical positive/negative ones.

If you abstract out all the generic SM logic you can have a neat source file per SM that contains only the allowed transition mappings or do something like https://github.com/pluginaweek/state_machine where the transitions are contained behind methods.

My experience with recursion has been the reverse - the more recursion in use the less predictable the code behaves (at least initially) - but even just a little bit of SM usage can increase stability from the start and also forces you to think about all the states required.


What's wrong with drawing the state machine diagram? And generally, what's wrong with drawing your code structure?

You may be able to keep it all in your head when you write it the first time... try again when you're doing maintenance after 6 months of not touching it though.


> I really don't like state machines because if you need to add a new event, each of the states need to be updated to handle that event. If you add a new state, you have to figure out how to handle each of the transitions from other states

You still have to do all this without state machines, but likely in a less organized and harder to maintain way.


>I really don't like state machines because if you need to add a new event, each of the states need to be updated to handle that event

Depends but usually no. An event in a state which has no transition from it would be an error. The state becomes undefined and you produce a crash.

>If you add a new state, you have to figure out how to handle each of the transitions from other states.

Yes but only states that transition to this new state which is easily formalized.

>Additionally, I find that I cannot understand how the program works without actually drawing out the state machine diagram if I come across it the first time, so there is a bit of a learning curve

SM diagrams are fairly easy, they were mandatory course material in my second semester at university.

>It's also a nightmare to test because of all of the states that need to be tested.

In fact, the opposite is usually true. You can mathematically verify that your state machine will always behave exactly as expected or crash. The coffee machine won't dispense coffee and return the cash put in; the state machine in it does not allow it, even better, such a series of events becomes utterly impossible. Once the coffee has been dispensed, the machines has only one way forward: initial state.

Additionally, SMs allow you to verify that your specific implementation is the most optimal one. And if it isn't, you can easily derive it. And you can test if two independent SM implementations are equivalent to eachother with 100% certainty.

Sadly, since their state is very limited, they are usually not very useful once you want to do something that can't be expressed in a finite state machine (basically anything with threads, ever, to start with).




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: