Live data from Hacker News

State Machines in Ruby: An Introduction

blog.appsignal.com

11–20 of 42 posts

Re: State Machines in Ruby: An Introduction

#11
post #4

Counterpoint: State machines in Ruby should be used sparingly, and only when necessary, because they start out quick and easy, but almost always grow into things that are big, ugly, and difficult to refactor or remove. Here are somebody's notes from a Railsconf talk that made this point, plus a link to the video: https://gist.github.com/benoittgt/05521e272e13c7b7c9c89eb4a9... But the short version is the takeaway quo…

Thanks for sharing this. For other people who are hovering over this and unsure if they want to watch a 40 minute video, it's time stamped and the two parts I found super valuable were the 'Anti-Pattern: Custom Methods' and the 'Anti-Pattern: State Machines' sections. The TL;DR there is it's alright to create a controller that manipulates a single field on a single model. If it is enough of a resource to expose it by a custom url (think update password) it is enough of a resource to get its own controller.

And going beyond that, to the state machine, if each state (or really, value of a particular field) is important enough to have it's own contextual validation, transition points, etc, then it's important enough to expose each state as a resource with it's own controller.

Super cool stuff and I've got some thinking to do about some side projects now.

Re: State Machines in Ruby: An Introduction

#12
post #7
post #3

I've seen a few large Rails codebases that included a state machine library like mentioned in the article. Every single one was worse because of it. It pushes the code down a path where hidden hooks run when magic methods are called. At this point in my career I'm just done with that type of "clever" code. The article starts with examples that just define the state machine by hand. This is a much better approach and…

Funny, I have spent a ton of time around Rails code where I dearly wished we had a state machine, because the alternative was an unorganized cluster of home-grown "state transition" glue without any consistent way of handling it, with all the weird-ass edge cases and split-brain BS that come with it.

I've been on the receiving and perpetuating end of state machines and it's painful to have to deal with one that started years before you got involved and easy to think that you can do better. I've got a modest one in a side project and due to it being a side project I touch it once every couple of weeks and already it is making me uncomfortable. And it's dirt simple and I wrote it!

There's a take on state machines in a railsconf talk further down in the thread and it seems like an awesome way to reap a lot of the benefits while keeping a grip on the complexity. Sometimes complexity can't be buried safely and you kind of need to frame it instead. I'd argue that state machines bury that complexity but breaking those states into ruby objects w/ their own validation frames and delineates them instead.

Re: State Machines in Ruby: An Introduction

#14
post #4

Counterpoint: State machines in Ruby should be used sparingly, and only when necessary, because they start out quick and easy, but almost always grow into things that are big, ugly, and difficult to refactor or remove. Here are somebody's notes from a Railsconf talk that made this point, plus a link to the video: https://gist.github.com/benoittgt/05521e272e13c7b7c9c89eb4a9... But the short version is the takeaway quo…

Indeed, a coworker at a previous job was fascinated/fixated with state machine patterns. After spending two weeks trying to force a process we were paired on into a state machine pattern and failing, I rewrote it in an afternoon without the state machine stuff.

It started out small and easy, when there were two states. A third state was manageable but to me already looked like it was going the wrong direction. The fourth state (out of IIRC 6) was never finished.

Re: State Machines in Ruby: An Introduction

#15
post #4

Counterpoint: State machines in Ruby should be used sparingly, and only when necessary, because they start out quick and easy, but almost always grow into things that are big, ugly, and difficult to refactor or remove. Here are somebody's notes from a Railsconf talk that made this point, plus a link to the video: https://gist.github.com/benoittgt/05521e272e13c7b7c9c89eb4a9... But the short version is the takeaway quo…

Of all the things I've seen in my time writing software I can qualify that some of the most fucked up things involved state machines. The worst of which was a 200 state hand written one in C for an embedded measurement system. There was no documentation, no comments and the states were numbered rather than named. The guy who wrote it originally was "anti RTOS" and had died after riding his motorbike recklessly leaving this shit for everyone to deal with.

It took me two weeks to do a trivial change because I had to reverse engineer a ton of it. And the only debugger I had was a couple of LEDs on the board I could wiggle on and off.

