Live data from Hacker News

State Machines in Ruby: An Introduction

blog.appsignal.com

21–30 of 42 posts

Re: State Machines in Ruby: An Introduction

#21
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.

For sure, this isn't an indictment against state machines, my message was exactly to be careful when making the decision to use them. They fit a lot of workflows and I've also worked in environments where they were not at all a bottlenecks, and regardless of the performance bottleneck it wasn't hard to reason about or adjust which for a long time meant more than performance for that business.

I guess I could amend my statement to "be careful about which library or implementation of a state machine you go with"

Re: State Machines in Ruby: An Introduction

#22
A lot of the comments here are rails oriented and anti state machine. In the context of rails that may make sense, but I do a lot of non rails ruby, and non object oriented Dev style, and state machines are a great way to write solid systems where the allowed state and transitions are explicit and easy to reason with.

Re: State Machines in Ruby: An Introduction

#23

A lot of the comments here are rails oriented and anti state machine. In the context of rails that may make sense, but I do a lot of non rails ruby, and non object oriented Dev style, and state machines are a great way to write solid systems where the allowed state and transitions are explicit and easy to reason with.

Unfortunately almost everyone treats rails and Ruby as synonymous

Re: State Machines in Ruby: An Introduction

#24
I get how these state machine gems can sound like a great idea if what you need is taming some state changes that are just a little too much to handle by hand, but they can also delay the realization that you're doing something wrong.

State changes are hard and most involve more than object, there are usually associations that need to be taken care of, validated or maybe also transitioned to a different state, there can be a myriad of conditions and things can go wrong at any moment. And I feel that being able to define state transitions this easily, almost as an afterthought, with a simple DSL, doesn't do all this justice (just like those friendly before/after callbacks can turn into massive spaghetti abominations).

The way I do it is that any state transition more complex than checking two attributes and updating a third one is an object. Transitioning a Campaign object from :reservation to :order? That's a new PORO called CampaignOrder, with a #perform! public method or something. All the conditions, assumptions and side effects have their private methods (check_showings!, update_occupancy!). Passed a dirty record into something delicate? That's a raise, I want something clean and valid to work with. Is this something where we expect a dirty record? Go right ahead, we'll save it later in the transition, plus it will be documented right in the constructor. Does it need to raise? It will. Custom error messages on any record? Right here in this private method. Does any model need to know anything about the state transition or own any related code? Nope.

Re: State Machines in Ruby: An Introduction

#25

A lot of the comments here are rails oriented and anti state machine. In the context of rails that may make sense, but I do a lot of non rails ruby, and non object oriented Dev style, and state machines are a great way to write solid systems where the allowed state and transitions are explicit and easy to reason with.

Would you mind sharing a little example of what you mean by non-OOP Ruby code with state machines?

Re: State Machines in Ruby: An Introduction

#26
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…

Sounds like a confused author or potentially an implementation-driven architectural decision (eg. regulatory or policy requirement, direct map from exposed states of a prior implementation that had been black box reverse engineered, etc.). AFAIK the normal way to implement state machines in embedded since ages yore is to use interlocking networks of state machines per isolate subsystem. At least, that's what I do and that's what seems natural in C and assembly where concerns such as manual memory management, code re-use and programmer cognitive load would all tend toward such an architecture. What was the hardware?

Re: State Machines in Ruby: An Introduction

#27
post #15

Earlier quoted context omitted.

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…

Sounds like a confused author or potentially an implementation-driven architectural decision (eg. regulatory or policy requirement, direct map from exposed states of a prior implementation that had been black box reverse engineered, etc.). AFAIK the normal way to implement state machines in embedded since ages yore is to use interlocking networks of state machines per isolate subsystem. At least, that's what I do and…

Was Coldfire + IAR. The design was driven entirely by idiocy and showboating. I was hired just to limp it along a bit further while they spun a new board and software as the MCU was obsolete anyway.

Re: State Machines in Ruby: An Introduction

#28

A lot of the comments here are rails oriented and anti state machine. In the context of rails that may make sense, but I do a lot of non rails ruby, and non object oriented Dev style, and state machines are a great way to write solid systems where the allowed state and transitions are explicit and easy to reason with.

Honestly state machines are fantastic in Rails too. My last company built Statesman (https://github.com/gocardless/statesman/) and being able to lean on it to prevent you getting into invalid states is fantastic. You also get the bonus of tracking the history of states your resources went through (which is especially useful when you're dealing with payments).

At some point you'll have to think about query performance on the state transition table, but it'll go further than you think and is firmly in the realm of problems of success.

Re: State Machines in Ruby: An Introduction

#29

A lot of the comments here are rails oriented and anti state machine. In the context of rails that may make sense, but I do a lot of non rails ruby, and non object oriented Dev style, and state machines are a great way to write solid systems where the allowed state and transitions are explicit and easy to reason with.

A pretty big +1 to this. My team (at Crunchy Data building Crunchy Bridge[1]) and similar teams at prior Citus Data and Heroku did a lot of Ruby and a lot of state machines. In all cases it was actually less Rails, but that may be because the team really prefers sequel as the ORM to ActiveRecord, though Rails does a bunch that doesn't really apply to such a workflow. We wrote about some of how we used state machines to power our database as a service and the full control plane previously[2]. Another big piece of the approach and stack that helps today is leveraging Sorbet[3] and our approach to test coverage, we probably should blog a little more on some of this but it helps quite a bit.

[1] - https://www.crunchydata.com/products/crunchy-bridge

[2] - https://www.citusdata.com/blog/2016/08/12/state-machines-to-...

[3] - https://brandur.org/fragments/large-scale-ruby-refactoring

Re: State Machines in Ruby: An Introduction

#30

A lot of the comments here are rails oriented and anti state machine. In the context of rails that may make sense, but I do a lot of non rails ruby, and non object oriented Dev style, and state machines are a great way to write solid systems where the allowed state and transitions are explicit and easy to reason with.

Redux is basically a state machine.
Post reply on HN