A Photo by Darren Hester from FreeImages

Managing states (or State Machines)

Ricardo Rachaus
The Arcane Programmer
7 min readMay 25, 2020

--

For my first topic, I will discuss state machines. It's a simple concept, but I see a lot of people don't know or understand. I have already talked about in this Cocoa Heads SP (it's in portuguese and focused on iOS). For this article I will take a more broad approach. All the code will be written in Swift, but its concepts is applied in any scenario (really, a lot of things can be represented as a state machine).

So, State Machines are a finite state automaton. But what the hell? Although looks like a complicated subject, it's very simple. Basically, everything has states. A simple example is a switch: you have turned on or off. Two states that can be represented in two values: 0 or 1, true or false. This is the simplest form of state control and manage states: a boolean value.

One of the most common use of states is very clear in circuit boards (and that's the reason of the cover). If you have ever study digital circuits and how it works, you already have seen state machines. This is the example of the switch.

A example of switch states

So, not scary at all right? Of course, this is the simplest state machine, and if you are more curious about state machines in circuits and computer theory, this article can help you understand more.

But when will we start the real programming examples? So let's dive in more daily programming examples:

The code from above shows a simple example of a switch. I didn't think in a more complex example because we all do it everyday in programming. It's usually a control flag that we use in ifs around the code to do something if true, otherwise do something else. Of course that boolean managing can be really a pain and with more booleans, we cause the infamous pyramid of doom (or Hadouken code) when we manage a lot of things with booleans in some code block.

And now that I have mentioned games, let's use it more, mainly because games it's the perfect example of states and state machines (if you doubt, search in Google for any character spritesheet and probably each row is a state of the character).

I already talked about using a boolean flag to control your states, but imagine something like Super Mario Bros. A simple game with simple mechanics: jump, run, and if you catch a flower, attack. With only a naive approach we have at least for flags: isJumping , isRunning , hasCatchFlower , isAttacking . But we have also when he died, when he is small, when catch a star… not much fun ahead right? (I don't know the original Super Mario Bros code, but probably they handled with a lot of flags since the original code is in Assembly 6502)

So, how we will handle all of those states? The next step is something not really new: enumerations. For those who don't know, enums (short for enumerations) is a feature in languages since C (can be even older, I don't know, but I think that quoting a language from the 70’s is enough for example). But then, what we do to use enums ?

A lot more of code than the previous example right? If this sound more complex, we are looking to a simplified version of a 1985 game. Imagine games like Megaman X or The Legend Of Zelda: A Link to the Past (give me chills just of thinking, but also a nice challenge 😉). For those who don't know these games, just a quick look at YouTube and you will find various gameplay videos.

The downside of this approach is that you need to handle with a lot of switch statements and can be really repetitive and painful to maintain. Also, you can mix a lot of responsibilities in just one place (I faked some methods that would contain the real logic, but the real world is not always this beautiful).

Okay, some may think "I don't make games, why will I use this?". If you're a frontend developer, probably you can use a these in: display content, loading and error. Or a button that has: pressed, highlight, normal. Don't sound like daily work? If you're a backend developer, this can be a status of a purchase in an e-commerce. Or even environments: develop, homolog, production. And like I said, everything can be modelled as states: message received, message send; wake, work, sleep; birth, life, death (☠️)… I think that it's not needed more examples, right?

After writing I noticed that a lot of my examples is 3 states based, but can be any N number of states, since N is a finite number. So yes, you can have a billion different states, but it doesn't look like something humans can handle (🤷).

And now what? It's just this? Now is everyone a "state master"? Actually there is still something to show: State Pattern. However, isn’t everything above a State Pattern? Or better, different States Patterns? Yes, but there is one more that is based in OOP, but we will take a different approach and make POP (not the music style, but Protocol Oriented Programming). POP is something in the roots of Swift, and for those who don't understand, basically are something like Java/Kotlin Interfaces or C++ Abstract Classes (actually there is some differences, but it's out of scope from this article).

If you're an iOS developer, there is a chance that you've heard about GameplayKit. In this Apple framework, there is already a full State Pattern implemented and free to use (also, it's the topic of my talk from the beginning of this text) called GKStateMachine. If you are curious, I have my own implementation of the GKStateMachine. If you aren't an iOS developer, I also recommend seeing the code, it's not complex and can easily be ported to another language.

So, what is a State Pattern using POP? Let's look (here comes a long gist, sorry 😅):

A lot of stuff going on. Also, can be seen as over-engineering or something like that. But remember, this is for complex cases where there is a lot of states or also complex behaviour and you want very clear separation of responsibilities (anyone think of the S of SOLID?). For instance, in a game like Super Mario Bros. that I referred before, it would really help, since in each state you can set the player animation, physics and etc.

For those who don't understand everything going on, basically the State Machine is a Value Type and to alter it's contents in some method, you need to specify that is mutating . I use metatypes to decide which state I should enter. Metatypes are types that describe types of the language (confusing?). Let's take the example of a String : we all know what a string is, but imagine that we want to reference the type String and not it's contents, how would we do that? And that's when enter metatypes. You can refer to the type itself and not the contents that holds. It's really useful in situations like the above that the type already know what will do, you just need to retrieve the type you want and it will do what needs to be done.

Likewise, this State Machine is resilient to mistakes like in the last line (trying to enter a State that is not mapped). But you can modify and handle each case in any way you want (make it crash, display an error…). And you don't really need a State Machine, as you can see, it's a little advanced (handling metatypes can be hard for beginners). The alternative would be for you to hold each state on it's own variable or "holder" (I don't know if anyone would make a type for something like this 🤔, but you can expect anything from people).

I think that another example is not necessary for when to use a state machine, and besides in a more complex case, everything that I mentioned earlier can be used (like, you could add a loading view in your application when it’s in loading state and remove it when finishing the loading). And if it isn’t clear until know, you can avoid a lot of duplication because each state is self-contained.

So, after a long way talking about state machine and managing states, you now can use in many places and try to avoid some common pitfalls that people do when handling states. Each case has its needs and don't jump into something complex when you usually just need few states. It's easy to want to use something more complex but you just have a case like a switch. Don't abuse!

Just reinforcing something that I said in the beginning: yes, state machines are applied everywhere. AI, circuit boards, mathematical models, physics models, computer graphics (OpenGL works like a State Machine and others graphics APIs also use state concepts) and etc. This is just a scratch at teaching it's use in common programming, but as you dive into more complex problems, state machines can be really handy and useful.

I hope that after reading this, at least some of you will try to use states and manage better your application. Let me know if something is not clear or any other topics related.

If you are curious about state pattern in different programming paradigms here is a example in C and here in Haskell language. I find important to show in different paradigms to see that even with my code being in Swift it's not limited to the language or the paradigms that Swift implements.

--

--

Ricardo Rachaus
The Arcane Programmer

Gosto de escrever estórias e pretendo começar a escrever artigos relacionados a programação.