Re: State Machines in Ruby: An Introduction

#16

I worked at a business (in ruby) where the entire core logic of the app was a state machine, as an idea the thought was good, a state machine modeled order flows pretty well, but in practice it was very slow and the amount of side effects that had to be considered as the business grew just compounded this. It got to the point where this state machine approach was a real bottleneck and though I left before it was reso…

On the flip side, I've built several production apps with AASM or Workflow that made adapting to changing business logic a breeze. If you're given a flow-chart you can translate that 1-1 and when that chart changes it's easy to adjust.

It was also really easy to write tests for.

Re: State Machines in Ruby: An Introduction

#18
post #16

I worked at a business (in ruby) where the entire core logic of the app was a state machine, as an idea the thought was good, a state machine modeled order flows pretty well, but in practice it was very slow and the amount of side effects that had to be considered as the business grew just compounded this. It got to the point where this state machine approach was a real bottleneck and though I left before it was reso…

On the flip side, I've built several production apps with AASM or Workflow that made adapting to changing business logic a breeze. If you're given a flow-chart you can translate that 1-1 and when that chart changes it's easy to adjust. It was also really easy to write tests for.

This has been my experience as well with AWS Step Functions. Obviously your use case is critical to the architecture decision. For us it's made automating workflows a breeze.

Re: State Machines in Ruby: An Introduction

#19
post #15
post #4

Counterpoint: State machines in Ruby should be used sparingly, and only when necessary, because they start out quick and easy, but almost always grow into things that are big, ugly, and difficult to refactor or remove. Here are somebody's notes from a Railsconf talk that made this point, plus a link to the video: https://gist.github.com/benoittgt/05521e272e13c7b7c9c89eb4a9... But the short version is the takeaway quo…

Of all the things I've seen in my time writing software I can qualify that some of the most fucked up things involved state machines. The worst of which was a 200 state hand written one in C for an embedded measurement system. There was no documentation, no comments and the states were numbered rather than named. The guy who wrote it originally was "anti RTOS" and had died after riding his motorbike recklessly leavin…

Send this by mail to thedailywtf, would love to read the expanded version

Re: State Machines in Ruby: An Introduction

#20
post #7
post #3

I've seen a few large Rails codebases that included a state machine library like mentioned in the article. Every single one was worse because of it. It pushes the code down a path where hidden hooks run when magic methods are called. At this point in my career I'm just done with that type of "clever" code. The article starts with examples that just define the state machine by hand. This is a much better approach and…

Funny, I have spent a ton of time around Rails code where I dearly wished we had a state machine, because the alternative was an unorganized cluster of home-grown "state transition" glue without any consistent way of handling it, with all the weird-ass edge cases and split-brain BS that come with it.

The quip I like best for this is: “Any sufficiently complicated model class contains an ad-hoc, informally-specified, bug-ridden, slow implementation of half of a state machine.”

Lots of models I've encountered eschew being organized as state machines in favour of having "if salad" strewn throughout their code. That being said, refactoring to a simple state machine and trying to maintain it as such in perpetuity isn't always the correct solution.

Sometimes, a hierarchal state machine is needed, and if it is expressed as a simple state machine, it's just as messy.

Sometimes, a portion of it needs to be a state machine, and the right thing to do is to delegate some of the methods to a strategy that reflects the current state, but not all of them.

Sometimes, the whole thing is just too fat, and a state machine won't save it, the right thing to do is to get very aggressive about refactoring to a composite object.

Any time you have a big, messy model, it's very easy to write a blog post espousing a single solution, like this one:

http://raganwald.com/2018/02/23/forde.html

HN discussion: https://news.ycombinator.com/item?id=16468280

But the reality is that a big, messy model is always going to be some kind of problem, and unless you can break it down into parts, you're going to have a problem. A state machine is conceptually a way to break a big thing into parts based on its "state," but that's just one approach to factoring.

p.s. Another problem is that even if a simple state machine is the right answer, "rolling your own" usually isn't. Grab a well-tested and documented library already. This isn't your passion project, this is industrial programming. Rolling your own is one of the best ways to learn how state machines work. Once you've learned how, reach for a professional tool.

Post reply on HN